From 8721d53ab2364d1d125b94a3cd1e3d5075a40630 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Wed, 9 Nov 2022 18:47:50 +0100 Subject: [PATCH] Clean up the config class names and methods --- novelwriter/config.py | 64 +++++++++++--------------- novelwriter/core/coretools.py | 2 +- novelwriter/dialogs/about.py | 4 +- novelwriter/gui/theme.py | 12 ++--- novelwriter/guimain.py | 4 +- novelwriter/tools/build.py | 2 +- novelwriter/tools/lipsum.py | 2 +- novelwriter/tools/projwizard.py | 2 +- novelwriter/tools/writingstats.py | 2 +- tests/test_base/test_base_config.py | 61 ++++++++++++------------ tests/test_core/test_core_coretools.py | 2 +- tests/test_dialogs/test_dlg_about.py | 2 +- tests/test_gui/test_gui_theme.py | 8 ++-- 13 files changed, 81 insertions(+), 86 deletions(-) diff --git a/novelwriter/config.py b/novelwriter/config.py index 5b4cfebd..af523dc5 100644 --- a/novelwriter/config.py +++ b/novelwriter/config.py @@ -74,10 +74,10 @@ class Config: self._appPath = self._appRoot # Runtime Settings and Variables - self.hasError = False # True if the config class encountered an error - self.errData = [] # List of error messages + self.hasError = False # True if the config class encountered an error + self.errData = [] # List of error messages self.confChanged = False # True whenever the config has chenged, false after save - self.cmdOpen = None # Path from command line for project to be opened on launch + self.cmdOpen = None # Path from command line for project to be opened on launch # Localisation Info self._qLocal = QLocale.system() @@ -171,7 +171,7 @@ class Config: self.fmtPadThin = False # Spell Checking Settings - self.spellLanguage = None + self.spellLanguage = "en" # Search Bar Switches self.searchCase = False @@ -261,21 +261,21 @@ class Config: """ return int(theSize/self.guiScale) - def getDataPath(self, target=None): + def dataPath(self, target=None): """Return a path in the data folder. """ if isinstance(target, str): return self._dataPath / target return self._dataPath - def getAssetPath(self, target=None): + def assetPath(self, target=None): """Return a path in the assets folder. """ if isinstance(target, str): return self._appPath / "assets" / target return self._appPath / "assets" - def getLastPath(self): + def lastPath(self): """Return the last path used by the user, but ensure it exists. """ if self._lastPath.is_dir(): @@ -294,7 +294,6 @@ class Config: if isinstance(confPath, (str, Path)): logger.info("Setting config from alternative path: %s", confPath) self._confPath = Path(confPath) - if isinstance(dataPath, (str, Path)): logger.info("Setting data path from alternative path: %s", dataPath) self._dataPath = Path(dataPath) @@ -306,33 +305,25 @@ class Config: logger.debug("Last Path: %s", self._lastPath) logger.debug("PDF Manual: %s", self.pdfDocs) - # If the config and data folders don't not exist, create them + # If the config and data folders don't exist, create them # This assumes that the os config and data folders exist self._confPath.mkdir(exist_ok=True) self._dataPath.mkdir(exist_ok=True) - # We don't error on these failing since they are not essential + # Also create the syntax and themes folders if possible if self._dataPath.is_dir(): (self._dataPath / "syntax").mkdir(exist_ok=True) (self._dataPath / "themes").mkdir(exist_ok=True) - # Check if config file exists + # Check if config file exists, and load it. If not, we save defaults if (self._confPath / nwFiles.CONF_FILE).is_file(): - # If it exists, load it self.loadConfig() else: - # If it does not exist, save a copy of the default values self.saveConfig() - # Load recent projects cache self.loadRecentCache() - - # Check the availability of optional packages self._checkOptionalPackages() - if not self.spellLanguage: - self.spellLanguage = "en" - logger.debug("Config initialisation complete") return True @@ -694,16 +685,17 @@ class Config: ## def setLastPath(self, lastPath): - """Set the last used path (by the user). + """Set the last used path. Only the folder is saved, so if the + path is not a folder, the parent of the path is used instead. """ - if isinstance(lastPath, str): + if isinstance(lastPath, (str, Path)): lastPath = Path(lastPath) - if isinstance(lastPath, Path): - if lastPath.is_file(): - self._lastPath = lastPath.parent - elif lastPath.is_dir(): + if not lastPath.is_dir(): + lastPath = lastPath.parent + if lastPath.is_dir(): self._lastPath = lastPath - return True + logger.debug("Last path updated: %s" % self._lastPath) + return def setWinSize(self, newWidth, newHeight): """Set the size of the main window, but only if the change is @@ -719,7 +711,7 @@ class Config: if abs(self.winGeometry[1] - newHeight) > 5: self.winGeometry[1] = newHeight self.confChanged = True - return True + return def setPreferencesSize(self, newWidth, newHeight): """Sat the size of the Preferences dialog window. @@ -727,63 +719,63 @@ class Config: self.prefGeometry[0] = int(newWidth/self.guiScale) self.prefGeometry[1] = int(newHeight/self.guiScale) self.confChanged = True - return True + return def setProjColWidths(self, colWidths): """Set the column widths of the Load Project dialog. """ self.projColWidth = [int(x/self.guiScale) for x in colWidths] self.confChanged = True - return True + return def setMainPanePos(self, panePos): """Set the position of the main GUI splitter. """ self.mainPanePos = [int(x/self.guiScale) for x in panePos] self.confChanged = True - return True + return def setDocPanePos(self, panePos): """Set the position of the main editor/viewer splitter. """ self.docPanePos = [int(x/self.guiScale) for x in panePos] self.confChanged = True - return True + return def setViewPanePos(self, panePos): """Set the position of the viewer meta data splitter. """ self.viewPanePos = [int(x/self.guiScale) for x in panePos] self.confChanged = True - return True + return def setOutlinePanePos(self, panePos): """Set the position of the outline details splitter. """ self.outlnPanePos = [int(x/self.guiScale) for x in panePos] self.confChanged = True - return True + return def setShowRefPanel(self, checkState): """Set the visibility state of the reference panel. """ self.showRefPanel = checkState self.confChanged = True - return self.showRefPanel + return def setViewComments(self, viewState): """Set the visibility state of comments in the viewer. """ self.viewComments = viewState self.confChanged = True - return self.viewComments + return def setViewSynopsis(self, viewState): """Set the visibility state of synopsis comments in the viewer. """ self.viewSynopsis = viewState self.confChanged = True - return self.viewSynopsis + return ## # Default Setters diff --git a/novelwriter/core/coretools.py b/novelwriter/core/coretools.py index 97bab0de..ff002935 100644 --- a/novelwriter/core/coretools.py +++ b/novelwriter/core/coretools.py @@ -430,7 +430,7 @@ class ProjectBuilder: logger.error("No project path set for the example project") return False - pkgSample = self.mainConf.getAssetPath("sample.zip") + pkgSample = self.mainConf.assetPath("sample.zip") if pkgSample.is_file(): try: shutil.unpack_archive(pkgSample, projPath) diff --git a/novelwriter/dialogs/about.py b/novelwriter/dialogs/about.py index 8d4523b1..11617a33 100644 --- a/novelwriter/dialogs/about.py +++ b/novelwriter/dialogs/about.py @@ -232,7 +232,7 @@ class GuiAbout(QDialog): def _fillNotesPage(self): """Load the content for the Release Notes page. """ - docPath = self.mainConf.getAssetPath("text") / "release_notes.htm" + docPath = self.mainConf.assetPath("text") / "release_notes.htm" docText = readTextFile(docPath) if docText: self.pageNotes.setHtml(docText) @@ -243,7 +243,7 @@ class GuiAbout(QDialog): def _fillLicensePage(self): """Load the content for the Licence page. """ - docPath = self.mainConf.getAssetPath("text") / "gplv3_en.htm" + docPath = self.mainConf.assetPath("text") / "gplv3_en.htm" docText = readTextFile(docPath) if docText: self.pageLicense.setHtml(docText) diff --git a/novelwriter/gui/theme.py b/novelwriter/gui/theme.py index 061c8b5c..2d69806c 100644 --- a/novelwriter/gui/theme.py +++ b/novelwriter/gui/theme.py @@ -118,10 +118,10 @@ class GuiTheme: self._availThemes = {} self._availSyntax = {} - self._listConf(self._availSyntax, self.mainConf.getAssetPath("syntax")) - self._listConf(self._availThemes, self.mainConf.getAssetPath("themes")) - self._listConf(self._availSyntax, self.mainConf.getDataPath("syntax")) - self._listConf(self._availThemes, self.mainConf.getDataPath("themes")) + self._listConf(self._availSyntax, self.mainConf.assetPath("syntax")) + self._listConf(self._availThemes, self.mainConf.assetPath("themes")) + self._listConf(self._availSyntax, self.mainConf.dataPath("syntax")) + self._listConf(self._availThemes, self.mainConf.dataPath("themes")) self.loadTheme() self.loadSyntax() @@ -472,7 +472,7 @@ class GuiIcons: self._confName = "icons.conf" # Icon Theme Path - self._iconPath = self.mainConf.getAssetPath("icons") + self._iconPath = self.mainConf.assetPath("icons") # Icon Theme Meta self.themeName = "" @@ -568,7 +568,7 @@ class GuiIcons: if decoKey in self._themeMap: imgPath = self._themeMap[decoKey] elif decoKey in self.IMAGE_MAP: - imgPath = self.mainConf.getAssetPath("images") / self.IMAGE_MAP[decoKey] + imgPath = self.mainConf.assetPath("images") / self.IMAGE_MAP[decoKey] else: logger.error("Decoration with name '%s' does not exist", decoKey) return QPixmap() diff --git a/novelwriter/guimain.py b/novelwriter/guimain.py index 90141c03..fb77ca8a 100644 --- a/novelwriter/guimain.py +++ b/novelwriter/guimain.py @@ -97,7 +97,7 @@ class GuiMain(QMainWindow): self.resize(*self.mainConf.getWinSize()) self._updateWindowTitle() - nwIcon = self.mainConf.getAssetPath("icons") / "novelwriter.svg" + nwIcon = self.mainConf.assetPath("icons") / "novelwriter.svg" self.nwIcon = QIcon(str(nwIcon)) if nwIcon.is_file() else QIcon() self.setWindowIcon(self.nwIcon) qApp.setWindowIcon(self.nwIcon) @@ -698,7 +698,7 @@ class GuiMain(QMainWindow): logger.error("No project open") return False - lastPath = self.mainConf.getLastPath() + lastPath = self.mainConf.lastPath() extFilter = [ self.tr("Text files ({0})").format("*.txt"), self.tr("Markdown files ({0})").format("*.md"), diff --git a/novelwriter/tools/build.py b/novelwriter/tools/build.py index 198ae15e..2935c556 100644 --- a/novelwriter/tools/build.py +++ b/novelwriter/tools/build.py @@ -890,7 +890,7 @@ class GuiBuildNovel(QDialog): cleanName = makeFileNameSafe(self.theProject.data.name) fileName = "%s.%s" % (cleanName, fileExt) - savePath = self.mainConf.getLastPath() / fileName + savePath = self.mainConf.lastPath() / fileName savePath, _ = QFileDialog.getSaveFileName( self, self.tr("Save Document As"), str(savePath) ) diff --git a/novelwriter/tools/lipsum.py b/novelwriter/tools/lipsum.py index 002f7769..def306c5 100644 --- a/novelwriter/tools/lipsum.py +++ b/novelwriter/tools/lipsum.py @@ -119,7 +119,7 @@ class GuiLipsum(QDialog): def _doInsert(self): """Load the text and insert it in the open document. """ - lipsumFile = self.mainConf.getAssetPath("text") / "lipsum.txt" + lipsumFile = self.mainConf.assetPath("text") / "lipsum.txt" lipsumText = readTextFile(lipsumFile).splitlines() if self.randSwitch.isChecked(): diff --git a/novelwriter/tools/projwizard.py b/novelwriter/tools/projwizard.py index bcc88484..fbd2b8ac 100644 --- a/novelwriter/tools/projwizard.py +++ b/novelwriter/tools/projwizard.py @@ -236,7 +236,7 @@ class ProjWizardFolderPage(QWizardPage): def _doBrowse(self): """Select a project folder. """ - lastPath = self.mainConf.getLastPath() + lastPath = self.mainConf.lastPath() projDir = QFileDialog.getExistingDirectory( self, self.tr("Select Project Folder"), str(lastPath), options=QFileDialog.ShowDirsOnly ) diff --git a/novelwriter/tools/writingstats.py b/novelwriter/tools/writingstats.py index efa3a6ca..5e8606d3 100644 --- a/novelwriter/tools/writingstats.py +++ b/novelwriter/tools/writingstats.py @@ -362,7 +362,7 @@ class GuiWritingStats(QDialog): return False # Generate the file name - savePath = self.mainConf.getLastPath() / f"sessionStats.{fileExt}" + savePath = self.mainConf.lastPath() / f"sessionStats.{fileExt}" savePath, _ = QFileDialog.getSaveFileName( self, self.tr("Save Data As"), str(savePath), "%s (*.%s)" % (textFmt, fileExt) ) diff --git a/tests/test_base/test_base_config.py b/tests/test_base/test_base_config.py index 36f0eb79..fdca0b8b 100644 --- a/tests/test_base/test_base_config.py +++ b/tests/test_base/test_base_config.py @@ -313,98 +313,98 @@ def testBaseConfig_SettersGetters(tmpConf, tmpDir, outDir, refDir): # Window Size tmpConf.guiScale = 1.0 - assert tmpConf.setWinSize(1205, 655) - assert not tmpConf.confChanged + tmpConf.setWinSize(1205, 655) + assert tmpConf.confChanged is False tmpConf.guiScale = 2.0 - assert tmpConf.setWinSize(70, 70) + tmpConf.setWinSize(70, 70) assert tmpConf.getWinSize() == [70, 70] assert tmpConf.winGeometry == [35, 35] tmpConf.guiScale = 1.0 - assert tmpConf.setWinSize(70, 70) + tmpConf.setWinSize(70, 70) assert tmpConf.getWinSize() == [70, 70] assert tmpConf.winGeometry == [70, 70] - assert tmpConf.setWinSize(1200, 650) + tmpConf.setWinSize(1200, 650) # Preferences Size tmpConf.guiScale = 2.0 - assert tmpConf.setPreferencesSize(70, 70) + tmpConf.setPreferencesSize(70, 70) assert tmpConf.getPreferencesSize() == [70, 70] assert tmpConf.prefGeometry == [35, 35] tmpConf.guiScale = 1.0 - assert tmpConf.setPreferencesSize(70, 70) + tmpConf.setPreferencesSize(70, 70) assert tmpConf.getPreferencesSize() == [70, 70] assert tmpConf.prefGeometry == [70, 70] - assert tmpConf.setPreferencesSize(700, 615) + tmpConf.setPreferencesSize(700, 615) # Project Settings Tree Columns tmpConf.guiScale = 2.0 - assert tmpConf.setProjColWidths([10, 20, 30]) + tmpConf.setProjColWidths([10, 20, 30]) assert tmpConf.getProjColWidths() == [10, 20, 30] assert tmpConf.projColWidth == [5, 10, 15] tmpConf.guiScale = 1.0 - assert tmpConf.setProjColWidths([10, 20, 30]) + tmpConf.setProjColWidths([10, 20, 30]) assert tmpConf.getProjColWidths() == [10, 20, 30] assert tmpConf.projColWidth == [10, 20, 30] - assert tmpConf.setProjColWidths([200, 60, 140]) + tmpConf.setProjColWidths([200, 60, 140]) # Main Pane Splitter tmpConf.guiScale = 2.0 - assert tmpConf.setMainPanePos([200, 700]) + tmpConf.setMainPanePos([200, 700]) assert tmpConf.getMainPanePos() == [200, 700] assert tmpConf.mainPanePos == [100, 350] tmpConf.guiScale = 1.0 - assert tmpConf.setMainPanePos([200, 700]) + tmpConf.setMainPanePos([200, 700]) assert tmpConf.getMainPanePos() == [200, 700] assert tmpConf.mainPanePos == [200, 700] - assert tmpConf.setMainPanePos([300, 800]) + tmpConf.setMainPanePos([300, 800]) # Doc Pane Splitter tmpConf.guiScale = 2.0 - assert tmpConf.setDocPanePos([300, 300]) + tmpConf.setDocPanePos([300, 300]) assert tmpConf.getDocPanePos() == [300, 300] assert tmpConf.docPanePos == [150, 150] tmpConf.guiScale = 1.0 - assert tmpConf.setDocPanePos([300, 300]) + tmpConf.setDocPanePos([300, 300]) assert tmpConf.getDocPanePos() == [300, 300] assert tmpConf.docPanePos == [300, 300] - assert tmpConf.setDocPanePos([400, 400]) + tmpConf.setDocPanePos([400, 400]) # View Pane Splitter tmpConf.guiScale = 2.0 - assert tmpConf.setViewPanePos([400, 250]) + tmpConf.setViewPanePos([400, 250]) assert tmpConf.getViewPanePos() == [400, 250] assert tmpConf.viewPanePos == [200, 125] tmpConf.guiScale = 1.0 - assert tmpConf.setViewPanePos([400, 250]) + tmpConf.setViewPanePos([400, 250]) assert tmpConf.getViewPanePos() == [400, 250] assert tmpConf.viewPanePos == [400, 250] - assert tmpConf.setViewPanePos([500, 150]) + tmpConf.setViewPanePos([500, 150]) # Outline Pane Splitter tmpConf.guiScale = 2.0 - assert tmpConf.setOutlinePanePos([400, 250]) + tmpConf.setOutlinePanePos([400, 250]) assert tmpConf.getOutlinePanePos() == [400, 250] assert tmpConf.outlnPanePos == [200, 125] tmpConf.guiScale = 1.0 - assert tmpConf.setOutlinePanePos([400, 250]) + tmpConf.setOutlinePanePos([400, 250]) assert tmpConf.getOutlinePanePos() == [400, 250] assert tmpConf.outlnPanePos == [400, 250] - assert tmpConf.setOutlinePanePos([500, 150]) + tmpConf.setOutlinePanePos([500, 150]) # Getters Only # ============ @@ -424,17 +424,20 @@ def testBaseConfig_SettersGetters(tmpConf, tmpDir, outDir, refDir): # Flag Setters # ============ - assert tmpConf.setShowRefPanel(False) is False + tmpConf.setShowRefPanel(False) assert tmpConf.showRefPanel is False - assert tmpConf.setShowRefPanel(True) is True + tmpConf.setShowRefPanel(True) + assert tmpConf.showRefPanel is True - assert tmpConf.setViewComments(False) is False + tmpConf.setViewComments(False) assert tmpConf.viewComments is False - assert tmpConf.setViewComments(True) is True + tmpConf.setViewComments(True) + assert tmpConf.viewComments is True - assert tmpConf.setViewSynopsis(False) is False + tmpConf.setViewSynopsis(False) assert tmpConf.viewSynopsis is False - assert tmpConf.setViewSynopsis(True) is True + tmpConf.setViewSynopsis(True) + assert tmpConf.viewSynopsis is True # Check Final File # ================ diff --git a/tests/test_core/test_core_coretools.py b/tests/test_core/test_core_coretools.py index 5398e4f7..39d95a7a 100644 --- a/tests/test_core/test_core_coretools.py +++ b/tests/test_core/test_core_coretools.py @@ -395,7 +395,7 @@ def testCoreTools_NewSample(monkeypatch, fncPath, tmpConf, tmpPath, mockGUI): srcSample = tmpConf._appRoot / "sample" dstSample = tmpPath / "sample.zip" monkeypatch.setattr( - "novelwriter.config.Config.getAssetPath", lambda *a: tmpPath / "sample.zip" + "novelwriter.config.Config.assetPath", lambda *a: tmpPath / "sample.zip" ) # Cannot extract when the zip does not exist diff --git a/tests/test_dialogs/test_dlg_about.py b/tests/test_dialogs/test_dlg_about.py index b4357051..1b650ec1 100644 --- a/tests/test_dialogs/test_dlg_about.py +++ b/tests/test_dialogs/test_dlg_about.py @@ -48,7 +48,7 @@ def testDlgAbout_NWDialog(qtbot, monkeypatch, nwGUI): assert msgAbout.pageLicense.document().characterCount() > 100 with monkeypatch.context() as mp: - mp.setattr("novelwriter.config.Config.getAssetPath", lambda *a: Path("whatever")) + mp.setattr("novelwriter.config.Config.assetPath", lambda *a: Path("whatever")) msgAbout._fillNotesPage() assert msgAbout.pageNotes.toPlainText() == "Error loading release notes text ..." msgAbout._fillLicensePage() diff --git a/tests/test_gui/test_gui_theme.py b/tests/test_gui/test_gui_theme.py index df0a1b15..42f5c7c5 100644 --- a/tests/test_gui/test_gui_theme.py +++ b/tests/test_gui/test_gui_theme.py @@ -132,8 +132,8 @@ def testGuiTheme_Theme(qtbot, monkeypatch, nwGUI, fncPath): # List Themes # =========== - shutil.copy(mainConf.getAssetPath("themes") / "default_dark.conf", fncPath / "themes") - shutil.copy(mainConf.getAssetPath("themes") / "default.conf", fncPath / "themes") + shutil.copy(mainConf.assetPath("themes") / "default_dark.conf", fncPath / "themes") + shutil.copy(mainConf.assetPath("themes") / "default.conf", fncPath / "themes") # Block the reading of the files with monkeypatch.context() as mp: @@ -199,8 +199,8 @@ def testGuiTheme_Syntax(qtbot, monkeypatch, nwGUI, fncPath): # List Themes # =========== - shutil.copy(mainConf.getAssetPath("syntax") / "default_dark.conf", fncPath / "syntax") - shutil.copy(mainConf.getAssetPath("syntax") / "default_light.conf", fncPath / "syntax") + shutil.copy(mainConf.assetPath("syntax") / "default_dark.conf", fncPath / "syntax") + shutil.copy(mainConf.assetPath("syntax") / "default_light.conf", fncPath / "syntax") # Block the reading of the files with monkeypatch.context() as mp: