From 1d9c4430f727eff558d74b2cd81fe3d4f8e6f19a Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Thu, 17 Dec 2020 18:50:37 +0100 Subject: [PATCH 1/4] Correct placeholder text in Build Novel Project tool --- nw/gui/build.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nw/gui/build.py b/nw/gui/build.py index bc820f16..7902996d 100644 --- a/nw/gui/build.py +++ b/nw/gui/build.py @@ -1114,8 +1114,8 @@ class GuiBuildNovelDocView(QTextBrowser): self.qDocument.setDocumentMargin(self.mainConf.getTextMargin()) self.setPlaceholderText( "This area will show the content of the document to be " - "exported or printed. Press the \"Build Novel Project\" " - "button to generate content." + "exported or printed. Press the \"Build Project\" button " + "to generate content." ) theFont = QFont() From d9cccc87523a32fefa136e9288fcb9925e5b381c Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Thu, 17 Dec 2020 18:52:56 +0100 Subject: [PATCH 2/4] The Writing Stats tool should not pop an error message if there is no satistics log --- nw/gui/writingstats.py | 6 +++++- tests/test_gui_writingstats.py | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/nw/gui/writingstats.py b/nw/gui/writingstats.py index 3b5bc5c5..18abe3ff 100644 --- a/nw/gui/writingstats.py +++ b/nw/gui/writingstats.py @@ -403,8 +403,12 @@ class GuiWritingStats(QDialog): ttNotes = 0 ttTime = 0 + logFile = os.path.join(self.theProject.projMeta, nwFiles.SESS_STATS) + if not os.path.isfile(logFile): + logger.info("This project has no writing stats logfile") + return False + try: - logFile = os.path.join(self.theProject.projMeta, nwFiles.SESS_STATS) with open(logFile, mode="r", encoding="utf8") as inFile: for inLine in inFile: if inLine.startswith("#"): diff --git a/tests/test_gui_writingstats.py b/tests/test_gui_writingstats.py index 62f8af9f..038b3dcf 100644 --- a/tests/test_gui_writingstats.py +++ b/tests/test_gui_writingstats.py @@ -203,6 +203,7 @@ def testGuiWritingStats_Dialog(qtbot, monkeypatch, nwGUI, fncDir, fncProj): # IOError # ======= monkeypatch.setattr("builtins.open", causeOSError) + assert not sessLog._loadLogFile() assert not sessLog._saveData(sessLog.FMT_CSV) # qtbot.stopForInteraction() From 885c62990a05e41f0c5a99b60f2f4fb8d8d7f311 Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Fri, 18 Dec 2020 21:57:46 +0100 Subject: [PATCH 3/4] Add move item up and down to the project tree context menu --- nw/gui/projtree.py | 54 +++++++++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 20 deletions(-) diff --git a/nw/gui/projtree.py b/nw/gui/projtree.py index 3e91cc2d..5dfc7228 100644 --- a/nw/gui/projtree.py +++ b/nw/gui/projtree.py @@ -994,6 +994,10 @@ class GuiProjectTreeMenu(QMenu): self.theTree = theTree self.theItem = None + self.editItem = QAction("Edit Project Item", self) + self.editItem.triggered.connect(self._doEditItem) + self.addAction(self.editItem) + self.openItem = QAction("Open Document", self) self.openItem.triggered.connect(self._doOpenItem) self.addAction(self.openItem) @@ -1002,10 +1006,6 @@ class GuiProjectTreeMenu(QMenu): self.viewItem.triggered.connect(self._doViewItem) self.addAction(self.viewItem) - self.editItem = QAction("Edit Project Item", self) - self.editItem.triggered.connect(self._doEditItem) - self.addAction(self.editItem) - self.toggleExp = QAction("Toggle Included Flag", self) self.toggleExp.triggered.connect(self._doToggleExported) self.addAction(self.toggleExp) @@ -1026,6 +1026,14 @@ class GuiProjectTreeMenu(QMenu): self.emptyTrash.triggered.connect(self._doEmptyTrash) self.addAction(self.emptyTrash) + self.moveUp = QAction("Move Item Up", self) + self.moveUp.triggered.connect(self._doMoveUp) + self.addAction(self.moveUp) + + self.moveDown = QAction("Move Item Down", self) + self.moveDown.triggered.connect(self._doMoveDown) + self.addAction(self.moveDown) + return def filterActions(self, theItem): @@ -1045,23 +1053,17 @@ class GuiProjectTreeMenu(QMenu): isFile = theItem.itemType == nwItemType.FILE isOrph = isFile and theItem.itemParent is None - showOpen = isFile - showView = isFile - showEdit = not isTrash and not isOrph - showExport = isFile - showNewFile = not (isTrash or inTrash or isOrph) - showNewFolder = not (isTrash or inTrash or isOrph) - showDelete = not isTrash - showEmpty = isTrash + allowEdit = not (isTrash or isOrph) + allowNew = not (isTrash or inTrash or isOrph) - self.openItem.setVisible(showOpen) - self.viewItem.setVisible(showView) - self.editItem.setVisible(showEdit) - self.toggleExp.setVisible(showExport) - self.newFile.setVisible(showNewFile) - self.newFolder.setVisible(showNewFolder) - self.deleteItem.setVisible(showDelete) - self.emptyTrash.setVisible(showEmpty) + self.editItem.setVisible(allowEdit) + self.openItem.setVisible(isFile) + self.viewItem.setVisible(isFile) + self.toggleExp.setVisible(isFile) + self.newFile.setVisible(allowNew) + self.newFolder.setVisible(allowNew) + self.deleteItem.setVisible(not isTrash) + self.emptyTrash.setVisible(isTrash) return True @@ -1125,4 +1127,16 @@ class GuiProjectTreeMenu(QMenu): self.theTree.emptyTrash() return + def _doMoveUp(self): + """Forward the move item call to the project tree. + """ + self.theTree.moveTreeItem(-1) + return + + def _doMoveDown(self): + """Forward the move item call to the project tree. + """ + self.theTree.moveTreeItem(1) + return + # END Class GuiProjectTreeMenu From 8d71ee30d4c679d659d837dac2a81a6737391b25 Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Sat, 19 Dec 2020 20:21:43 +0100 Subject: [PATCH 4/4] Use the main gui askQuestion function for yes/no dialogs --- nw/core/project.py | 8 ++++---- nw/gui/docsplit.py | 17 +++++++---------- nw/gui/projload.py | 9 ++++----- nw/gui/projtree.py | 26 +++++++++++--------------- nw/guimain.py | 26 +++++++++++--------------- 5 files changed, 37 insertions(+), 49 deletions(-) diff --git a/nw/core/project.py b/nw/core/project.py index 1a834d73..8bfbaa74 100644 --- a/nw/core/project.py +++ b/nw/core/project.py @@ -471,14 +471,14 @@ class NWProject(): # read the file. Introduced in version 0.10. if fileVersion == "1.0": - msgRes = self.theParent.askQuestion("Old Project Version", ( + msgYes = self.theParent.askQuestion("Old Project Version", ( "The project file and data is created by a novelWriter version " "lower than 0.7. Do you want to upgrade the project to the " "most recent format?

