From 6393ae7621064d2053741eb2c439bf433b4a4e8b Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Fri, 12 Apr 2024 22:57:49 +0200 Subject: [PATCH 1/6] Default to 0 chapters and scenes for new projects (#1811) --- novelwriter/tools/welcome.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/novelwriter/tools/welcome.py b/novelwriter/tools/welcome.py index 2c08cdf5..bff031ac 100644 --- a/novelwriter/tools/welcome.py +++ b/novelwriter/tools/welcome.py @@ -632,17 +632,17 @@ class _NewProjectForm(QWidget): self.numChapters = NSpinBox(self) self.numChapters.setRange(0, 200) - self.numChapters.setValue(5) + self.numChapters.setValue(0) self.numChapters.setToolTip(self.tr("Set to 0 to only add scenes")) self.chapterBox = NWrappedWidgetBox( self.tr("Add {0} chapter documents"), self.numChapters ) - self.chapterBox.addStretch(1) + self.chapterBox.addStretch(0) self.numScenes = NSpinBox(self) self.numScenes.setRange(0, 200) - self.numScenes.setValue(5) + self.numScenes.setValue(3) self.sceneBox = NWrappedWidgetBox( self.tr("Add {0} scene documents (to each chapter)"), self.numScenes From 77a90256ed35e51bce167cf7c018708d508c1812 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Fri, 12 Apr 2024 23:45:15 +0200 Subject: [PATCH 2/6] Simplify project language setting in project settings --- novelwriter/dialogs/projectsettings.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/novelwriter/dialogs/projectsettings.py b/novelwriter/dialogs/projectsettings.py index 4e234f76..62e791df 100644 --- a/novelwriter/dialogs/projectsettings.py +++ b/novelwriter/dialogs/projectsettings.py @@ -257,17 +257,17 @@ class _SettingsPage(NScrollableForm): ) # Project Language + projLang = data.language or CONFIG.guiLocale self.projLang = NComboBox(self) self.projLang.setMinimumWidth(xW) for tag, language in CONFIG.listLanguages(CONFIG.LANG_PROJ): self.projLang.addItem(language, tag) + self.projLang.setCurrentData(projLang, projLang) self.addRow( self.tr("Project language"), self.projLang, self.tr("Only used when building the manuscript."), stretch=(3, 2) ) - if (idx := self.projLang.findData(data.language)) != -1: - self.projLang.setCurrentIndex(idx) # Spell Check Language self.spellLang = NComboBox(self) From a43c351e25906b136a3bb833008ba32d7a2db159 Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Fri, 12 Apr 2024 23:46:09 +0200 Subject: [PATCH 3/6] Add a project language setting to manuscript build (#1812) --- novelwriter/tools/manuscript.py | 52 ++++++++++++++++------- tests/test_tools/test_tools_manuscript.py | 6 +++ 2 files changed, 43 insertions(+), 15 deletions(-) diff --git a/novelwriter/tools/manuscript.py b/novelwriter/tools/manuscript.py index 8f1df562..bc63dac9 100644 --- a/novelwriter/tools/manuscript.py +++ b/novelwriter/tools/manuscript.py @@ -48,7 +48,7 @@ from novelwriter.core.tohtml import ToHtml from novelwriter.core.tokenizer import HeadingFormatter from novelwriter.error import logException from novelwriter.extensions.circularprogress import NProgressCircle -from novelwriter.extensions.modified import NIconToggleButton, NIconToolButton +from novelwriter.extensions.modified import NComboBox, NIconToggleButton, NIconToolButton from novelwriter.gui.theme import STYLES_FLAT_TABS, STYLES_MIN_TOOLBUTTON from novelwriter.tools.manusbuild import GuiManuscriptBuild from novelwriter.tools.manussettings import GuiBuildSettings @@ -91,6 +91,8 @@ class GuiManuscript(QDialog): self.setMinimumHeight(CONFIG.pxInt(500)) iSz = SHARED.theme.baseIconSize + sPx = CONFIG.pxInt(12) + bPx = CONFIG.pxInt(4) wWin = CONFIG.pxInt(900) hWin = CONFIG.pxInt(600) @@ -167,6 +169,22 @@ class GuiManuscript(QDialog): CONFIG.pxInt(pOptions.getInt("GuiManuscript", "detailsHeight", 50)), ]) + # Build Language + # ============== + + projLang = SHARED.project.data.language or CONFIG.guiLocale + self.buildLanguage = NComboBox(self) + # self.projLang.setMinimumWidth(xW) + for tag, language in CONFIG.listLanguages(CONFIG.LANG_PROJ): + self.buildLanguage.addItem(language, tag) + self.buildLanguage.setCurrentData(projLang, projLang) + self.buildLanguage.currentIndexChanged.connect(self._updateBuildLanguage) + + self.languageBox = QHBoxLayout() + self.languageBox.addWidget(QLabel(self.tr("Build Language"), self), 0) + self.languageBox.addWidget(self.buildLanguage, 1) + self.languageBox.setContentsMargins(0, 0, 0, 0) + # Process Controls # ================ @@ -187,6 +205,7 @@ class GuiManuscript(QDialog): self.processBox.addWidget(self.btnPrint, 0, 1) self.processBox.addWidget(self.btnBuild, 1, 0) self.processBox.addWidget(self.btnClose, 1, 1) + self.processBox.setSpacing(bPx) # Assemble GUI # ============ @@ -205,8 +224,10 @@ class GuiManuscript(QDialog): self.controlBox = QVBoxLayout() self.controlBox.addLayout(self.listToolBox, 0) self.controlBox.addWidget(self.buildSplit, 1) + self.controlBox.addLayout(self.languageBox, 0) self.controlBox.addLayout(self.processBox, 0) self.controlBox.setContentsMargins(0, 0, 0, 0) + self.controlBox.setSpacing(sPx) self.optsWidget = QWidget(self) self.optsWidget.setLayout(self.controlBox) @@ -303,37 +324,40 @@ class GuiManuscript(QDialog): @pyqtSlot() def _editSelectedBuild(self) -> None: """Edit the currently selected build settings entry.""" - build = self._getSelectedBuild() - if build is not None: + if build := self._getSelectedBuild(): self._openSettingsDialog(build) return @pyqtSlot("QListWidgetItem*", "QListWidgetItem*") def _updateBuildDetails(self, current: QListWidgetItem, previous: QListWidgetItem) -> None: """Process change of build selection to update the details.""" - if isinstance(current, QListWidgetItem): - build = self._builds.getBuild(current.data(self.D_KEY)) - if build is not None: - self.buildDetails.updateInfo(build) + if current and (build := self._builds.getBuild(current.data(self.D_KEY))): + self.buildDetails.updateInfo(build) return @pyqtSlot() def _deleteSelectedBuild(self) -> None: """Delete the currently selected build settings entry.""" - build = self._getSelectedBuild() - if build is not None: + if build := self._getSelectedBuild(): if SHARED.question(self.tr("Delete build '{0}'?".format(build.name))): self._builds.removeBuild(build.buildID) self._updateBuildsList() return + @pyqtSlot(int) + def _updateBuildLanguage(self, index: int) -> None: + """Update the build language on user selection.""" + SHARED.project.setProjectLang(self.buildLanguage.currentData()) + if build := self._getSelectedBuild(): + self.buildDetails.updateInfo(build) + return + @pyqtSlot(BuildSettings) def _processNewSettings(self, build: BuildSettings) -> None: """Process new build settings from the settings dialog.""" self._builds.setBuild(build) self._updateBuildItem(build) - current = self.buildList.currentItem() - if isinstance(current, QListWidgetItem) and current.data(self.D_KEY) == build.buildID: + if (current := self.buildList.currentItem()) and current.data(self.D_KEY) == build.buildID: self._updateBuildDetails(current, current) return @@ -342,8 +366,7 @@ class GuiManuscript(QDialog): """Run the document builder on the current build settings for the preview widget. """ - build = self._getSelectedBuild() - if build is None: + if not (build := self._getSelectedBuild()): return docBuild = NWBuildDocument(SHARED.project, build) @@ -383,8 +406,7 @@ class GuiManuscript(QDialog): @pyqtSlot() def _buildManuscript(self) -> None: """Open the build dialog and build the manuscript.""" - build = self._getSelectedBuild() - if isinstance(build, BuildSettings): + if build := self._getSelectedBuild(): dlgBuild = GuiManuscriptBuild(self, build) dlgBuild.exec() diff --git a/tests/test_tools/test_tools_manuscript.py b/tests/test_tools/test_tools_manuscript.py index 5e80767f..f3da018a 100644 --- a/tests/test_tools/test_tools_manuscript.py +++ b/tests/test_tools/test_tools_manuscript.py @@ -141,6 +141,12 @@ def testManuscript_Builds(qtbot: QtBot, nwGUI: GuiMain, projPath: Path): assert build.name == "Test Build" assert manus.buildList.count() == 1 + # Changing language should also update project language + manus.buildLanguage.setCurrentData("de_DE", "de_DE") + assert SHARED.project.data.language == "de_DE" + manus.buildLanguage.setCurrentData("en_GB", "en_GB") + assert SHARED.project.data.language == "en_GB" + # Close the dialog should also close the child dialogs manus.btnClose.click() if isinstance(bSettings, GuiBuildSettings): From 95d91562ec068b2503d6e6a44f0be6f2eb0a21fa Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Sat, 13 Apr 2024 00:03:08 +0200 Subject: [PATCH 4/6] Revert last changes, but keep code improvements --- novelwriter/tools/manuscript.py | 31 +---------------------- tests/test_tools/test_tools_manuscript.py | 6 ----- 2 files changed, 1 insertion(+), 36 deletions(-) diff --git a/novelwriter/tools/manuscript.py b/novelwriter/tools/manuscript.py index bc63dac9..1cec67d5 100644 --- a/novelwriter/tools/manuscript.py +++ b/novelwriter/tools/manuscript.py @@ -48,7 +48,7 @@ from novelwriter.core.tohtml import ToHtml from novelwriter.core.tokenizer import HeadingFormatter from novelwriter.error import logException from novelwriter.extensions.circularprogress import NProgressCircle -from novelwriter.extensions.modified import NComboBox, NIconToggleButton, NIconToolButton +from novelwriter.extensions.modified import NIconToggleButton, NIconToolButton from novelwriter.gui.theme import STYLES_FLAT_TABS, STYLES_MIN_TOOLBUTTON from novelwriter.tools.manusbuild import GuiManuscriptBuild from novelwriter.tools.manussettings import GuiBuildSettings @@ -91,8 +91,6 @@ class GuiManuscript(QDialog): self.setMinimumHeight(CONFIG.pxInt(500)) iSz = SHARED.theme.baseIconSize - sPx = CONFIG.pxInt(12) - bPx = CONFIG.pxInt(4) wWin = CONFIG.pxInt(900) hWin = CONFIG.pxInt(600) @@ -169,22 +167,6 @@ class GuiManuscript(QDialog): CONFIG.pxInt(pOptions.getInt("GuiManuscript", "detailsHeight", 50)), ]) - # Build Language - # ============== - - projLang = SHARED.project.data.language or CONFIG.guiLocale - self.buildLanguage = NComboBox(self) - # self.projLang.setMinimumWidth(xW) - for tag, language in CONFIG.listLanguages(CONFIG.LANG_PROJ): - self.buildLanguage.addItem(language, tag) - self.buildLanguage.setCurrentData(projLang, projLang) - self.buildLanguage.currentIndexChanged.connect(self._updateBuildLanguage) - - self.languageBox = QHBoxLayout() - self.languageBox.addWidget(QLabel(self.tr("Build Language"), self), 0) - self.languageBox.addWidget(self.buildLanguage, 1) - self.languageBox.setContentsMargins(0, 0, 0, 0) - # Process Controls # ================ @@ -205,7 +187,6 @@ class GuiManuscript(QDialog): self.processBox.addWidget(self.btnPrint, 0, 1) self.processBox.addWidget(self.btnBuild, 1, 0) self.processBox.addWidget(self.btnClose, 1, 1) - self.processBox.setSpacing(bPx) # Assemble GUI # ============ @@ -224,10 +205,8 @@ class GuiManuscript(QDialog): self.controlBox = QVBoxLayout() self.controlBox.addLayout(self.listToolBox, 0) self.controlBox.addWidget(self.buildSplit, 1) - self.controlBox.addLayout(self.languageBox, 0) self.controlBox.addLayout(self.processBox, 0) self.controlBox.setContentsMargins(0, 0, 0, 0) - self.controlBox.setSpacing(sPx) self.optsWidget = QWidget(self) self.optsWidget.setLayout(self.controlBox) @@ -344,14 +323,6 @@ class GuiManuscript(QDialog): self._updateBuildsList() return - @pyqtSlot(int) - def _updateBuildLanguage(self, index: int) -> None: - """Update the build language on user selection.""" - SHARED.project.setProjectLang(self.buildLanguage.currentData()) - if build := self._getSelectedBuild(): - self.buildDetails.updateInfo(build) - return - @pyqtSlot(BuildSettings) def _processNewSettings(self, build: BuildSettings) -> None: """Process new build settings from the settings dialog.""" diff --git a/tests/test_tools/test_tools_manuscript.py b/tests/test_tools/test_tools_manuscript.py index f3da018a..5e80767f 100644 --- a/tests/test_tools/test_tools_manuscript.py +++ b/tests/test_tools/test_tools_manuscript.py @@ -141,12 +141,6 @@ def testManuscript_Builds(qtbot: QtBot, nwGUI: GuiMain, projPath: Path): assert build.name == "Test Build" assert manus.buildList.count() == 1 - # Changing language should also update project language - manus.buildLanguage.setCurrentData("de_DE", "de_DE") - assert SHARED.project.data.language == "de_DE" - manus.buildLanguage.setCurrentData("en_GB", "en_GB") - assert SHARED.project.data.language == "en_GB" - # Close the dialog should also close the child dialogs manus.btnClose.click() if isinstance(bSettings, GuiBuildSettings): From 4b5383f1c7b71ed034ba85ffdbfcf2c66ad62e6f Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Sat, 13 Apr 2024 00:12:43 +0200 Subject: [PATCH 5/6] Add home path getter to config --- novelwriter/config.py | 4 ++++ tests/test_base/test_base_config.py | 3 +++ 2 files changed, 7 insertions(+) diff --git a/novelwriter/config.py b/novelwriter/config.py index 1f817e0f..e9fab918 100644 --- a/novelwriter/config.py +++ b/novelwriter/config.py @@ -390,6 +390,10 @@ class Config: """Un-scale fixed gui sizes by the screen scale factor.""" return int(value/self.guiScale) + def homePath(self) -> Path: + """The user's home folder.""" + return self._homePath + def dataPath(self, target: str | None = None) -> Path: """Return a path in the data folder.""" if isinstance(target, str): diff --git a/tests/test_base/test_base_config.py b/tests/test_base/test_base_config.py index 5ec474fe..7c9cc88d 100644 --- a/tests/test_base/test_base_config.py +++ b/tests/test_base/test_base_config.py @@ -200,6 +200,9 @@ def testBaseConfig_Methods(fncPath): tstConf = Config() tstConf.initConfig(confPath=fncPath, dataPath=fncPath) + # Home Path + assert tstConf.homePath() == Path.home().absolute() + # Data Path assert tstConf.dataPath() == fncPath assert tstConf.dataPath("stuff") == fncPath / "stuff" From afd4aa5d1f4a0eca331f904f259d5b6316faddfe Mon Sep 17 00:00:00 2001 From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com> Date: Sat, 13 Apr 2024 00:13:20 +0200 Subject: [PATCH 6/6] Update home path and fix wrong setting fix for scene and chapter count on welcome dialog --- novelwriter/core/buildsettings.py | 6 +++--- novelwriter/dialogs/wordlist.py | 4 ++-- novelwriter/tools/welcome.py | 7 +++---- tests/test_core/test_core_buildsettings.py | 11 ++++++----- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/novelwriter/core/buildsettings.py b/novelwriter/core/buildsettings.py index 3957ed27..b68dd97d 100644 --- a/novelwriter/core/buildsettings.py +++ b/novelwriter/core/buildsettings.py @@ -178,7 +178,7 @@ class BuildSettings: def __init__(self) -> None: self._name = "" self._uuid = str(uuid.uuid4()) - self._path = Path.home() + self._path = CONFIG.homePath() self._build = "" self._order = 0 self._format = nwBuildFmt.ODT @@ -220,7 +220,7 @@ class BuildSettings: """The last used build path.""" if self._path.is_dir(): return self._path - return Path.home() + return CONFIG.homePath() @property def lastBuildName(self) -> str: @@ -297,7 +297,7 @@ class BuildSettings: if isinstance(path, Path) and path.is_dir(): self._path = path else: - self._path = Path.home() + self._path = CONFIG.homePath() self._changed = True return diff --git a/novelwriter/dialogs/wordlist.py b/novelwriter/dialogs/wordlist.py index c82ca3d6..54ec2f2f 100644 --- a/novelwriter/dialogs/wordlist.py +++ b/novelwriter/dialogs/wordlist.py @@ -190,7 +190,7 @@ class GuiWordList(QDialog): )) ffilter = formatFileFilter(["*.txt", "*"]) path, _ = QFileDialog.getOpenFileName( - self, self.tr("Import File"), str(Path.home()), filter=ffilter + self, self.tr("Import File"), str(CONFIG.homePath()), filter=ffilter ) if path: try: @@ -207,7 +207,7 @@ class GuiWordList(QDialog): def _exportWords(self) -> None: """Export words to file.""" path, _ = QFileDialog.getSaveFileName( - self, self.tr("Export File"), str(Path.home()) + self, self.tr("Export File"), str(CONFIG.homePath()) ) if path: try: diff --git a/novelwriter/tools/welcome.py b/novelwriter/tools/welcome.py index bff031ac..ce37539b 100644 --- a/novelwriter/tools/welcome.py +++ b/novelwriter/tools/welcome.py @@ -560,7 +560,7 @@ class _NewProjectForm(QWidget): def __init__(self, parent: QWidget) -> None: super().__init__(parent=parent) - self._basePath = CONFIG.lastPath() + self._basePath = CONFIG.homePath() self._fillMode = self.FILL_BLANK self._copyPath = None @@ -638,11 +638,11 @@ class _NewProjectForm(QWidget): self.chapterBox = NWrappedWidgetBox( self.tr("Add {0} chapter documents"), self.numChapters ) - self.chapterBox.addStretch(0) + self.chapterBox.addStretch(1) self.numScenes = NSpinBox(self) self.numScenes.setRange(0, 200) - self.numScenes.setValue(3) + self.numScenes.setValue(0) self.sceneBox = NWrappedWidgetBox( self.tr("Add {0} scene documents (to each chapter)"), self.numScenes @@ -742,7 +742,6 @@ class _NewProjectForm(QWidget): ): self._basePath = Path(projDir) self._updateProjPath() - CONFIG.setLastPath(self._basePath) return @pyqtSlot() diff --git a/tests/test_core/test_core_buildsettings.py b/tests/test_core/test_core_buildsettings.py index bccccae1..10c63253 100644 --- a/tests/test_core/test_core_buildsettings.py +++ b/tests/test_core/test_core_buildsettings.py @@ -27,6 +27,7 @@ import shutil from pathlib import Path +from novelwriter import CONFIG from tools import C, buildTestProject from mocked import causeOSError @@ -58,7 +59,7 @@ def testCoreBuildSettings_ClassAttributes(fncPath: Path): build.setName("Test Build") assert build.name == "Test Build" - # Only valid UUIDs are accpeted, anything else generates a new UUID + # Only valid UUIDs are accepted, anything else generates a new UUID build.setBuildID("5cf45d24-f496-42c9-8733-529a9e52a62b") assert build.buildID == "5cf45d24-f496-42c9-8733-529a9e52a62b" @@ -72,14 +73,14 @@ def testCoreBuildSettings_ClassAttributes(fncPath: Path): # Last path must be valid, if not it defaults to $HOME build.setLastPath("/path/to/nowhere") - assert build.lastPath == Path.home() + assert build.lastPath == CONFIG.homePath() build.setLastPath(None) - assert build.lastPath == Path.home() + assert build.lastPath == CONFIG.homePath() (fncPath / "test.txt").write_text("foobar") build.setLastPath(fncPath / "test.txt") # Can't be a file - assert build.lastPath == Path.home() + assert build.lastPath == CONFIG.homePath() build.setLastPath(fncPath) assert build.lastPath == fncPath @@ -93,7 +94,7 @@ def testCoreBuildSettings_ClassAttributes(fncPath: Path): build.setLastPath(testDir) assert build.lastPath == testDir testDir.rmdir() - assert build.lastPath == Path.home() + assert build.lastPath == CONFIG.homePath() # Last build name build.setLastBuildName(None) # type: ignore