From cde0d6dff5c78db28dbf3c4b7b2a1e8b76beca08 Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Sun, 25 Oct 2020 14:14:40 +0100 Subject: [PATCH 1/9] Only run word counter when a document is open --- nw/gui/doceditor.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/nw/gui/doceditor.py b/nw/gui/doceditor.py index 09792041..4546d717 100644 --- a/nw/gui/doceditor.py +++ b/nw/gui/doceditor.py @@ -1004,6 +1004,9 @@ class GuiDocEditor(QTextEdit): """Decide whether to run the word counter, or not due to inactivity. """ + if self.theHandle is None: + return + if self.wCounter.isRunning(): logger.verbose("Word counter is busy") return From 02b79248ec192c351017d372490c0730833bea16 Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Sun, 25 Oct 2020 14:22:44 +0100 Subject: [PATCH 2/9] Make build panels non-collapsible and fix spacing values --- nw/gui/build.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/nw/gui/build.py b/nw/gui/build.py index 4a8f8aad..fde18f9e 100644 --- a/nw/gui/build.py +++ b/nw/gui/build.py @@ -422,7 +422,7 @@ class GuiBuildNovel(QDialog): self.buttonBox.addWidget(self.btnSave) self.buttonBox.addWidget(self.btnPrint) self.buttonBox.addWidget(self.btnClose) - self.buttonBox.setSpacing(4) + self.buttonBox.setSpacing(self.mainConf.pxInt(4)) # Assemble GUI # ============ @@ -464,12 +464,13 @@ class GuiBuildNovel(QDialog): self.toolsArea.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded) # Tools and Buttons Layout + tSp = self.mainConf.pxInt(8) self.innerBox = QVBoxLayout() self.innerBox.addWidget(self.toolsArea) - self.innerBox.addSpacing(8) + self.innerBox.addSpacing(tSp) self.innerBox.addWidget(self.buildProgress) self.innerBox.addWidget(self.buildNovel) - self.innerBox.addSpacing(8) + self.innerBox.addSpacing(tSp) self.innerBox.addLayout(self.buttonBox) # Tools and Buttons Wrapper Widget @@ -482,6 +483,12 @@ class GuiBuildNovel(QDialog): self.mainSplit.addWidget(self.docView) self.mainSplit.setSizes([boxWidth, docWidth]) + self.idxSettings = self.mainSplit.indexOf(self.innerWidget) + self.idxDocument = self.mainSplit.indexOf(self.docView) + + self.mainSplit.setCollapsible(self.idxSettings, False) + self.mainSplit.setCollapsible(self.idxDocument, False) + # Outer Layout self.outerBox = QHBoxLayout() self.outerBox.addWidget(self.mainSplit) From 42700a23251ca6deaea766a3c0b51c693bd92b1c Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Sun, 25 Oct 2020 14:31:23 +0100 Subject: [PATCH 3/9] More sensible default values for tree column widths --- nw/config.py | 6 +++--- tests/reference/novelwriter.conf | 6 +++--- tests/test_config.py | 12 ++++++------ 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/nw/config.py b/nw/config.py index a82c133b..8fc681e0 100644 --- a/nw/config.py +++ b/nw/config.py @@ -93,9 +93,9 @@ class Config: self.guiScale = 1.0 # Set automatically by Theme class ## Sizes - self.winGeometry = [1100, 650] - self.treeColWidth = [120, 30, 50] - self.projColWidth = [140, 55, 140] + self.winGeometry = [1200, 650] + self.treeColWidth = [200, 50, 30] + self.projColWidth = [200, 60, 140] self.mainPanePos = [300, 800] self.docPanePos = [400, 400] self.viewPanePos = [500, 150] diff --git a/tests/reference/novelwriter.conf b/tests/reference/novelwriter.conf index aef7459f..99b01f75 100644 --- a/tests/reference/novelwriter.conf +++ b/tests/reference/novelwriter.conf @@ -8,9 +8,9 @@ guifont = guifontsize = 11 [Sizes] -geometry = 1100, 650 -treecols = 120, 30, 50 -projcols = 140, 55, 140 +geometry = 1200, 650 +treecols = 200, 50, 30 +projcols = 200, 60, 140 mainpane = 300, 800 docpane = 400, 400 viewpane = 500, 150 diff --git a/tests/test_config.py b/tests/test_config.py index 8911a69d..f9ce767b 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -44,11 +44,11 @@ def testConfigSetWinSize(tmpConf, nwTemp, nwRef): tmpConf.guiScale = 1.0 assert tmpConf.confPath == nwTemp - assert tmpConf.setWinSize(1105, 655) + assert tmpConf.setWinSize(1205, 655) assert not tmpConf.confChanged assert tmpConf.setWinSize(70, 70) assert tmpConf.confChanged - assert tmpConf.setWinSize(1100, 650) + assert tmpConf.setWinSize(1200, 650) assert tmpConf.saveConfig() assert cmpFiles(testConf, refConf, [2]) @@ -62,13 +62,13 @@ def testConfigSetTreeColWidths(tmpConf, nwTemp, nwRef): assert tmpConf.confPath == nwTemp tmpConf.guiScale = 1.0 - assert tmpConf.setTreeColWidths([10, 20, 30]) - assert tmpConf.treeColWidth == [10, 20, 30] - assert tmpConf.setTreeColWidths([120, 30, 50]) + assert tmpConf.setTreeColWidths([10, 20, 25]) + assert tmpConf.treeColWidth == [10, 20, 25] + assert tmpConf.setTreeColWidths([200, 50, 30]) assert tmpConf.setProjColWidths([10, 20, 30]) assert tmpConf.projColWidth == [10, 20, 30] - assert tmpConf.setProjColWidths([140, 55, 140]) + assert tmpConf.setProjColWidths([200, 60, 140]) assert tmpConf.confChanged assert tmpConf.saveConfig() From 6e029f56a4a2f3459acd3691d30464f93339df0f Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Sun, 25 Oct 2020 14:51:15 +0100 Subject: [PATCH 4/9] Remove line endings from logged ignored doc meta lines --- nw/core/document.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nw/core/document.py b/nw/core/document.py index 2e22e389..2597eac8 100644 --- a/nw/core/document.py +++ b/nw/core/document.py @@ -251,7 +251,7 @@ class NWDoc(): self._docMeta["layout"] = nwItemLayout[metaBits[1]] else: - logger.debug("Ignoring meta data: '%s'" % metaLine) + logger.debug("Ignoring meta data: '%s'" % metaLine.strip()) return From 91e2092674b935f56a38787fea2e85b856b60494 Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Tue, 27 Oct 2020 20:21:39 +0100 Subject: [PATCH 5/9] Move the spell check class constants to the nwConst class --- nw/config.py | 8 ++++---- nw/constants/constants.py | 6 ++++++ nw/core/spellcheck.py | 28 ++++++++++++---------------- nw/gui/doceditor.py | 4 ++-- nw/gui/preferences.py | 11 ++++++----- tests/test_project.py | 4 ++-- 6 files changed, 32 insertions(+), 29 deletions(-) diff --git a/nw/config.py b/nw/config.py index 8fc681e0..05345b45 100644 --- a/nw/config.py +++ b/nw/config.py @@ -37,7 +37,7 @@ from shutil import which from PyQt5.Qt import PYQT_VERSION_STR from PyQt5.QtCore import QT_VERSION_STR, QStandardPaths, QSysInfo -from nw.constants import nwFiles, nwUnicode +from nw.constants import nwConst, nwFiles, nwUnicode from nw.common import splitVersionNumber, formatTimeStamp logger = logging.getLogger(__name__) @@ -88,7 +88,7 @@ class Config: self.guiIcons = "typicons_colour_light" self.guiDark = False # Load icons for dark backgrounds, if available self.guiLang = "en" # Hardcoded for now since the GUI is only in English - self.guiFont = "" # Defaults to system defualt font + self.guiFont = "" # Defaults to system default font self.guiFontSize = 11 self.guiScale = 1.0 # Set automatically by Theme class @@ -284,7 +284,7 @@ class Config: logger.verbose("App path: %s" % self.appPath) logger.verbose("Last path: %s" % self.lastPath) - # If config folder does not exist, make it. + # If config folder does not exist, create it. # This assumes that the os config folder itself exists. if not os.path.isdir(self.confPath): try: @@ -327,7 +327,7 @@ class Config: self._checkOptionalPackages() if self.spellTool is None: - self.spellTool = "internal" + self.spellTool = nwConst.SP_INTERNAL if self.spellLanguage is None: self.spellLanguage = "en" diff --git a/nw/constants/constants.py b/nw/constants/constants.py index e7549bb4..f2e97cf5 100644 --- a/nw/constants/constants.py +++ b/nw/constants/constants.py @@ -29,14 +29,20 @@ from nw.constants.enum import nwItemClass, nwItemLayout, nwOutline class nwConst(): + # Date and Time Formats tStampFmt = "%Y-%m-%d %H:%M:%S" # Default format fStampFmt = "%Y-%m-%d %H.%M.%S" # FileName safe format dStampFmt = "%Y-%m-%d" # Date only format + # Various Hard Limits maxDepth = 30 # Maximum folder depth of a project maxDocSize = 5000000 # Maxium size of a single document maxBuildSize = 10000000 # Maxium size of a project build + # Spell Check Providers + SP_INTERNAL = "internal" + SP_ENCHANT = "enchant" + # END Class nwConst class nwRegEx(): diff --git a/nw/core/spellcheck.py b/nw/core/spellcheck.py index 7223c616..b2f92a96 100644 --- a/nw/core/spellcheck.py +++ b/nw/core/spellcheck.py @@ -31,7 +31,7 @@ import os from difflib import get_close_matches -from nw.constants import isoLanguage +from nw.constants import nwConst, isoLanguage logger = logging.getLogger(__name__) @@ -41,11 +41,8 @@ logger = logging.getLogger(__name__) class NWSpellCheck(): - SP_INTERNAL = "internal" - SP_ENCHANT = "enchant" - theDict = None - PROJW = [] + projDict = [] def __init__(self): self.mainConf = nw.CONFIG @@ -71,9 +68,9 @@ class NWSpellCheck(): def addWord(self, newWord): """Add a word to the project dictionary. """ - if self.projectDict is not None and newWord not in self.PROJW: + if self.projectDict is not None and newWord not in self.projDict: newWord = newWord.strip() - self.PROJW.append(newWord) + self.projDict.append(newWord) try: with open(self.projectDict, mode="a+", encoding="utf-8") as outFile: outFile.write("%s\n" % newWord) @@ -110,7 +107,7 @@ class NWSpellCheck(): """Read the content of the project dictionary, and add it to the lookup lists. """ - self.PROJW = [] + self.projDict = [] if projectDict is not None: self.projectDict = projectDict if not os.path.isfile(projectDict): @@ -120,9 +117,9 @@ class NWSpellCheck(): with open(projectDict, mode="r", encoding="utf-8") as wordsFile: for theLine in wordsFile: theLine = theLine.strip() - if len(theLine) > 0 and theLine not in self.PROJW: - self.PROJW.append(theLine) - logger.debug("Project word list contains %d words" % len(self.PROJW)) + if len(theLine) > 0 and theLine not in self.projDict: + self.projDict.append(theLine) + logger.debug("Project word list contains %d words" % len(self.projDict)) except Exception as e: logger.error("Failed to load project word list") logger.error(str(e)) @@ -157,7 +154,7 @@ class NWSpellEnchant(NWSpellCheck): self.spellLanguage = None self._readProjectDictionary(projectDict) - for pWord in self.PROJW: + for pWord in self.projDict: self.theDict.add_to_session(pWord) return @@ -236,7 +233,6 @@ class NWSpellSimple(NWSpellCheck): when no other is available. This method is fairly slow compared to other implementations. """ - WORDS = [] def __init__(self): @@ -266,7 +262,7 @@ class NWSpellSimple(NWSpellCheck): self.spellLanguage = None self._readProjectDictionary(projectDict) - for pWord in self.PROJW: + for pWord in self.projDict: if pWord not in self.WORDS: self.WORDS.append(pWord) @@ -324,7 +320,7 @@ class NWSpellSimple(NWSpellCheck): if theBits[1] != ".dict": continue - spName = "%s [internal]" % self.expandLanguage(theBits[0]) + spName = "%s [%s]" % (self.expandLanguage(theBits[0]), nwConst.SP_INTERNAL) retList.append((theBits[0], spName)) return retList @@ -333,6 +329,6 @@ class NWSpellSimple(NWSpellCheck): """Return the tag and provider of the currently loaded dictionary. """ - return self.theLang, "internal" + return self.theLang, nwConst.SP_INTERNAL # END Class NWSpellSimple diff --git a/nw/gui/doceditor.py b/nw/gui/doceditor.py index 4546d717..f45e569d 100644 --- a/nw/gui/doceditor.py +++ b/nw/gui/doceditor.py @@ -50,7 +50,7 @@ from PyQt5.QtWidgets import ( QFrame ) -from nw.core import NWDoc, NWSpellCheck, NWSpellSimple, countWords +from nw.core import NWDoc, NWSpellSimple, countWords from nw.gui.dochighlight import GuiDocHighlighter from nw.common import transferCase from nw.constants import ( @@ -1614,7 +1614,7 @@ class GuiDocEditor(QTextEdit): """Create the spell checking object based on the spellTool setting in config. """ - if self.mainConf.spellTool == NWSpellCheck.SP_ENCHANT: + if self.mainConf.spellTool == nwConst.SP_ENCHANT: from nw.core.spellcheck import NWSpellEnchant self.theDict = NWSpellEnchant() else: diff --git a/nw/gui/preferences.py b/nw/gui/preferences.py index 945e35f6..2bb22bde 100644 --- a/nw/gui/preferences.py +++ b/nw/gui/preferences.py @@ -37,7 +37,8 @@ from PyQt5.QtWidgets import ( ) from nw.gui.custom import QSwitch, QConfigLayout, PagedDialog, QuotesDialog -from nw.core import NWSpellCheck, NWSpellSimple, NWSpellEnchant +from nw.core import NWSpellSimple, NWSpellEnchant +from nw.constants import nwConst logger = logging.getLogger(__name__) @@ -703,11 +704,11 @@ class GuiConfigEditEditingTab(QWidget): ## Spell Check Provider and Language self.spellLangList = QComboBox(self) self.spellToolList = QComboBox(self) - self.spellToolList.addItem("Internal (difflib)", NWSpellCheck.SP_INTERNAL) - self.spellToolList.addItem("Spell Enchant (pyenchant)", NWSpellCheck.SP_ENCHANT) + self.spellToolList.addItem("Internal (difflib)", nwConst.SP_INTERNAL) + self.spellToolList.addItem("Spell Enchant (pyenchant)", nwConst.SP_ENCHANT) theModel = self.spellToolList.model() - idEnchant = self.spellToolList.findData(NWSpellCheck.SP_ENCHANT) + idEnchant = self.spellToolList.findData(nwConst.SP_ENCHANT) theModel.item(idEnchant).setEnabled(self.mainConf.hasEnchant) self.spellToolList.currentIndexChanged.connect(self._doUpdateSpellTool) @@ -814,7 +815,7 @@ class GuiConfigEditEditingTab(QWidget): preserve the language choice, if the language exists in the updated list. """ - if spellTool == NWSpellCheck.SP_ENCHANT: + if spellTool == nwConst.SP_ENCHANT: theDict = NWSpellEnchant() else: theDict = NWSpellSimple() diff --git a/tests/test_project.py b/tests/test_project.py index 9be85a67..b8df3c0e 100644 --- a/tests/test_project.py +++ b/tests/test_project.py @@ -13,7 +13,7 @@ from nwtools import cmpFiles from nw.core.project import NWProject from nw.core.document import NWDoc from nw.core.spellcheck import NWSpellEnchant, NWSpellSimple -from nw.constants import nwItemClass, nwItemType, nwItemLayout, nwFiles +from nw.constants import nwConst, nwItemClass, nwItemType, nwItemLayout, nwFiles @pytest.mark.project def testProjectNewOpenSave(nwFuncTemp, nwTempProj, nwRef, nwTemp, nwDummy): @@ -405,7 +405,7 @@ def testSpellSimple(nwTemp, nwConf): aTag, aName = spChk.describeDict() assert aTag == "en" - assert aName == "internal" + assert aName == nwConst.SP_INTERNAL @pytest.mark.project def testProjectOptions(nwDummy, nwLipsum): From 8e95728e20b769d2095c767925be16a0742e4bee Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Tue, 27 Oct 2020 20:30:11 +0100 Subject: [PATCH 6/9] Move the keyword maps into the nwKeyWords constants class where the keywords are defined --- nw/constants/constants.py | 18 ++++++++++++++++++ nw/core/index.py | 28 +++------------------------- 2 files changed, 21 insertions(+), 25 deletions(-) diff --git a/nw/constants/constants.py b/nw/constants/constants.py index f2e97cf5..0a23e369 100644 --- a/nw/constants/constants.py +++ b/nw/constants/constants.py @@ -80,6 +80,24 @@ class nwKeyWords: ENTITY_KEY = "@entity" CUSTOM_KEY = "@custom" + # Set of Valid Keys + VALID_KEYS = { + TAG_KEY, POV_KEY, CHAR_KEY, PLOT_KEY, TIME_KEY, + WORLD_KEY, OBJECT_KEY, ENTITY_KEY, CUSTOM_KEY + } + + # Map from Keys to Item Class + KEY_CLASS = { + CHAR_KEY : nwItemClass.CHARACTER, + POV_KEY : nwItemClass.CHARACTER, + PLOT_KEY : nwItemClass.PLOT, + TIME_KEY : nwItemClass.TIMELINE, + WORLD_KEY : nwItemClass.WORLD, + OBJECT_KEY : nwItemClass.OBJECT, + ENTITY_KEY : nwItemClass.ENTITY, + CUSTOM_KEY : nwItemClass.CUSTOM, + } + # END Class nwKeyWords class nwLabels(): diff --git a/nw/core/index.py b/nw/core/index.py index 29f80ea9..cb0ac376 100644 --- a/nw/core/index.py +++ b/nw/core/index.py @@ -42,28 +42,6 @@ logger = logging.getLogger(__name__) class NWIndex(): - VALID_KEYS = { - nwKeyWords.TAG_KEY, - nwKeyWords.PLOT_KEY, - nwKeyWords.POV_KEY, - nwKeyWords.CHAR_KEY, - nwKeyWords.WORLD_KEY, - nwKeyWords.TIME_KEY, - nwKeyWords.OBJECT_KEY, - nwKeyWords.ENTITY_KEY, - nwKeyWords.CUSTOM_KEY - } - TAG_CLASS = { - nwKeyWords.CHAR_KEY : nwItemClass.CHARACTER, - nwKeyWords.POV_KEY : nwItemClass.CHARACTER, - nwKeyWords.PLOT_KEY : nwItemClass.PLOT, - nwKeyWords.TIME_KEY : nwItemClass.TIMELINE, - nwKeyWords.WORLD_KEY : nwItemClass.WORLD, - nwKeyWords.OBJECT_KEY : nwItemClass.OBJECT, - nwKeyWords.ENTITY_KEY : nwItemClass.ENTITY, - nwKeyWords.CUSTOM_KEY : nwItemClass.CUSTOM, - } - def __init__(self, theProject, theParent): # Internal @@ -530,7 +508,7 @@ class NWIndex(): return [] # Check that the key is valid - isGood[0] = theBits[0] in self.VALID_KEYS + isGood[0] = theBits[0] in nwKeyWords.VALID_KEYS if not isGood[0] or nBits == 1: return isGood @@ -550,7 +528,7 @@ class NWIndex(): # If we're still here, we better check that the references exist for n in range(1, nBits): if theBits[n] in self.tagIndex: - isGood[n] = self.TAG_CLASS[theBits[0]].name == self.tagIndex[theBits[n]][2] + isGood[n] = nwKeyWords.KEY_CLASS[theBits[0]].name == self.tagIndex[theBits[n]][2] return isGood @@ -608,7 +586,7 @@ class NWIndex(): section. sTitle must be a string. """ theRefs = {} - for tKey in self.TAG_CLASS: + for tKey in nwKeyWords.KEY_CLASS: theRefs[tKey] = [] if tHandle not in self.refIndex: From e2ab9ed6cfc43bc61241bdbfff8e513a045a921e Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Tue, 27 Oct 2020 20:36:04 +0100 Subject: [PATCH 7/9] All constants should be upper case --- nw/common.py | 4 ++-- nw/constants/constants.py | 12 ++++++------ nw/core/tokenizer.py | 2 +- nw/core/tree.py | 4 ++-- nw/gui/build.py | 4 ++-- nw/gui/doceditor.py | 12 ++++++------ nw/gui/docsplit.py | 2 +- nw/gui/projtree.py | 6 +++--- nw/gui/writingstats.py | 8 ++++---- 9 files changed, 27 insertions(+), 27 deletions(-) diff --git a/nw/common.py b/nw/common.py index d5563d16..47e86ff6 100644 --- a/nw/common.py +++ b/nw/common.py @@ -165,9 +165,9 @@ def formatTimeStamp(theTime, fileSafe=False): it to a timestamp string. """ if fileSafe: - return datetime.fromtimestamp(theTime).strftime(nwConst.fStampFmt) + return datetime.fromtimestamp(theTime).strftime(nwConst.FMT_FSTAMP) else: - return datetime.fromtimestamp(theTime).strftime(nwConst.tStampFmt) + return datetime.fromtimestamp(theTime).strftime(nwConst.FMT_TSTAMP) def formatTime(tS): """Format a time in seconds in HH:MM:SS format or d-HH:MM:SS format diff --git a/nw/constants/constants.py b/nw/constants/constants.py index 0a23e369..e237b662 100644 --- a/nw/constants/constants.py +++ b/nw/constants/constants.py @@ -30,14 +30,14 @@ from nw.constants.enum import nwItemClass, nwItemLayout, nwOutline class nwConst(): # Date and Time Formats - tStampFmt = "%Y-%m-%d %H:%M:%S" # Default format - fStampFmt = "%Y-%m-%d %H.%M.%S" # FileName safe format - dStampFmt = "%Y-%m-%d" # Date only format + FMT_TSTAMP = "%Y-%m-%d %H:%M:%S" # Default format + FMT_FSTAMP = "%Y-%m-%d %H.%M.%S" # FileName safe format + FMT_DSTAMP = "%Y-%m-%d" # Date only format # Various Hard Limits - maxDepth = 30 # Maximum folder depth of a project - maxDocSize = 5000000 # Maxium size of a single document - maxBuildSize = 10000000 # Maxium size of a project build + MAX_DEPTH = 30 # Maximum folder depth of a project + MAX_DOCSIZE = 5000000 # Maxium size of a single document + MAX_BUILDSIZE = 10000000 # Maxium size of a project build # Spell Check Providers SP_INTERNAL = "internal" diff --git a/nw/core/tokenizer.py b/nw/core/tokenizer.py index c7b23208..7870493c 100644 --- a/nw/core/tokenizer.py +++ b/nw/core/tokenizer.py @@ -216,7 +216,7 @@ class Tokenizer(): self.theText = theDocument.openDocument(theHandle) docSize = len(self.theText) - if docSize > nwConst.maxDocSize: + if docSize > nwConst.MAX_DOCSIZE: errVal = "Document '%s' is too big (%.2f MB). Skipping." % ( self.theItem.itemName, docSize/1.0e6 ) diff --git a/nw/core/tree.py b/nw/core/tree.py index fc908745..2973d462 100644 --- a/nw/core/tree.py +++ b/nw/core/tree.py @@ -260,7 +260,7 @@ class NWTree(): """ tItem = self.__getitem__(tHandle) if tItem is not None: - for i in range(nwConst.maxDepth + 1): + for i in range(nwConst.MAX_DEPTH + 1): if tItem.itemParent is None: return tItem else: @@ -278,7 +278,7 @@ class NWTree(): tItem = self.__getitem__(tHandle) if tItem is not None: tTree.append(tHandle) - for i in range(nwConst.maxDepth + 1): + for i in range(nwConst.MAX_DEPTH + 1): if tItem.itemParent is None: return tTree else: diff --git a/nw/gui/build.py b/nw/gui/build.py index fde18f9e..bc820f16 100644 --- a/nw/gui/build.py +++ b/nw/gui/build.py @@ -515,7 +515,7 @@ class GuiBuildNovel(QDialog): self.docView.setStyleSheet(self.htmlStyle) htmlSize = sum([len(x) for x in self.htmlText]) - if htmlSize < nwConst.maxBuildSize: + if htmlSize < nwConst.MAX_BUILDSIZE: qApp.processEvents() self.docView.setContent(self.htmlText, self.buildTime) else: @@ -656,7 +656,7 @@ class GuiBuildNovel(QDialog): else: self.docView.setStyleSheet(self.htmlStyle) - if htmlSize < nwConst.maxBuildSize: + if htmlSize < nwConst.MAX_BUILDSIZE: self.docView.setContent(self.htmlText, self.buildTime) self._enableQtSave(True) else: diff --git a/nw/gui/doceditor.py b/nw/gui/doceditor.py index f45e569d..85a3f75d 100644 --- a/nw/gui/doceditor.py +++ b/nw/gui/doceditor.py @@ -284,12 +284,12 @@ class GuiDocEditor(QTextEdit): return False docSize = len(theDoc) - if docSize > nwConst.maxDocSize: + if docSize > nwConst.MAX_DOCSIZE: self.theParent.makeAlert(( "The document you are trying to open is too big. " "The document size is %.2f\u202fMB. " "The maximum size allowed is %.2f\u202fMB." - ) % (docSize/1.0e6, nwConst.maxDocSize/1.0e6), nwAlert.ERROR) + ) % (docSize/1.0e6, nwConst.MAX_DOCSIZE/1.0e6), nwAlert.ERROR) self.clearEditor() return False @@ -361,12 +361,12 @@ class GuiDocEditor(QTextEdit): text. This also clears undo history. """ docSize = len(theText) - if docSize > nwConst.maxDocSize: + if docSize > nwConst.MAX_DOCSIZE: self.theParent.makeAlert(( "The text you are trying to add is too big. " "The text size is %.2f\u202fMB. " "The maximum size allowed is %.2f\u202fMB." - ) % (docSize/1.0e6, nwConst.maxDocSize/1.0e6), nwAlert.ERROR) + ) % (docSize/1.0e6, nwConst.MAX_DOCSIZE/1.0e6), nwAlert.ERROR) return False qApp.setOverrideCursor(QCursor(Qt.WaitCursor)) @@ -859,11 +859,11 @@ class GuiDocEditor(QTextEdit): """ self.lastEdit = time() self.lastFind = None - if self.qDocument.characterCount() > nwConst.maxDocSize: + if self.qDocument.characterCount() > nwConst.MAX_DOCSIZE: self.theParent.makeAlert(( "The document has grown too big and you cannot add more text to it. " "The maximum size of a single novelWriter document is %.2f\u202fMB." - ) % (nwConst.maxDocSize/1.0e6), nwAlert.ERROR) + ) % (nwConst.MAX_DOCSIZE/1.0e6), nwAlert.ERROR) self.undo() return if not self.docChanged: diff --git a/nw/gui/docsplit.py b/nw/gui/docsplit.py index 1a5e9491..48ea3e9e 100644 --- a/nw/gui/docsplit.py +++ b/nw/gui/docsplit.py @@ -155,7 +155,7 @@ class GuiDocSplit(QDialog): # Check that another folder can be created parTree = self.theProject.projTree.getItemPath(srcItem.itemParent) - if len(parTree) >= nwConst.maxDepth - 1: + if len(parTree) >= nwConst.MAX_DEPTH - 1: self.theParent.makeAlert(( "Cannot add new folder for the document split. " "Maximum folder depth has been reached. " diff --git a/nw/gui/projtree.py b/nw/gui/projtree.py index 89e41374..f0d0bca9 100644 --- a/nw/gui/projtree.py +++ b/nw/gui/projtree.py @@ -243,8 +243,8 @@ class GuiProjectTree(QTreeWidget): tHandle = self.theProject.newFile("New File", itemClass, pHandle) elif itemType == nwItemType.FOLDER: - if len(parTree) >= nwConst.maxDepth - 1: - # Folders cannot be deeper than maxDepth - 1, leaving room + if len(parTree) >= nwConst.MAX_DEPTH - 1: + # Folders cannot be deeper than MAX_DEPTH - 1, leaving room # for one more level of files. self.makeAlert(( "Cannot add new folder to this item. " @@ -579,7 +579,7 @@ class GuiProjectTree(QTreeWidget): pCount += int(pItem.child(i).data(self.C_COUNT, Qt.UserRole)) pHandle = pItem.data(self.C_NAME, Qt.UserRole) - if not nDepth > nwConst.maxDepth + 1 and pHandle != "": + if not nDepth > nwConst.MAX_DEPTH + 1 and pHandle != "": self.propagateCount(pHandle, pCount, nDepth+1) return diff --git a/nw/gui/writingstats.py b/nw/gui/writingstats.py index fb10f7a4..b796bbce 100644 --- a/nw/gui/writingstats.py +++ b/nw/gui/writingstats.py @@ -428,10 +428,10 @@ class GuiWritingStats(QDialog): continue dStart = datetime.strptime( - "%s %s" % (inData[0], inData[1]), nwConst.tStampFmt + "%s %s" % (inData[0], inData[1]), nwConst.FMT_TSTAMP ) dEnd = datetime.strptime( - "%s %s" % (inData[2], inData[3]), nwConst.tStampFmt + "%s %s" % (inData[2], inData[3]), nwConst.FMT_TSTAMP ) tDiff = dEnd - dStart @@ -528,9 +528,9 @@ class GuiWritingStats(QDialog): isFirst = False if groupByDay: - sStart = dStart.strftime(nwConst.dStampFmt) + sStart = dStart.strftime(nwConst.FMT_DSTAMP) else: - sStart = dStart.strftime(nwConst.tStampFmt) + sStart = dStart.strftime(nwConst.FMT_TSTAMP) self.filterData.append((dStart, sStart, sDiff, dwTotal, wcNovel, wcNotes)) listMax = min(max(listMax, dwTotal), histMax) From 90ed47b8360b44b1a47472196f3073e2c45a04e5 Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Thu, 29 Oct 2020 13:00:38 +0100 Subject: [PATCH 8/9] Make the setup script a bit more helpful! --- setup.py | 54 ++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 38 insertions(+), 16 deletions(-) diff --git a/setup.py b/setup.py index 1eae8bf7..9fc4bcf6 100755 --- a/setup.py +++ b/setup.py @@ -5,23 +5,20 @@ The main setup script for novelWeiter. It runs the standard setuptool.setup() with all options taken from the setup.cfg file. -In addtion, a few speicalised commands are available: - - * sample: Will build a sample.zip file, which is the way the sample project is - included into distributable packages. - * qthelp: Will build a QtAssistant readable version of the novelWriter - documentation. This should also be a part of distributed packages. It allows - for reading the help offline. Otherwise, the F1 button redirects to the - online documentation only. - * launcher: Will attempt to install novelWriter icons, mime type and create a - launcher for the application. - +In addtion, a few speicalised commands are available. These are +described in the help text in the main section. """ + import os import sys import shutil import subprocess +OS_NONE = 0 +OS_LINUX = 1 +OS_WIN = 2 +OS_DARWIN = 3 + # =============================================================================================== # # Qt Assistant Documentation Builder # =============================================================================================== # @@ -285,6 +282,19 @@ def xdgInstall(): # =============================================================================================== # if __name__ == "__main__": + """Parse command line options and run the commands. + """ + # Detect OS + if sys.platform.startswith("linux"): + hostOS = OS_LINUX + elif sys.platform.startswith("darwin"): + hostOS = OS_DARWIN + elif sys.platform.startswith("win32"): + hostOS = OS_WIN + elif sys.platform.startswith("cygwin"): + hostOS = OS_WIN + else: + hostOS = OS_NONE helpMsg = ( "\n" @@ -292,10 +302,17 @@ if __name__ == "__main__": "======================\n" "This tool provides some additional setup commands for novelWriter.\n" "\n" - "help Print the help message.\n" - "qthelp Build the help documentation for use with the QtAssistant.\n" + "help Print this help message.\n" + "qthelp Build the help documentation for use with the Qt Assistant.\n" + " Run before install to enable in the the installed version.\n" "sample Build the sample project as a zip file.\n" + " Run before install to enable creating sample projects.\n" + "install Installs novelWriter to the system's Python install location.\n" + " Run as root or with sudo for system-wide install, or as\n" + " user for single user install.\n" "xdg-install Install launcher and icons for freedesktop systems.\n" + " Run as root or with sudo for system-wide install, or as\n" + " user for single user install.\n" ) if "help" in sys.argv: @@ -303,6 +320,11 @@ if __name__ == "__main__": print(helpMsg) sys.exit(0) + if "launcher" in sys.argv: + sys.argv.remove("launcher") + print("The 'launcher' option has been replaced by 'xdg-install'.") + sys.exit(1) + if "qthelp" in sys.argv: sys.argv.remove("qthelp") buildQtDocs() @@ -313,11 +335,11 @@ if __name__ == "__main__": if "xdg-install" in sys.argv: sys.argv.remove("xdg-install") - if not sys.platform.startswith("win32"): - xdgInstall() - else: + if hostOS == OS_WIN: print("ERROR: xdg-install cannot be used on Windows") sys.exit(1) + else: + xdgInstall() if len(sys.argv) <= 1: # Nothing more to do From 967037ff893b0cb1e39cfa968dc4fa59ff2fd915 Mon Sep 17 00:00:00 2001 From: "Veronica K. B. Olsen" <1619840+vkbo@users.noreply.github.com> Date: Sat, 31 Oct 2020 17:49:32 +0100 Subject: [PATCH 9/9] Clear the outline details panel when closing a project --- nw/gui/outlinedetails.py | 21 +++++++++++++++++++++ nw/guimain.py | 1 + 2 files changed, 22 insertions(+) diff --git a/nw/gui/outlinedetails.py b/nw/gui/outlinedetails.py index d19bf2e9..c4e54f16 100644 --- a/nw/gui/outlinedetails.py +++ b/nw/gui/outlinedetails.py @@ -246,6 +246,27 @@ class GuiOutlineDetails(QScrollArea): return + def clearDetails(self): + """Clear all the data labels. + """ + self.titleLabel.setText("Title") + self.titleValue.setText("") + self.fileValue.setText("") + self.itemValue.setText("") + self.cCValue.setText("") + self.wCValue.setText("") + self.pCValue.setText("") + self.synopValue.setText("") + self.povKeyValue.setText("") + self.chrKeyValue.setText("") + self.pltKeyValue.setText("") + self.timKeyValue.setText("") + self.wldKeyValue.setText("") + self.objKeyValue.setText("") + self.entKeyValue.setText("") + self.cstKeyValue.setText("") + return + def showItem(self, tHandle, sTitle): """Update the content of the tree with the given handle and line number pointing to a header. diff --git a/nw/guimain.py b/nw/guimain.py index 9b1a8a42..1a6b5a16 100644 --- a/nw/guimain.py +++ b/nw/guimain.py @@ -345,6 +345,7 @@ class GuiMain(QMainWindow): self.closeDocument() self.docViewer.clearNavHistory() self.projView.closeOutline() + self.projMeta.clearDetails() self.theProject.closeProject() self.theIndex.clearIndex() self.clearGUI()