Note that after the upgrade, you " "cannot open the project with an older version of novelWriter " "any more, so make sure you have a recent backup." )) - if not msgRes: + if not msgYes: self.clearProject() return False @@ -497,7 +497,7 @@ class NWProject(): # ========================= if int(hexVersion, 16) > int(nw.__hexversion__, 16): - msgRes = self.theParent.askQuestion("Version Conflict", ( + msgYes = self.theParent.askQuestion("Version Conflict", ( "This project was saved by a newer version of novelWriter, version %s. " "This is version %s. If you continue to open the project, some attributes " "and settings may not be preserved, but the overall project should be fine. " @@ -505,7 +505,7 @@ class NWProject(): ) % ( appVersion, nw.__version__ )) - if not msgRes: + if not msgYes: self.clearProject() return False diff --git a/nw/gui/docsplit.py b/nw/gui/docsplit.py index 48ea3e9e..8299d14e 100644 --- a/nw/gui/docsplit.py +++ b/nw/gui/docsplit.py @@ -31,7 +31,7 @@ import logging from PyQt5.QtCore import Qt from PyQt5.QtWidgets import ( QDialog, QVBoxLayout, QComboBox, QListWidget, QAbstractItemView, - QListWidgetItem, QDialogButtonBox, QLabel, QMessageBox + QListWidgetItem, QDialogButtonBox, QLabel ) from nw.core import NWDoc @@ -163,15 +163,12 @@ class GuiDocSplit(QDialog): ), nwAlert.ERROR) return - msgBox = QMessageBox() - msgRes = msgBox.question( - self, "Split Document", ( - "The document will be split into %d file(s) in a new folder. " - "The original document will remain intact.

" - "Continue with the splitting process?" - ) % nFiles - ) - if msgRes != QMessageBox.Yes: + msgYes = self.theParent.askQuestion("Split Document", ( + "The document will be split into %d file(s) in a new folder. " + "The original document will remain intact.

