Search code examples
pythonpython-3.xpyqtpyqt5qfiledialog

'Save' and 'Save as' using QFileDialog.getSaveFile()


I working on a notepad clone. While saving a file is a straight forward, I am a bit stuck with the following issue:

QFileDialog.getSavefile() always prompt user to save file even if the the file was saved earlier and no changes have been made to it. How do I make my notepad smart to ignore save command if no changes have been made to the file? Just like the real notepad in windows.

Here is the extract of my save function from my project:

def save_file(self):
    """
    Saves the user's work.
    :return: True if the saving is successful. False if otherwise
    """
    options = QFileDialog.Options()
    options |= QFileDialog.DontUseNativeDialog
    file_name, _ = QFileDialog.getSaveFileName(self,"Save File","","All Files(*);;Text Files(*.txt)",options = options)
    if file_name:
        f = open(file_name, 'w')
        text = self.ui.textEdit.toPlainText()
        f.write(text)
        self.setWindowTitle(str(os.path.basename(file_name)) + " - Notepad Alpha")
        f.close()
        return True
    else:
        return False

Solution

  • Your question is not related to the QFileDialog, but to your program logic.

    You can use a variable to store the current file name, leaving it to None at the beginning. Then create two distinct functions, one for "save" (which will try to save the file if the file name is set), and one for "save as" (which will always show the file dialog.

    Also, consider that you can use the windowModified property to set/know (and let the user know) if the document requires saving:

    class Notepad(QtWidgets.QMainWindow):
        def __init__(self):
            super().__init__()
            self.setWindowTitle('New document - Notepad Alpha[*]')
            fileMenu = self.menuBar().addMenu('File')
            saveAction = fileMenu.addAction('Save')
            saveAction.triggered.connect(self.save)
            saveAsAction = fileMenu.addAction('Save as...')
            saveAsAction.triggered.connect(self.saveAs)
    
            self.editor = QtWidgets.QTextEdit()
            self.setCentralWidget(self.editor)
            self.editor.document().modificationChanged.connect(self.setWindowModified)
            self.fileName = None
    
        def save(self):
            if not self.isWindowModified():
                return
            if not self.fileName:
                self.saveAs()
            else:
                with open(self.fileName, 'w') as f:
                    f.write(self.editor.toPlainText())
    
        def saveAs(self):
            if not self.isWindowModified():
                return
            options = QtWidgets.QFileDialog.Options()
            options |= QtWidgets.QFileDialog.DontUseNativeDialog
            fileName, _ = QtWidgets.QFileDialog.getSaveFileName(self, 
                "Save File", "", "All Files(*);;Text Files(*.txt)", options = options)
            if fileName:
                with open(fileName, 'w') as f:
                    f.write(self.editor.toPlainText())
                self.fileName = fileName
                self.setWindowTitle(str(os.path.basename(fileName)) + " - Notepad Alpha[*]")