" + "Continue with the splitting process?" + ) % nFiles) + if not msgYes: return # Create the folder diff --git a/nw/gui/projload.py b/nw/gui/projload.py index 15fe2825..5c8736ea 100644 --- a/nw/gui/projload.py +++ b/nw/gui/projload.py @@ -36,7 +36,7 @@ from PyQt5.QtGui import QKeySequence from PyQt5.QtWidgets import ( QDialog, QHBoxLayout, QVBoxLayout, QGridLayout, QPushButton, QTreeWidget, QAbstractItemView, QTreeWidgetItem, QDialogButtonBox, QLabel, QShortcut, - QFileDialog, QLineEdit, QMessageBox + QFileDialog, QLineEdit ) from nw.common import formatInt @@ -218,12 +218,11 @@ class GuiProjectLoad(QDialog): """ selList = self.listBox.selectedItems() if selList: - msgBox = QMessageBox() - msgRes = msgBox.question( - self, "Remove Entry", + msgYes = self.theParent.askQuestion( + "Remove Entry", "Remove the selected entry from the recent projects list?" ) - if msgRes == QMessageBox.Yes: + if msgYes: self.mainConf.removeFromRecentCache( selList[0].data(self.C_NAME, Qt.UserRole) ) diff --git a/nw/gui/projtree.py b/nw/gui/projtree.py index 5dfc7228..2c52c4cb 100644 --- a/nw/gui/projtree.py +++ b/nw/gui/projtree.py @@ -32,8 +32,7 @@ import logging from PyQt5.QtCore import Qt, QSize from PyQt5.QtGui import QIcon from PyQt5.QtWidgets import ( - qApp, QTreeWidget, QTreeWidgetItem, QAbstractItemView, QMessageBox, - QMenu, QAction + qApp, QTreeWidget, QTreeWidgetItem, QAbstractItemView, QMenu, QAction ) from nw.core import NWDoc @@ -391,13 +390,12 @@ class GuiProjectTree(QTreeWidget): self.makeAlert("The Trash folder is already empty.", nwAlert.INFO) return False - msgBox = QMessageBox() - msgRes = msgBox.question( - self, "Empty Trash", "Permanently delete %d file%s from Trash?" % ( + msgYes = self.theParent.askQuestion( + "Empty Trash", "Permanently delete %d file%s from Trash?" % ( nTrash, "s" if nTrash > 1 else "" ) ) - if msgRes != QMessageBox.Yes: + if not msgYes: return False logger.verbose("Deleting %d files from Trash" % nTrash) @@ -449,11 +447,10 @@ class GuiProjectTree(QTreeWidget): # user if they want to permanently delete the file. doPermanent = False if not alreadyAsked: - msgBox = QMessageBox() - msgRes = msgBox.question( - self, "Delete File", "Permanently delete file '%s'?" % nwItemS.itemName + msgYes = self.theParent.askQuestion( + "Delete File", "Permanently delete file '%s'?" % nwItemS.itemName ) - if msgRes == QMessageBox.Yes: + if msgYes: doPermanent = True else: doPermanent = True @@ -478,11 +475,10 @@ class GuiProjectTree(QTreeWidget): # move it there. doTrash = False if askForTrash: - msgBox = QMessageBox() - msgRes = msgBox.question( - self, "Delete File", "Move file '%s' to Trash?" % nwItemS.itemName + msgYes = self.theParent.askQuestion( + "Delete File", "Move file '%s' to Trash?" % nwItemS.itemName ) - if msgRes == QMessageBox.Yes: + if msgYes: doTrash = True else: doTrash = True @@ -1122,7 +1118,7 @@ class GuiProjectTreeMenu(QMenu): return def _doEmptyTrash(self): - """Forward the delete item call to the project tree. + """Forward the empty trash call to the project tree. """ self.theTree.emptyTrash() return diff --git a/nw/guimain.py b/nw/guimain.py index 16965057..4361ae8f 100644 --- a/nw/guimain.py +++ b/nw/guimain.py @@ -320,12 +320,11 @@ class GuiMain(QMainWindow): return True if not isYes: - msgBox = QMessageBox() - msgRes = msgBox.question( - self, "Close Project", + msgYes = self.askQuestion( + "Close Project", "Close the current project?
Changes are saved automatically." ) - if msgRes != QMessageBox.Yes: + if not msgYes: return False if self.docEditor.docChanged: @@ -337,11 +336,10 @@ class GuiMain(QMainWindow): if self.theProject.doBackup and self.mainConf.backupOnClose: doBackup = True if self.mainConf.askBeforeBackup: - msgBox = QMessageBox() - msgRes = msgBox.question( - self, "Backup Project", "Backup the current project?" + msgYes = self.askQuestion( + "Backup Project", "Backup the current project?" ) - if msgRes != QMessageBox.Yes: + if not msgYes: doBackup = False if doBackup: self.theProject.zipIt(False) @@ -640,12 +638,11 @@ class GuiMain(QMainWindow): return False if not self.docEditor.isEmpty(): - msgBox = QMessageBox() - msgRes = msgBox.question(self, "Import Document", ( + msgYes = self.askQuestion("Import Document", ( "Importing the file will overwrite the current content of the document. " "Do you want to proceed?" )) - if msgRes != QMessageBox.Yes: + if not msgYes: return False self.docEditor.replaceText(theText) @@ -1007,12 +1004,11 @@ class GuiMain(QMainWindow): """Save everything, and close novelWriter. """ if self.hasProject: - msgBox = QMessageBox() - msgRes = msgBox.question( - self, "Exit", + msgYes = self.askQuestion( + "Exit", "Do you want to exit novelWriter?
Changes are saved automatically." ) - if msgRes != QMessageBox.Yes: + if not msgYes: return False logger.info("Exiting novelWriter")