From ee21045ee2953c07cbe37149d26a4c430b7f633f Mon Sep 17 00:00:00 2001
From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com>
Date: Fri, 26 Jan 2024 19:50:17 +0100
Subject: [PATCH 1/7] Update the design on the Project Settings dialog
---
.../{projsettings.py => projectsettings.py} | 318 ++++++++++--------
novelwriter/extensions/configlayout.py | 18 +-
novelwriter/gui/projtree.py | 6 +-
novelwriter/guimain.py | 12 +-
4 files changed, 195 insertions(+), 159 deletions(-)
rename novelwriter/dialogs/{projsettings.py => projectsettings.py} (72%)
diff --git a/novelwriter/dialogs/projsettings.py b/novelwriter/dialogs/projectsettings.py
similarity index 72%
rename from novelwriter/dialogs/projsettings.py
rename to novelwriter/dialogs/projectsettings.py
index 8a9354a0..51efce1b 100644
--- a/novelwriter/dialogs/projsettings.py
+++ b/novelwriter/dialogs/projectsettings.py
@@ -3,7 +3,8 @@ novelWriter – GUI Project Settings
==================================
File History:
-Created: 2018-09-29 [0.0.1] GuiProjectSettings
+Created: 2018-09-29 [0.0.1] GuiProjectSettings
+Rewritten: 2024-01-26 [2.3b1] GuiProjectSettings
This file is a part of novelWriter
Copyright 2018–2024, Veronica Berglyd Olsen
@@ -25,75 +26,102 @@ from __future__ import annotations
import logging
-from typing import TYPE_CHECKING
-
-from PyQt5.QtGui import QCloseEvent, QIcon, QPixmap, QColor
+from PyQt5.QtGui import QCloseEvent, QColor, QIcon, QPixmap
from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot
from PyQt5.QtWidgets import (
- QColorDialog, QComboBox, QDialogButtonBox, QHBoxLayout, QLabel, QLineEdit,
- QPushButton, QTreeWidget, QTreeWidgetItem, QVBoxLayout, QWidget, qApp
+ QColorDialog, QComboBox, QDialog, QDialogButtonBox, QHBoxLayout, QLabel,
+ QLineEdit, QPushButton, QStackedWidget, QTreeWidget, QTreeWidgetItem,
+ QVBoxLayout, QWidget, qApp
)
from novelwriter import CONFIG, SHARED
from novelwriter.common import simplified
from novelwriter.extensions.switch import NSwitch
-from novelwriter.extensions.pageddialog import NPagedDialog
-from novelwriter.extensions.configlayout import NConfigLayout
-
-if TYPE_CHECKING: # pragma: no cover
- from novelwriter.guimain import GuiMain
+from novelwriter.extensions.configlayout import NColourLabel, NScrollableForm
+from novelwriter.extensions.pagedsidebar import NPagedSideBar
logger = logging.getLogger(__name__)
-class GuiProjectSettings(NPagedDialog):
+class GuiProjectSettings(QDialog):
- TAB_MAIN = 0
- TAB_STATUS = 1
- TAB_IMPORT = 2
- TAB_REPLACE = 3
+ PAGE_SETTINGS = 0
+ PAGE_STATUS = 1
+ PAGE_IMPORT = 2
+ PAGE_REPLACE = 3
- newProjectSettingsReady = pyqtSignal()
+ newProjectSettingsReady = pyqtSignal(bool)
- def __init__(self, mainGui: GuiMain, focusTab: int = TAB_MAIN) -> None:
- super().__init__(parent=mainGui)
+ def __init__(self, parent: QWidget, gotoPage: int = PAGE_SETTINGS) -> None:
+ super().__init__(parent=parent)
logger.debug("Create: GuiProjectSettings")
self.setObjectName("GuiProjectSettings")
-
- self.mainGui = mainGui
- SHARED.project.countStatus()
self.setWindowTitle(self.tr("Project Settings"))
- wW = CONFIG.pxInt(570)
- wH = CONFIG.pxInt(375)
- pOptions = SHARED.project.options
+ wW = CONFIG.pxInt(500)
+ wH = CONFIG.pxInt(400)
+ options = SHARED.project.options
- self.setMinimumWidth(wW)
- self.setMinimumHeight(wH)
+ self.setMinimumSize(wW, wH)
self.resize(
- CONFIG.pxInt(pOptions.getInt("GuiProjectSettings", "winWidth", wW)),
- CONFIG.pxInt(pOptions.getInt("GuiProjectSettings", "winHeight", wH))
+ CONFIG.pxInt(options.getInt("GuiProjectSettings", "winWidth", wW)),
+ CONFIG.pxInt(options.getInt("GuiProjectSettings", "winHeight", wH))
)
- self.tabMain = GuiProjectEditMain(self)
- self.tabStatus = GuiProjectEditStatus(self, True)
- self.tabImport = GuiProjectEditStatus(self, False)
- self.tabReplace = GuiProjectEditReplace(self)
+ # Title
+ self.titleLabel = NColourLabel(
+ self.tr("Project Settings"), SHARED.theme.helpText, parent=self, scale=1.25
+ )
+ self.titleLabel.setIndent(CONFIG.pxInt(4))
- self.addTab(self.tabMain, self.tr("Settings"))
- self.addTab(self.tabStatus, self.tr("Status"))
- self.addTab(self.tabImport, self.tr("Importance"))
- self.addTab(self.tabReplace, self.tr("Auto-Replace"))
+ # SideBar
+ self.sidebar = NPagedSideBar(self)
+ self.sidebar.setLabelColor(SHARED.theme.helpText)
+ self.sidebar.addButton(self.tr("Settings"), self.PAGE_SETTINGS)
+ self.sidebar.addButton(self.tr("Status"), self.PAGE_STATUS)
+ self.sidebar.addButton(self.tr("Importance"), self.PAGE_IMPORT)
+ self.sidebar.addButton(self.tr("Auto-Replace"), self.PAGE_REPLACE)
+ self.sidebar.setSelected(gotoPage)
+ self.sidebar.buttonClicked.connect(self._sidebarClicked)
- self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
+ # Buttons
+ self.buttonBox = QDialogButtonBox(
+ QDialogButtonBox.StandardButton.Save | QDialogButtonBox.StandardButton.Cancel
+ )
self.buttonBox.accepted.connect(self._doSave)
self.buttonBox.rejected.connect(self.close)
- self.rejected.connect(self.close)
- self.addControls(self.buttonBox)
- # Focus Tab
- self._focusTab(focusTab)
+ # Content
+ self.settingsPage = _SettingsPage(self)
+ self.statusPage = _StatusPage(self, True)
+ self.importPage = _StatusPage(self, False)
+ self.replacePage = _ReplacePage(self)
+
+ self.mainStack = QStackedWidget(self)
+ self.mainStack.addWidget(self.settingsPage)
+ self.mainStack.addWidget(self.statusPage)
+ self.mainStack.addWidget(self.importPage)
+ self.mainStack.addWidget(self.replacePage)
+
+ # Assemble
+ self.topBox = QHBoxLayout()
+ self.topBox.addWidget(self.titleLabel)
+ self.topBox.addStretch(1)
+
+ self.mainBox = QHBoxLayout()
+ self.mainBox.addWidget(self.sidebar)
+ self.mainBox.addWidget(self.mainStack)
+ self.mainBox.setContentsMargins(0, 0, 0, 0)
+
+ self.outerBox = QVBoxLayout()
+ self.outerBox.addLayout(self.topBox)
+ self.outerBox.addLayout(self.mainBox)
+ self.outerBox.addWidget(self.buttonBox)
+ self.outerBox.setSpacing(CONFIG.pxInt(8))
+
+ self.setLayout(self.outerBox)
+ self.setSizeGripEnabled(True)
logger.debug("Ready: GuiProjectSettings")
@@ -103,9 +131,13 @@ class GuiProjectSettings(NPagedDialog):
logger.debug("Delete: GuiProjectSettings")
return
+ ##
+ # Events
+ ##
+
def closeEvent(self, event: QCloseEvent) -> None:
- """Capture the close event and perform cleanup."""
- self._saveGuiSettings()
+ """Capture the user closing the window and save settings."""
+ self._saveSettings()
event.accept()
self.deleteLater()
return
@@ -114,40 +146,52 @@ class GuiProjectSettings(NPagedDialog):
# Private Slots
##
+ @pyqtSlot(int)
+ def _sidebarClicked(self, pageId: int) -> None:
+ """Process a user request to switch page."""
+ if pageId == self.PAGE_SETTINGS:
+ self.mainStack.setCurrentWidget(self.settingsPage)
+ elif pageId == self.PAGE_STATUS:
+ self.mainStack.setCurrentWidget(self.statusPage)
+ elif pageId == self.PAGE_IMPORT:
+ self.mainStack.setCurrentWidget(self.importPage)
+ elif pageId == self.PAGE_REPLACE:
+ self.mainStack.setCurrentWidget(self.replacePage)
+ return
+
@pyqtSlot()
def _doSave(self) -> None:
"""Save settings and close dialog."""
project = SHARED.project
- projName = self.tabMain.editName.text()
- bookTitle = self.tabMain.editTitle.text()
- bookAuthor = self.tabMain.editAuthor.text()
- projLang = self.tabMain.projLang.currentData()
- spellLang = self.tabMain.spellLang.currentData()
- doBackup = not self.tabMain.doBackup.isChecked()
+ projName = self.settingsPage.projName.text()
+ projAuthor = self.settingsPage.projAuthor.text()
+ projLang = self.settingsPage.projLang.currentData()
+ spellLang = self.settingsPage.spellLang.currentData()
+ doBackup = not self.settingsPage.doBackup.isChecked()
project.data.setName(projName)
- project.data.setTitle(bookTitle)
- project.data.setAuthor(bookAuthor)
+ project.data.setAuthor(projAuthor)
project.data.setDoBackup(doBackup)
project.data.setSpellLang(spellLang)
project.setProjectLang(projLang)
- if self.tabStatus.colChanged:
- newList, delList = self.tabStatus.getNewList()
+ rebuildTrees = False
+
+ if self.statusPage.colChanged:
+ newList, delList = self.statusPage.getNewList()
project.setStatusColours(newList, delList)
+ rebuildTrees = True
- if self.tabImport.colChanged:
- newList, delList = self.tabImport.getNewList()
+ if self.importPage.colChanged:
+ newList, delList = self.importPage.getNewList()
project.setImportColours(newList, delList)
+ rebuildTrees = True
- if self.tabStatus.colChanged or self.tabImport.colChanged:
- self.mainGui.rebuildTrees()
-
- if self.tabReplace.arChanged:
- newList = self.tabReplace.getNewList()
+ if self.replacePage.arChanged:
+ newList = self.replacePage.getNewList()
project.data.setAutoReplace(newList)
- self.newProjectSettingsReady.emit()
+ self.newProjectSettingsReady.emit(rebuildTrees)
qApp.processEvents()
self.close()
@@ -157,134 +201,104 @@ class GuiProjectSettings(NPagedDialog):
# Internal Functions
##
- def _focusTab(self, tab: int) -> None:
- """Change which is the focused tab."""
- if tab == self.TAB_MAIN:
- self.setCurrentWidget(self.tabMain)
- elif tab == self.TAB_STATUS:
- self.setCurrentWidget(self.tabStatus)
- elif tab == self.TAB_IMPORT:
- self.setCurrentWidget(self.tabImport)
- elif tab == self.TAB_REPLACE:
- self.setCurrentWidget(self.tabReplace)
- return
-
- def _saveGuiSettings(self) -> None:
+ def _saveSettings(self) -> None:
"""Save GUI settings."""
winWidth = CONFIG.rpxInt(self.width())
winHeight = CONFIG.rpxInt(self.height())
- replaceColW = CONFIG.rpxInt(self.tabReplace.listBox.columnWidth(0))
- statusColW = CONFIG.rpxInt(self.tabStatus.listBox.columnWidth(0))
- importColW = CONFIG.rpxInt(self.tabImport.listBox.columnWidth(0))
+ statusColW = CONFIG.rpxInt(self.statusPage.columnWidth())
+ importColW = CONFIG.rpxInt(self.importPage.columnWidth())
+ replaceColW = CONFIG.rpxInt(self.replacePage.columnWidth())
logger.debug("Saving State: GuiProjectSettings")
- pOptions = SHARED.project.options
- pOptions.setValue("GuiProjectSettings", "winWidth", winWidth)
- pOptions.setValue("GuiProjectSettings", "winHeight", winHeight)
- pOptions.setValue("GuiProjectSettings", "replaceColW", replaceColW)
- pOptions.setValue("GuiProjectSettings", "statusColW", statusColW)
- pOptions.setValue("GuiProjectSettings", "importColW", importColW)
+ options = SHARED.project.options
+ options.setValue("GuiProjectSettings", "winWidth", winWidth)
+ options.setValue("GuiProjectSettings", "winHeight", winHeight)
+ options.setValue("GuiProjectSettings", "statusColW", statusColW)
+ options.setValue("GuiProjectSettings", "importColW", importColW)
+ options.setValue("GuiProjectSettings", "replaceColW", replaceColW)
return
# END Class GuiProjectSettings
-class GuiProjectEditMain(QWidget):
+class _SettingsPage(NScrollableForm):
def __init__(self, parent: QWidget) -> None:
super().__init__(parent=parent)
- # The Form
- self.mainForm = NConfigLayout()
- self.mainForm.setHelpTextStyle(SHARED.theme.helpText)
- self.setLayout(self.mainForm)
-
- self.mainForm.addGroupLabel(self.tr("Project Settings"))
-
xW = CONFIG.pxInt(250)
- pData = SHARED.project.data
+ data = SHARED.project.data
+ self.setHelpTextStyle(SHARED.theme.helpText)
+ self.setRowIndent(0)
- self.editName = QLineEdit()
- self.editName.setMaxLength(200)
- self.editName.setMaximumWidth(xW)
- self.editName.setText(pData.name)
- self.mainForm.addRow(
+ # Project Name
+ self.projName = QLineEdit(self)
+ self.projName.setMaxLength(200)
+ self.projName.setMaximumWidth(xW)
+ self.projName.setText(data.name)
+ self.addRow(
self.tr("Project name"),
- self.editName,
- self.tr("Should be set only once.")
+ self.projName,
+ self.tr("Changing this will affect the backup path.")
)
- self.editTitle = QLineEdit()
- self.editTitle.setMaxLength(200)
- self.editTitle.setMaximumWidth(xW)
- self.editTitle.setText(pData.title)
- self.mainForm.addRow(
- self.tr("Novel title"),
- self.editTitle,
- self.tr("Change whenever you want!")
- )
-
- self.editAuthor = QLineEdit()
- self.editAuthor.setMaxLength(200)
- self.editAuthor.setMaximumWidth(xW)
- self.editAuthor.setText(pData.author)
- self.mainForm.addRow(
+ # Project Author
+ self.projAuthor = QLineEdit(self)
+ self.projAuthor.setMaxLength(200)
+ self.projAuthor.setMaximumWidth(xW)
+ self.projAuthor.setText(data.author)
+ self.addRow(
self.tr("Author(s)"),
- self.editAuthor,
- self.tr("Change whenever you want!")
+ self.projAuthor,
+ self.tr("Only used when building the manuscript.")
)
+ # Project Language
self.projLang = QComboBox(self)
self.projLang.setMaximumWidth(xW)
for tag, language in CONFIG.listLanguages(CONFIG.LANG_PROJ):
self.projLang.addItem(language, tag)
- self.mainForm.addRow(
+ self.addRow(
self.tr("Project language"),
self.projLang,
- self.tr("Used when building the manuscript.")
+ self.tr("Only used when building the manuscript.")
)
+ if (idx := self.projLang.findData(data.language)) != -1:
+ self.projLang.setCurrentIndex(idx)
- langIdx = 0
- if pData.language is not None:
- langIdx = self.projLang.findData(pData.language)
- if langIdx == -1:
- langIdx = self.projLang.findData("en_GB")
- if langIdx != -1:
- self.projLang.setCurrentIndex(langIdx)
-
+ # Spell Check Language
self.spellLang = QComboBox(self)
self.spellLang.setMaximumWidth(xW)
self.spellLang.addItem(self.tr("Default"), "None")
if CONFIG.hasEnchant:
for tag, language in SHARED.spelling.listDictionaries():
self.spellLang.addItem(language, tag)
- self.mainForm.addRow(
+ self.addRow(
self.tr("Spell check language"),
self.spellLang,
self.tr("Overrides main preferences.")
)
+ if (idx := self.spellLang.findData(data.spellLang)) != -1:
+ self.spellLang.setCurrentIndex(idx)
- langIdx = 0
- if pData.spellLang is not None:
- langIdx = self.spellLang.findData(pData.spellLang)
- if langIdx != -1:
- self.spellLang.setCurrentIndex(langIdx)
-
+ # Backup on Close
self.doBackup = NSwitch(self)
- self.doBackup.setChecked(not pData.doBackup)
- self.mainForm.addRow(
- self.tr("No backup on close"),
+ self.doBackup.setChecked(not data.doBackup)
+ self.addRow(
+ self.tr("Disable backup on close"),
self.doBackup,
self.tr("Overrides main preferences.")
)
+ self.finalise()
+
return
-# END Class GuiProjectEditMain
+# END Class _SettingsPage
-class GuiProjectEditStatus(QWidget):
+class _StatusPage(QWidget):
COL_LABEL = 0
COL_USAGE = 1
@@ -318,7 +332,7 @@ class GuiProjectEditStatus(QWidget):
# The List
# ========
- self.listBox = QTreeWidget()
+ self.listBox = QTreeWidget(self)
self.listBox.setHeaderLabels([
self.tr("Label"), self.tr("Usage"),
])
@@ -332,16 +346,16 @@ class GuiProjectEditStatus(QWidget):
# List Controls
# =============
- self.addButton = QPushButton(SHARED.theme.getIcon("add"), "")
+ self.addButton = QPushButton(SHARED.theme.getIcon("add"), "", self)
self.addButton.clicked.connect(self._newItem)
- self.delButton = QPushButton(SHARED.theme.getIcon("remove"), "")
+ self.delButton = QPushButton(SHARED.theme.getIcon("remove"), "", self)
self.delButton.clicked.connect(self._delItem)
- self.upButton = QPushButton(SHARED.theme.getIcon("up"), "")
+ self.upButton = QPushButton(SHARED.theme.getIcon("up"), "", self)
self.upButton.clicked.connect(lambda: self._moveItem(-1))
- self.dnButton = QPushButton(SHARED.theme.getIcon("down"), "")
+ self.dnButton = QPushButton(SHARED.theme.getIcon("down"), "", self)
self.dnButton.clicked.connect(lambda: self._moveItem(1))
# Edit Form
@@ -389,6 +403,7 @@ class GuiProjectEditStatus(QWidget):
self.outerBox = QVBoxLayout()
self.outerBox.addWidget(QLabel("%s" % pageLabel))
self.outerBox.addLayout(self.innerBox)
+ self.outerBox.setContentsMargins(0, 0, 0, 0)
self.setLayout(self.outerBox)
@@ -410,6 +425,10 @@ class GuiProjectEditStatus(QWidget):
return [], []
+ def columnWidth(self) -> int:
+ """Return the size of the header column."""
+ return self.listBox.columnWidth(0)
+
##
# Private Slots
##
@@ -553,10 +572,10 @@ class GuiProjectEditStatus(QWidget):
else:
return self.tr("Used by {0} items").format(nUse)
-# END Class GuiProjectEditStatus
+# END Class _StatusPage
-class GuiProjectEditReplace(QWidget):
+class _ReplacePage(QWidget):
COL_KEY = 0
COL_REPL = 1
@@ -638,6 +657,7 @@ class GuiProjectEditReplace(QWidget):
self.outerBox = QVBoxLayout()
self.outerBox.addWidget(QLabel("%s" % pageLabel))
self.outerBox.addLayout(self.innerBox)
+ self.outerBox.setContentsMargins(0, 0, 0, 0)
self.setLayout(self.outerBox)
@@ -655,6 +675,10 @@ class GuiProjectEditReplace(QWidget):
new[aKey] = aVal
return new
+ def columnWidth(self) -> int:
+ """Return the size of the header column."""
+ return self.listBox.columnWidth(0)
+
##
# Internal Functions
##
@@ -725,4 +749,4 @@ class GuiProjectEditReplace(QWidget):
result += c
return result
-# END Class GuiProjectEditReplace
+# END Class _ReplacePage
diff --git a/novelwriter/extensions/configlayout.py b/novelwriter/extensions/configlayout.py
index c71036be..2db50ded 100644
--- a/novelwriter/extensions/configlayout.py
+++ b/novelwriter/extensions/configlayout.py
@@ -50,6 +50,7 @@ class NScrollableForm(QScrollArea):
self._helpCol = QColor(0, 0, 0)
self._fontScale = FONT_SCALE
self._first = True
+ self._indent = CONFIG.pxInt(12)
self._sections: dict[int, QLabel] = {}
self._editable: dict[str, NColourLabel] = {}
@@ -92,6 +93,16 @@ class NScrollableForm(QScrollArea):
qHelp.setText(text)
return
+ def setRowIndent(self, indent: int) -> None:
+ """Set the indentation of each row."""
+ self._indent = max(indent, 0)
+ return
+
+ def setLayoutMargins(self, left: int, top: int, right: int, bottom: int) -> None:
+ """Set the contents margins on the layout."""
+ self._layout.setContentsMargins(left, top, right, bottom)
+ return
+
##
# Methods
##
@@ -128,14 +139,13 @@ class NScrollableForm(QScrollArea):
row = QHBoxLayout()
row.setSpacing(CONFIG.pxInt(4))
- mPx = CONFIG.pxInt(12)
qLabel = QLabel(label, self)
- qLabel.setIndent(mPx)
+ qLabel.setIndent(self._indent)
qLabel.setBuddy(widget)
if helpText:
qHelp = NColourLabel(str(helpText), self._helpCol, scale=self._fontScale, wrap=True)
- qHelp.setIndent(mPx)
+ qHelp.setIndent(self._indent)
labelBox = QVBoxLayout()
labelBox.addWidget(qLabel)
labelBox.addWidget(qHelp)
@@ -147,7 +157,7 @@ class NScrollableForm(QScrollArea):
else:
row.addWidget(qLabel)
- row.addSpacing(mPx)
+ row.addSpacing(CONFIG.pxInt(12))
row.addWidget(widget)
if isinstance(unit, str):
diff --git a/novelwriter/gui/projtree.py b/novelwriter/gui/projtree.py
index 8c42a107..da050876 100644
--- a/novelwriter/gui/projtree.py
+++ b/novelwriter/gui/projtree.py
@@ -48,7 +48,7 @@ from novelwriter.core.coretools import DocDuplicator, DocMerger, DocSplitter
from novelwriter.dialogs.docmerge import GuiDocMerge
from novelwriter.dialogs.docsplit import GuiDocSplit
from novelwriter.dialogs.editlabel import GuiEditLabel
-from novelwriter.dialogs.projsettings import GuiProjectSettings
+from novelwriter.dialogs.projectsettings import GuiProjectSettings
from novelwriter.enum import (
nwDocMode, nwItemType, nwItemClass, nwItemLayout, nwWidget
)
@@ -1748,7 +1748,7 @@ class _TreeContextMenu(QMenu):
menu.addSeparator()
action = menu.addAction(self.tr("Manage Labels ..."))
action.triggered.connect(
- lambda: self.projView.projectSettingsRequest.emit(GuiProjectSettings.TAB_STATUS)
+ lambda: self.projView.projectSettingsRequest.emit(GuiProjectSettings.PAGE_STATUS)
)
else:
menu = self.addMenu(self.tr("Set Importance to ..."))
@@ -1765,7 +1765,7 @@ class _TreeContextMenu(QMenu):
menu.addSeparator()
action = menu.addAction(self.tr("Manage Labels ..."))
action.triggered.connect(
- lambda: self.projView.projectSettingsRequest.emit(GuiProjectSettings.TAB_IMPORT)
+ lambda: self.projView.projectSettingsRequest.emit(GuiProjectSettings.PAGE_IMPORT)
)
return
diff --git a/novelwriter/guimain.py b/novelwriter/guimain.py
index 795c058a..0282b8d7 100644
--- a/novelwriter/guimain.py
+++ b/novelwriter/guimain.py
@@ -53,7 +53,7 @@ from novelwriter.dialogs.about import GuiAbout
from novelwriter.dialogs.updates import GuiUpdates
from novelwriter.dialogs.wordlist import GuiWordList
from novelwriter.dialogs.preferences import GuiPreferences
-from novelwriter.dialogs.projsettings import GuiProjectSettings
+from novelwriter.dialogs.projectsettings import GuiProjectSettings
from novelwriter.tools.welcome import GuiWelcome
from novelwriter.tools.manuscript import GuiManuscript
from novelwriter.tools.dictionaries import GuiDictionaries
@@ -809,10 +809,10 @@ class GuiMain(QMainWindow):
@pyqtSlot()
@pyqtSlot(int)
- def showProjectSettingsDialog(self, focusTab: int = GuiProjectSettings.TAB_MAIN) -> None:
+ def showProjectSettingsDialog(self, focusTab: int = GuiProjectSettings.PAGE_SETTINGS) -> None:
"""Open the project settings dialog."""
if SHARED.hasProject:
- dialog = GuiProjectSettings(self, focusTab=focusTab)
+ dialog = GuiProjectSettings(self, gotoPage=focusTab)
dialog.newProjectSettingsReady.connect(self._processProjectSettingsChanges)
dialog.exec_()
return
@@ -1111,13 +1111,15 @@ class GuiMain(QMainWindow):
return
- @pyqtSlot()
- def _processProjectSettingsChanges(self) -> None:
+ @pyqtSlot(bool)
+ def _processProjectSettingsChanges(self, rebuildTrees: bool) -> None:
"""Refresh data dependent on project settings."""
logger.debug("Applying new project settings")
SHARED.updateSpellCheckLanguage()
self.itemDetails.refreshDetails()
self._updateWindowTitle(SHARED.project.data.name)
+ if rebuildTrees:
+ self.rebuildTrees()
return
@pyqtSlot()
From c6ee6746a295ca05fdc59ef0497c7d5635757b18 Mon Sep 17 00:00:00 2001
From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com>
Date: Fri, 26 Jan 2024 19:51:31 +0100
Subject: [PATCH 2/7] Make layout improvements to Project Settings
---
novelwriter/dialogs/projectsettings.py | 170 ++++++++++++-------------
novelwriter/extensions/configlayout.py | 24 ++--
2 files changed, 97 insertions(+), 97 deletions(-)
diff --git a/novelwriter/dialogs/projectsettings.py b/novelwriter/dialogs/projectsettings.py
index 51efce1b..57bd4237 100644
--- a/novelwriter/dialogs/projectsettings.py
+++ b/novelwriter/dialogs/projectsettings.py
@@ -177,17 +177,17 @@ class GuiProjectSettings(QDialog):
rebuildTrees = False
- if self.statusPage.colChanged:
+ if self.statusPage.wasChanged:
newList, delList = self.statusPage.getNewList()
project.setStatusColours(newList, delList)
rebuildTrees = True
- if self.importPage.colChanged:
+ if self.importPage.wasChanged:
newList, delList = self.importPage.getNewList()
project.setImportColours(newList, delList)
rebuildTrees = True
- if self.replacePage.arChanged:
+ if self.replacePage.wasChanged:
newList = self.replacePage.getNewList()
project.data.setAutoReplace(newList)
@@ -227,7 +227,7 @@ class _SettingsPage(NScrollableForm):
def __init__(self, parent: QWidget) -> None:
super().__init__(parent=parent)
- xW = CONFIG.pxInt(250)
+ xW = CONFIG.pxInt(200)
data = SHARED.project.data
self.setHelpTextStyle(SHARED.theme.helpText)
self.setRowIndent(0)
@@ -235,23 +235,23 @@ class _SettingsPage(NScrollableForm):
# Project Name
self.projName = QLineEdit(self)
self.projName.setMaxLength(200)
- self.projName.setMaximumWidth(xW)
+ self.projName.setMinimumWidth(xW)
self.projName.setText(data.name)
self.addRow(
- self.tr("Project name"),
- self.projName,
- self.tr("Changing this will affect the backup path.")
+ self.tr("Project name"), self.projName,
+ self.tr("Changing this will affect the backup path."),
+ stretch=(3, 2)
)
# Project Author
self.projAuthor = QLineEdit(self)
self.projAuthor.setMaxLength(200)
- self.projAuthor.setMaximumWidth(xW)
+ self.projAuthor.setMinimumWidth(xW)
self.projAuthor.setText(data.author)
self.addRow(
- self.tr("Author(s)"),
- self.projAuthor,
- self.tr("Only used when building the manuscript.")
+ self.tr("Author(s)"), self.projAuthor,
+ self.tr("Only used when building the manuscript."),
+ stretch=(2, 1)
)
# Project Language
@@ -260,8 +260,7 @@ class _SettingsPage(NScrollableForm):
for tag, language in CONFIG.listLanguages(CONFIG.LANG_PROJ):
self.projLang.addItem(language, tag)
self.addRow(
- self.tr("Project language"),
- self.projLang,
+ self.tr("Project language"), self.projLang,
self.tr("Only used when building the manuscript.")
)
if (idx := self.projLang.findData(data.language)) != -1:
@@ -275,8 +274,7 @@ class _SettingsPage(NScrollableForm):
for tag, language in SHARED.spelling.listDictionaries():
self.spellLang.addItem(language, tag)
self.addRow(
- self.tr("Spell check language"),
- self.spellLang,
+ self.tr("Spell check language"), self.spellLang,
self.tr("Overrides main preferences.")
)
if (idx := self.spellLang.findData(data.spellLang)) != -1:
@@ -286,8 +284,7 @@ class _SettingsPage(NScrollableForm):
self.doBackup = NSwitch(self)
self.doBackup.setChecked(not data.doBackup)
self.addRow(
- self.tr("Disable backup on close"),
- self.doBackup,
+ self.tr("Disable backup on close"), self.doBackup,
self.tr("Overrides main preferences.")
)
@@ -323,9 +320,9 @@ class _StatusPage(QWidget):
SHARED.project.options.getInt("GuiProjectSettings", colSetting, 130)
)
- self.colDeleted = []
- self.colChanged = False
- self.selColour = QColor(100, 100, 100)
+ self._changed = False
+ self._colDeleted = []
+ self._selColour = QColor(100, 100, 100)
self.iPx = SHARED.theme.baseIconSize
@@ -344,8 +341,6 @@ class _StatusPage(QWidget):
self._addItem(key, entry["name"], entry["cols"], entry["count"])
# List Controls
- # =============
-
self.addButton = QPushButton(SHARED.theme.getIcon("add"), "", self)
self.addButton.clicked.connect(self._newItem)
@@ -359,8 +354,6 @@ class _StatusPage(QWidget):
self.dnButton.clicked.connect(lambda: self._moveItem(1))
# Edit Form
- # =========
-
self.editName = QLineEdit()
self.editName.setMaxLength(40)
self.editName.setPlaceholderText(self.tr("Select item to edit"))
@@ -378,8 +371,6 @@ class _StatusPage(QWidget):
self.saveButton.clicked.connect(self._saveItem)
# Assemble
- # ========
-
self.listControls = QVBoxLayout()
self.listControls.addWidget(self.addButton)
self.listControls.addWidget(self.delButton)
@@ -409,9 +400,18 @@ class _StatusPage(QWidget):
return
+ @property
+ def wasChanged(self) -> bool:
+ """The user changed these settings."""
+ return self._changed
+
+ ##
+ # Methods
+ ##
+
def getNewList(self) -> tuple[list, list]:
"""Return list of entries."""
- if self.colChanged:
+ if self._changed:
newList = []
for n in range(self.listBox.topLevelItemCount()):
item = self.listBox.topLevelItem(n)
@@ -421,7 +421,7 @@ class _StatusPage(QWidget):
"name": item.text(self.COL_LABEL),
"cols": item.data(self.COL_LABEL, self.COL_ROLE),
})
- return newList, self.colDeleted
+ return newList, self._colDeleted
return [], []
@@ -436,12 +436,12 @@ class _StatusPage(QWidget):
@pyqtSlot()
def _selectColour(self) -> None:
"""Open a dialog to select the status icon colour."""
- if self.selColour is not None:
+ if self._selColour is not None:
newCol = QColorDialog.getColor(
- self.selColour, self, self.tr("Select Colour")
+ self._selColour, self, self.tr("Select Colour")
)
if newCol.isValid():
- self.selColour = newCol
+ self._selColour = newCol
pixmap = QPixmap(self.iPx, self.iPx)
pixmap.fill(newCol)
self.colButton.setIcon(QIcon(pixmap))
@@ -452,7 +452,7 @@ class _StatusPage(QWidget):
def _newItem(self) -> None:
"""Create a new status item."""
self._addItem(None, self.tr("New Item"), (100, 100, 100), 0)
- self.colChanged = True
+ self._changed = True
return
@pyqtSlot()
@@ -465,8 +465,8 @@ class _StatusPage(QWidget):
SHARED.error(self.tr("Cannot delete a status item that is in use."))
else:
self.listBox.takeTopLevelItem(iRow)
- self.colDeleted.append(selItem.data(self.COL_LABEL, self.KEY_ROLE))
- self.colChanged = True
+ self._colDeleted.append(selItem.data(self.COL_LABEL, self.KEY_ROLE))
+ self._changed = True
return
@pyqtSlot()
@@ -477,9 +477,9 @@ class _StatusPage(QWidget):
selItem.setText(self.COL_LABEL, simplified(self.editName.text()))
selItem.setIcon(self.COL_LABEL, self.colButton.icon())
selItem.setData(self.COL_LABEL, self.COL_ROLE, (
- self.selColour.red(), self.selColour.green(), self.selColour.blue()
+ self._selColour.red(), self._selColour.green(), self._selColour.blue()
))
- self.colChanged = True
+ self._changed = True
return
@pyqtSlot()
@@ -493,7 +493,7 @@ class _StatusPage(QWidget):
name = selItem.text(self.COL_LABEL)
pixmap = QPixmap(self.iPx, self.iPx)
pixmap.fill(QColor(*cols))
- self.selColour = QColor(*cols)
+ self._selColour = QColor(*cols)
self.editName.setText(name)
self.colButton.setIcon(QIcon(pixmap))
self.editName.selectAll()
@@ -504,7 +504,7 @@ class _StatusPage(QWidget):
else:
pixmap = QPixmap(self.iPx, self.iPx)
pixmap.fill(QColor(100, 100, 100))
- self.selColour = QColor(100, 100, 100)
+ self._selColour = QColor(100, 100, 100)
self.editName.setText("")
self.colButton.setIcon(QIcon(pixmap))
self.editName.setEnabled(False)
@@ -552,7 +552,7 @@ class _StatusPage(QWidget):
if cItem is not None:
cItem.setSelected(True)
- self.colChanged = True
+ self._changed = True
return
@@ -583,7 +583,7 @@ class _ReplacePage(QWidget):
def __init__(self, parent: QWidget) -> None:
super().__init__(parent=parent)
- self.arChanged = False
+ self._changed = False
wCol0 = CONFIG.pxInt(
SHARED.project.options.getInt("GuiProjectSettings", "replaceColW", 130)
@@ -591,16 +591,11 @@ class _ReplacePage(QWidget):
pageLabel = self.tr("Text Replace List for Preview and Export")
# List Box
- # ========
-
self.listBox = QTreeWidget()
- self.listBox.setHeaderLabels([
- self.tr("Keyword"),
- self.tr("Replace With"),
- ])
- self.listBox.itemSelectionChanged.connect(self._selectedItem)
+ self.listBox.setHeaderLabels([self.tr("Keyword"), self.tr("Replace With")])
self.listBox.setColumnWidth(self.COL_KEY, wCol0)
self.listBox.setIndentation(0)
+ self.listBox.itemSelectionChanged.connect(self._selectedItem)
for aKey, aVal in SHARED.project.data.autoReplace.items():
newItem = QTreeWidgetItem(["<%s>" % aKey, aVal])
@@ -610,8 +605,6 @@ class _ReplacePage(QWidget):
self.listBox.setSortingEnabled(True)
# List Controls
- # =============
-
self.addButton = QPushButton(SHARED.theme.getIcon("add"), "")
self.addButton.clicked.connect(self._addEntry)
@@ -619,8 +612,6 @@ class _ReplacePage(QWidget):
self.delButton.clicked.connect(self._delEntry)
# Edit Form
- # =========
-
self.editKey = QLineEdit()
self.editKey.setPlaceholderText(self.tr("Select item to edit"))
self.editKey.setEnabled(False)
@@ -634,8 +625,6 @@ class _ReplacePage(QWidget):
self.saveButton.clicked.connect(self._saveEntry)
# Assemble
- # ========
-
self.listControls = QVBoxLayout()
self.listControls.addWidget(self.addButton)
self.listControls.addWidget(self.delButton)
@@ -663,12 +652,20 @@ class _ReplacePage(QWidget):
return
+ @property
+ def wasChanged(self) -> bool:
+ """The user changed these settings."""
+ return self._changed
+
+ ##
+ # Methods
+ ##
+
def getNewList(self) -> dict:
"""Extract the list from the widget."""
new = {}
for n in range(self.listBox.topLevelItemCount()):
- tItem = self.listBox.topLevelItem(n)
- if tItem is not None:
+ if tItem := self.listBox.topLevelItem(n):
aKey = self._stripNotAllowed(tItem.text(0))
aVal = tItem.text(1)
if len(aKey) > 0:
@@ -680,30 +677,29 @@ class _ReplacePage(QWidget):
return self.listBox.columnWidth(0)
##
- # Internal Functions
+ # Private Slots
##
- def _selectedItem(self) -> bool:
+ @pyqtSlot()
+ def _selectedItem(self) -> None:
"""Extract the details from the selected item and populate the
edit form.
"""
- selItem = self._getSelectedItem()
- if selItem is None:
- return False
- editKey = self._stripNotAllowed(selItem.text(0))
- editVal = selItem.text(1)
- self.editKey.setText(editKey)
- self.editValue.setText(editVal)
- self.editKey.setEnabled(True)
- self.editValue.setEnabled(True)
- self.editKey.selectAll()
- self.editKey.setFocus()
- return True
+ if selItem := self._getSelectedItem():
+ editKey = self._stripNotAllowed(selItem.text(0))
+ editVal = selItem.text(1)
+ self.editKey.setText(editKey)
+ self.editValue.setText(editVal)
+ self.editKey.setEnabled(True)
+ self.editValue.setEnabled(True)
+ self.editKey.selectAll()
+ self.editKey.setFocus()
+ return
+ @pyqtSlot()
def _saveEntry(self) -> None:
"""Save the form data into the list widget."""
- selItem = self._getSelectedItem()
- if selItem:
+ if selItem := self._getSelectedItem():
newKey = self.editKey.text()
newVal = self.editValue.text()
saveKey = self._stripNotAllowed(newKey)
@@ -715,38 +711,36 @@ class _ReplacePage(QWidget):
self.editKey.setEnabled(False)
self.editValue.setEnabled(False)
self.listBox.clearSelection()
- self.arChanged = True
+ self._changed = True
return
+ @pyqtSlot()
def _addEntry(self) -> None:
"""Add a new list entry."""
saveKey = "" % (self.listBox.topLevelItemCount() + 1)
- newVal = ""
- newItem = QTreeWidgetItem([saveKey, newVal])
- self.listBox.addTopLevelItem(newItem)
+ self.listBox.addTopLevelItem(QTreeWidgetItem([saveKey, ""]))
return
+ @pyqtSlot()
def _delEntry(self) -> None:
"""Delete the selected entry."""
- selItem = self._getSelectedItem()
- if selItem:
+ if selItem := self._getSelectedItem():
self.listBox.takeTopLevelItem(self.listBox.indexOfTopLevelItem(selItem))
- self.arChanged = True
+ self._changed = True
return
+ ##
+ # Internal Functions
+ ##
+
def _getSelectedItem(self) -> QTreeWidgetItem | None:
"""Extract the currently selected item."""
- selItem = self.listBox.selectedItems()
- if len(selItem) == 0:
- return None
- return selItem[0]
+ if items := self.listBox.selectedItems():
+ return items[0]
+ return None
def _stripNotAllowed(self, key: str) -> str:
"""Clean up the replace key string."""
- result = ""
- for c in key:
- if c.isalnum():
- result += c
- return result
+ return "".join(c for c in key if c.isalnum())
# END Class _ReplacePage
diff --git a/novelwriter/extensions/configlayout.py b/novelwriter/extensions/configlayout.py
index 2db50ded..39e1e651 100644
--- a/novelwriter/extensions/configlayout.py
+++ b/novelwriter/extensions/configlayout.py
@@ -134,10 +134,11 @@ class NScrollableForm(QScrollArea):
return
def addRow(self, label: str, widget: QWidget, helpText: str = "", unit: str | None = None,
- button: QWidget | None = None, editable: str | None = None) -> None:
+ button: QWidget | None = None, editable: str | None = None,
+ stretch: tuple[int, int] = (0, 0)) -> None:
"""Add a label and a widget as a new row of the form."""
row = QHBoxLayout()
- row.setSpacing(CONFIG.pxInt(4))
+ row.setSpacing(CONFIG.pxInt(12))
qLabel = QLabel(label, self)
qLabel.setIndent(self._indent)
@@ -151,19 +152,24 @@ class NScrollableForm(QScrollArea):
labelBox.addWidget(qHelp)
labelBox.setSpacing(0)
labelBox.addStretch(1)
- row.addLayout(labelBox)
+ row.addLayout(labelBox, stretch[0])
if editable:
self._editable[editable] = qHelp
else:
- row.addWidget(qLabel)
-
- row.addSpacing(CONFIG.pxInt(12))
- row.addWidget(widget)
+ row.addWidget(qLabel, stretch[0])
if isinstance(unit, str):
- row.addWidget(QLabel(unit, self))
+ box = QHBoxLayout()
+ box.addWidget(widget)
+ box.addWidget(QLabel(unit, self))
+ row.addLayout(box, stretch[1])
elif isinstance(button, QAbstractButton):
- row.addWidget(button)
+ box = QHBoxLayout()
+ box.addWidget(widget)
+ box.addWidget(button)
+ row.addLayout(box, stretch[1])
+ else:
+ row.addWidget(widget, stretch[1])
self._layout.addLayout(row)
self._index[label.strip()] = widget
From 0dc47194007b27953d7de2fac3d695ee8d2546f5 Mon Sep 17 00:00:00 2001
From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com>
Date: Fri, 26 Jan 2024 19:51:54 +0100
Subject: [PATCH 3/7] Fix log formatting for longer file names
---
novelwriter/__init__.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/novelwriter/__init__.py b/novelwriter/__init__.py
index 5b3fe49c..164c5b35 100644
--- a/novelwriter/__init__.py
+++ b/novelwriter/__init__.py
@@ -131,7 +131,7 @@ def main(sysArgs: list | None = None):
elif inOpt == "--debug":
CONFIG.isDebug = True
logLevel = logging.DEBUG
- logFormat = "[{asctime:}] {filename:>17}:{lineno:<4d} {levelname:8} {message:}"
+ logFormat = "[{asctime:}] {filename:>18}:{lineno:<4d} {levelname:8} {message:}"
elif inOpt == "--style":
qtStyle = inArg
elif inOpt == "--config":
From 3761b1729f2f4e466beddb65a69a82c95725dc70 Mon Sep 17 00:00:00 2001
From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com>
Date: Fri, 26 Jan 2024 21:31:14 +0100
Subject: [PATCH 4/7] Make the style of config dialogs consistent
---
novelwriter/dialogs/preferences.py | 4 +-
novelwriter/dialogs/projectsettings.py | 82 ++++++++++++-----------
novelwriter/extensions/configlayout.py | 91 ++++++++++++++++++++------
novelwriter/tools/noveldetails.py | 52 ++++++++-------
4 files changed, 144 insertions(+), 85 deletions(-)
diff --git a/novelwriter/dialogs/preferences.py b/novelwriter/dialogs/preferences.py
index 5ece68b1..7653734e 100644
--- a/novelwriter/dialogs/preferences.py
+++ b/novelwriter/dialogs/preferences.py
@@ -59,9 +59,9 @@ class GuiPreferences(QDialog):
# Title
self.titleLabel = NColourLabel(
- self.tr("Preferences"), SHARED.theme.helpText, parent=self, scale=1.25
+ self.tr("Preferences"), SHARED.theme.helpText,
+ parent=self, scale=NColourLabel.HEADER_SCALE, indent=CONFIG.pxInt(4)
)
- self.titleLabel.setIndent(CONFIG.pxInt(4))
# Search Box
self.searchText = QLineEdit(self)
diff --git a/novelwriter/dialogs/projectsettings.py b/novelwriter/dialogs/projectsettings.py
index 57bd4237..b7f50f24 100644
--- a/novelwriter/dialogs/projectsettings.py
+++ b/novelwriter/dialogs/projectsettings.py
@@ -29,15 +29,15 @@ import logging
from PyQt5.QtGui import QCloseEvent, QColor, QIcon, QPixmap
from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot
from PyQt5.QtWidgets import (
- QColorDialog, QComboBox, QDialog, QDialogButtonBox, QHBoxLayout, QLabel,
- QLineEdit, QPushButton, QStackedWidget, QTreeWidget, QTreeWidgetItem,
- QVBoxLayout, QWidget, qApp
+ QColorDialog, QComboBox, QDialog, QDialogButtonBox, QHBoxLayout, QLineEdit,
+ QPushButton, QStackedWidget, QTreeWidget, QTreeWidgetItem, QVBoxLayout,
+ QWidget, qApp
)
from novelwriter import CONFIG, SHARED
from novelwriter.common import simplified
from novelwriter.extensions.switch import NSwitch
-from novelwriter.extensions.configlayout import NColourLabel, NScrollableForm
+from novelwriter.extensions.configlayout import NColourLabel, NFixedPage, NScrollableForm
from novelwriter.extensions.pagedsidebar import NPagedSideBar
logger = logging.getLogger(__name__)
@@ -59,21 +59,18 @@ class GuiProjectSettings(QDialog):
self.setObjectName("GuiProjectSettings")
self.setWindowTitle(self.tr("Project Settings"))
- wW = CONFIG.pxInt(500)
- wH = CONFIG.pxInt(400)
options = SHARED.project.options
-
- self.setMinimumSize(wW, wH)
+ self.setMinimumSize(CONFIG.pxInt(500), CONFIG.pxInt(400))
self.resize(
- CONFIG.pxInt(options.getInt("GuiProjectSettings", "winWidth", wW)),
- CONFIG.pxInt(options.getInt("GuiProjectSettings", "winHeight", wH))
+ CONFIG.pxInt(options.getInt("GuiProjectSettings", "winWidth", CONFIG.pxInt(650))),
+ CONFIG.pxInt(options.getInt("GuiProjectSettings", "winHeight", CONFIG.pxInt(500)))
)
# Title
self.titleLabel = NColourLabel(
- self.tr("Project Settings"), SHARED.theme.helpText, parent=self, scale=1.25
+ self.tr("Project Settings"), SHARED.theme.helpText,
+ parent=self, scale=NColourLabel.HEADER_SCALE, indent=CONFIG.pxInt(4)
)
- self.titleLabel.setIndent(CONFIG.pxInt(4))
# SideBar
self.sidebar = NPagedSideBar(self)
@@ -251,31 +248,33 @@ class _SettingsPage(NScrollableForm):
self.addRow(
self.tr("Author(s)"), self.projAuthor,
self.tr("Only used when building the manuscript."),
- stretch=(2, 1)
+ stretch=(3, 2)
)
# Project Language
self.projLang = QComboBox(self)
- self.projLang.setMaximumWidth(xW)
+ self.projLang.setMinimumWidth(xW)
for tag, language in CONFIG.listLanguages(CONFIG.LANG_PROJ):
self.projLang.addItem(language, tag)
self.addRow(
self.tr("Project language"), self.projLang,
- self.tr("Only used when building the manuscript.")
+ 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 = QComboBox(self)
- self.spellLang.setMaximumWidth(xW)
+ self.spellLang.setMinimumWidth(xW)
self.spellLang.addItem(self.tr("Default"), "None")
if CONFIG.hasEnchant:
for tag, language in SHARED.spelling.listDictionaries():
self.spellLang.addItem(language, tag)
self.addRow(
self.tr("Spell check language"), self.spellLang,
- self.tr("Overrides main preferences.")
+ self.tr("Overrides main preferences."),
+ stretch=(3, 2)
)
if (idx := self.spellLang.findData(data.spellLang)) != -1:
self.spellLang.setCurrentIndex(idx)
@@ -295,7 +294,7 @@ class _SettingsPage(NScrollableForm):
# END Class _SettingsPage
-class _StatusPage(QWidget):
+class _StatusPage(NFixedPage):
COL_LABEL = 0
COL_USAGE = 1
@@ -326,9 +325,13 @@ class _StatusPage(QWidget):
self.iPx = SHARED.theme.baseIconSize
- # The List
- # ========
+ # Title
+ self.pageTitle = NColourLabel(
+ pageLabel, SHARED.theme.helpText, parent=self,
+ scale=NColourLabel.HEADER_SCALE
+ )
+ # List Box
self.listBox = QTreeWidget(self)
self.listBox.setHeaderLabels([
self.tr("Label"), self.tr("Usage"),
@@ -392,11 +395,10 @@ class _StatusPage(QWidget):
self.innerBox.addLayout(self.listControls)
self.outerBox = QVBoxLayout()
- self.outerBox.addWidget(QLabel("%s" % pageLabel))
+ self.outerBox.addWidget(self.pageTitle)
self.outerBox.addLayout(self.innerBox)
- self.outerBox.setContentsMargins(0, 0, 0, 0)
- self.setLayout(self.outerBox)
+ self.setCentralLayout(self.outerBox)
return
@@ -422,7 +424,6 @@ class _StatusPage(QWidget):
"cols": item.data(self.COL_LABEL, self.COL_ROLE),
})
return newList, self._colDeleted
-
return [], []
def columnWidth(self) -> int:
@@ -517,16 +518,16 @@ class _StatusPage(QWidget):
##
def _addItem(self, key: str | None, name: str,
- cols: tuple[int, int, int], count: int) -> None:
+ colour: tuple[int, int, int], count: int) -> None:
"""Add a status item to the list."""
pixmap = QPixmap(self.iPx, self.iPx)
- pixmap.fill(QColor(*cols))
+ pixmap.fill(QColor(*colour))
item = QTreeWidgetItem()
item.setText(self.COL_LABEL, name)
item.setIcon(self.COL_LABEL, QIcon(pixmap))
item.setData(self.COL_LABEL, self.KEY_ROLE, key)
- item.setData(self.COL_LABEL, self.COL_ROLE, cols)
+ item.setData(self.COL_LABEL, self.COL_ROLE, colour)
item.setData(self.COL_LABEL, self.NUM_ROLE, count)
item.setText(self.COL_USAGE, self._usageString(count))
@@ -558,24 +559,23 @@ class _StatusPage(QWidget):
def _getSelectedItem(self) -> QTreeWidgetItem | None:
"""Get the currently selected item."""
- selItem = self.listBox.selectedItems()
- if len(selItem) > 0:
- return selItem[0]
+ if items := self.listBox.selectedItems():
+ return items[0]
return None
- def _usageString(self, nUse: int) -> str:
+ def _usageString(self, count: int) -> str:
"""Generate usage string."""
- if nUse == 0:
+ if count == 0:
return self.tr("Not in use")
- elif nUse == 1:
+ elif count == 1:
return self.tr("Used once")
else:
- return self.tr("Used by {0} items").format(nUse)
+ return self.tr("Used by {0} items").format(count)
# END Class _StatusPage
-class _ReplacePage(QWidget):
+class _ReplacePage(NFixedPage):
COL_KEY = 0
COL_REPL = 1
@@ -588,7 +588,12 @@ class _ReplacePage(QWidget):
wCol0 = CONFIG.pxInt(
SHARED.project.options.getInt("GuiProjectSettings", "replaceColW", 130)
)
- pageLabel = self.tr("Text Replace List for Preview and Export")
+
+ # Title
+ self.pageTitle = NColourLabel(
+ self.tr("Text Auto-Replace for Preview and Build"),
+ SHARED.theme.helpText, parent=self, scale=NColourLabel.HEADER_SCALE
+ )
# List Box
self.listBox = QTreeWidget()
@@ -644,11 +649,10 @@ class _ReplacePage(QWidget):
self.innerBox.addLayout(self.listControls)
self.outerBox = QVBoxLayout()
- self.outerBox.addWidget(QLabel("%s" % pageLabel))
+ self.outerBox.addWidget(self.pageTitle)
self.outerBox.addLayout(self.innerBox)
- self.outerBox.setContentsMargins(0, 0, 0, 0)
- self.setLayout(self.outerBox)
+ self.setCentralLayout(self.outerBox)
return
diff --git a/novelwriter/extensions/configlayout.py b/novelwriter/extensions/configlayout.py
index 39e1e651..809068bc 100644
--- a/novelwriter/extensions/configlayout.py
+++ b/novelwriter/extensions/configlayout.py
@@ -6,6 +6,8 @@ File History:
Created: 2020-05-03 [0.4.5] NConfigLayout, NColourLabel
Created: 2023-05-23 [2.1b1] NSimpleLayout
Created: 2024-01-08 [2.3b1] NScrollableForm
+Created: 2024-01-26 [2.3b1] NScrollablePage
+Created: 2024-01-26 [2.3b1] NFixedPage
This file is a part of novelWriter
Copyright 2018–2024, Veronica Berglyd Olsen
@@ -28,17 +30,59 @@ from __future__ import annotations
from PyQt5.QtGui import QColor, QPalette
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (
- QAbstractButton, QGridLayout, QHBoxLayout, QLabel, QLineEdit, QScrollArea, QSizePolicy,
- QVBoxLayout, QWidget
+ QAbstractButton, QFrame, QGridLayout, QHBoxLayout, QLabel, QLayout, QLineEdit,
+ QScrollArea, QSizePolicy, QVBoxLayout, QWidget
)
from novelwriter import CONFIG
-FONT_SCALE = 0.9
+DEFAULT_SCALE = 0.9
RIGHT_TOP = Qt.AlignmentFlag.AlignRight | Qt.AlignmentFlag.AlignTop
LEFT_TOP = Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignTop
+class NFixedPage(QFrame):
+ """Extension: Fixed Page Widget
+
+ A custom widget that holds a layout. This is just a wrapper around a
+ QFrame that sets the same frame style as the other Page widgets.
+ """
+
+ def __init__(self, parent: QWidget) -> None:
+ super().__init__(parent=parent)
+ self.setFrameShadow(QFrame.Shadow.Sunken)
+ self.setFrameShape(QFrame.Shape.StyledPanel)
+ self.setCentralLayout = self.setLayout
+ return
+
+# END Class NFixedPage
+
+
+class NScrollablePage(QScrollArea):
+ """Extension: Scrollable Page Widget
+
+ A custom widget that holds a layout within a scrollable area.
+ """
+
+ def __init__(self, parent: QWidget) -> None:
+ super().__init__(parent=parent)
+ self._widget = QWidget(self)
+ self.setWidget(self._widget)
+ self.setWidgetResizable(True)
+ self.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
+ self.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
+ self.setFrameShadow(QFrame.Shadow.Sunken)
+ self.setFrameShape(QFrame.Shape.StyledPanel)
+ return
+
+ def setCentralLayout(self, layout: QLayout) -> None:
+ """Set the central layout of the scroll page."""
+ self._widget.setLayout(layout)
+ return
+
+# END Class NScrollablePage
+
+
class NScrollableForm(QScrollArea):
"""Extension: Scrollable Form Widget
@@ -48,7 +92,7 @@ class NScrollableForm(QScrollArea):
def __init__(self, parent: QWidget) -> None:
super().__init__(parent=parent)
self._helpCol = QColor(0, 0, 0)
- self._fontScale = FONT_SCALE
+ self._fontScale = DEFAULT_SCALE
self._first = True
self._indent = CONFIG.pxInt(12)
@@ -66,6 +110,8 @@ class NScrollableForm(QScrollArea):
self.setWidgetResizable(True)
self.setHorizontalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
self.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
+ self.setFrameShadow(QFrame.Shadow.Sunken)
+ self.setFrameShape(QFrame.Shape.StyledPanel)
return
@@ -81,7 +127,7 @@ class NScrollableForm(QScrollArea):
# Setters
##
- def setHelpTextStyle(self, color: QColor, scale: float = FONT_SCALE) -> None:
+ def setHelpTextStyle(self, color: QColor, scale: float = DEFAULT_SCALE) -> None:
"""Set the text color for the help text."""
self._helpCol = color
self._fontScale = scale
@@ -145,13 +191,14 @@ class NScrollableForm(QScrollArea):
qLabel.setBuddy(widget)
if helpText:
- qHelp = NColourLabel(str(helpText), self._helpCol, scale=self._fontScale, wrap=True)
- qHelp.setIndent(self._indent)
+ qHelp = NColourLabel(
+ str(helpText), self._helpCol, parent=self,
+ scale=self._fontScale, wrap=True, indent=self._indent
+ )
labelBox = QVBoxLayout()
labelBox.addWidget(qLabel)
labelBox.addWidget(qHelp)
labelBox.setSpacing(0)
- labelBox.addStretch(1)
row.addLayout(labelBox, stretch[0])
if editable:
self._editable[editable] = qHelp
@@ -193,7 +240,7 @@ class NConfigLayout(QGridLayout):
self._nextRow = 0
self._helpCol = QColor(0, 0, 0)
- self._fontScale = FONT_SCALE
+ self._fontScale = DEFAULT_SCALE
self._itemMap = {}
wSp = CONFIG.pxInt(8)
@@ -207,7 +254,7 @@ class NConfigLayout(QGridLayout):
# Getters and Setters
##
- def setHelpTextStyle(self, color: QColor, scale: float = FONT_SCALE) -> None:
+ def setHelpTextStyle(self, color: QColor, scale: float = DEFAULT_SCALE) -> None:
"""Set the text color for the help text."""
self._helpCol = color if isinstance(color, QColor) else QColor(*color)
self._fontScale = scale
@@ -238,8 +285,10 @@ class NConfigLayout(QGridLayout):
qHelp = None
if helpText is not None:
- qHelp = NColourLabel(str(helpText), self._helpCol, scale=self._fontScale, wrap=True)
- qHelp.setIndent(wSp)
+ qHelp = NColourLabel(
+ str(helpText), self._helpCol,
+ scale=self._fontScale, wrap=True, indent=wSp
+ )
labelBox = QVBoxLayout()
labelBox.addWidget(qLabel)
labelBox.addWidget(qHelp)
@@ -337,17 +386,21 @@ class NColourLabel(QLabel):
optionally at a specific size, and word wrapped.
"""
+ HELP_SCALE = DEFAULT_SCALE
+ HEADER_SCALE = 1.25
+
def __init__(self, text: str, color: QColor, parent: QWidget | None = None,
- scale: float = FONT_SCALE, wrap: bool = False) -> None:
+ scale: float = HELP_SCALE, wrap: bool = False, indent: int = 0) -> None:
super().__init__(text, parent=parent)
- lblCol = self.palette()
- lblCol.setColor(QPalette.WindowText, color)
- self.setPalette(lblCol)
+ font = self.font()
+ font.setPointSizeF(scale*font.pointSizeF())
+ colour = self.palette()
+ colour.setColor(QPalette.WindowText, color)
- lblFont = self.font()
- lblFont.setPointSizeF(scale*lblFont.pointSizeF())
- self.setFont(lblFont)
+ self.setPalette(colour)
+ self.setFont(font)
+ self.setIndent(indent)
if wrap:
self.setWordWrap(True)
diff --git a/novelwriter/tools/noveldetails.py b/novelwriter/tools/noveldetails.py
index 3fcd54cc..71375d7f 100644
--- a/novelwriter/tools/noveldetails.py
+++ b/novelwriter/tools/noveldetails.py
@@ -38,14 +38,12 @@ from novelwriter import CONFIG, SHARED
from novelwriter.common import formatTime, numberToRoman
from novelwriter.constants import nwUnicode
from novelwriter.extensions.switch import NSwitch
-from novelwriter.extensions.configlayout import NColourLabel
+from novelwriter.extensions.configlayout import NColourLabel, NFixedPage, NScrollablePage
from novelwriter.extensions.pagedsidebar import NPagedSideBar
from novelwriter.extensions.novelselector import NovelSelector
logger = logging.getLogger(__name__)
-HEADER_SIZE = 1.4
-
class GuiNovelDetails(QDialog):
@@ -59,21 +57,18 @@ class GuiNovelDetails(QDialog):
self.setObjectName("GuiNovelDetails")
self.setWindowTitle(self.tr("Novel Details"))
- wW = CONFIG.pxInt(500)
- wH = CONFIG.pxInt(400)
options = SHARED.project.options
-
- self.setMinimumSize(wW, wH)
+ self.setMinimumSize(CONFIG.pxInt(500), CONFIG.pxInt(400))
self.resize(
- CONFIG.pxInt(options.getInt("GuiNovelDetails", "winWidth", wW)),
- CONFIG.pxInt(options.getInt("GuiNovelDetails", "winHeight", wH))
+ CONFIG.pxInt(options.getInt("GuiNovelDetails", "winWidth", CONFIG.pxInt(650))),
+ CONFIG.pxInt(options.getInt("GuiNovelDetails", "winHeight", CONFIG.pxInt(500)))
)
# Title
self.titleLabel = NColourLabel(
- self.tr("Novel Details"), SHARED.theme.helpText, parent=self, scale=1.25
+ self.tr("Novel Details"), SHARED.theme.helpText,
+ parent=self, scale=NColourLabel.HEADER_SCALE, indent=CONFIG.pxInt(4)
)
- self.titleLabel.setIndent(CONFIG.pxInt(4))
# Novel Selector
self.novelSelector = NovelSelector(self)
@@ -192,7 +187,7 @@ class GuiNovelDetails(QDialog):
# END Class GuiNovelDetails
-class _OverviewPage(QWidget):
+class _OverviewPage(NScrollablePage):
def __init__(self, parent: QWidget) -> None:
super().__init__(parent=parent)
@@ -204,7 +199,8 @@ class _OverviewPage(QWidget):
# Project Info
self.projLabel = NColourLabel(
- self.tr("Project"), SHARED.theme.helpText, parent=self, scale=HEADER_SIZE
+ self.tr("Project"), SHARED.theme.helpText,
+ parent=self, scale=NColourLabel.HEADER_SCALE
)
self.projName = QLabel("", self)
@@ -227,7 +223,8 @@ class _OverviewPage(QWidget):
# Novel Info
self.novelLabel = NColourLabel(
- self.tr("Selected Novel"), SHARED.theme.helpText, parent=self, scale=HEADER_SIZE
+ self.tr("Selected Novel"), SHARED.theme.helpText,
+ parent=self, scale=NColourLabel.HEADER_SCALE
)
self.novelName = QLabel("", self)
@@ -250,11 +247,10 @@ class _OverviewPage(QWidget):
self.outerBox.addLayout(self.projForm)
self.outerBox.addWidget(self.novelLabel)
self.outerBox.addLayout(self.novelForm)
- self.outerBox.setContentsMargins(0, 0, 0, 0)
self.outerBox.setSpacing(sPx)
self.outerBox.addStretch(1)
- self.setLayout(self.outerBox)
+ self.setCentralLayout(self.outerBox)
return
@@ -299,7 +295,7 @@ class _OverviewPage(QWidget):
# END Class _OverviewPage
-class _ContentsPage(QWidget):
+class _ContentsPage(NFixedPage):
C_TITLE = 0
C_WORDS = 1
@@ -320,7 +316,8 @@ class _ContentsPage(QWidget):
# Title
self.contentLabel = NColourLabel(
- self.tr("Table of Contents"), SHARED.theme.helpText, parent=self, scale=HEADER_SIZE
+ self.tr("Table of Contents"), SHARED.theme.helpText,
+ parent=self, scale=NColourLabel.HEADER_SCALE
)
# Contents Tree
@@ -407,20 +404,25 @@ class _ContentsPage(QWidget):
self.outerBox.addWidget(self.contentLabel)
self.outerBox.addWidget(self.tocTree)
self.outerBox.addLayout(self.optionsBox)
- self.outerBox.setContentsMargins(0, 0, 0, 0)
- self.setLayout(self.outerBox)
+ self.setCentralLayout(self.outerBox)
return
def saveSettings(self) -> None:
"""Save the user GUI settings."""
+ widthCol0 = CONFIG.rpxInt(self.tocTree.columnWidth(0))
+ widthCol1 = CONFIG.rpxInt(self.tocTree.columnWidth(1))
+ widthCol2 = CONFIG.rpxInt(self.tocTree.columnWidth(2))
+ widthCol3 = CONFIG.rpxInt(self.tocTree.columnWidth(3))
+ widthCol4 = CONFIG.rpxInt(self.tocTree.columnWidth(4))
+
options = SHARED.project.options
- options.setValue("GuiNovelDetails", "widthCol0", self.tocTree.columnWidth(0))
- options.setValue("GuiNovelDetails", "widthCol1", self.tocTree.columnWidth(1))
- options.setValue("GuiNovelDetails", "widthCol2", self.tocTree.columnWidth(2))
- options.setValue("GuiNovelDetails", "widthCol3", self.tocTree.columnWidth(3))
- options.setValue("GuiNovelDetails", "widthCol4", self.tocTree.columnWidth(4))
+ options.setValue("GuiNovelDetails", "widthCol0", widthCol0)
+ options.setValue("GuiNovelDetails", "widthCol1", widthCol1)
+ options.setValue("GuiNovelDetails", "widthCol2", widthCol2)
+ options.setValue("GuiNovelDetails", "widthCol3", widthCol3)
+ options.setValue("GuiNovelDetails", "widthCol4", widthCol4)
options.setValue("GuiNovelDetails", "wordsPerPage", self.wpValue.value())
options.setValue("GuiNovelDetails", "countFrom", self.poValue.value())
options.setValue("GuiNovelDetails", "clearDouble", self.dblValue.isChecked())
From a7a2eaff557df34be89a4c7a38f3a9a899807548 Mon Sep 17 00:00:00 2001
From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com>
Date: Fri, 26 Jan 2024 21:36:05 +0100
Subject: [PATCH 5/7] Delete the old config dialog base class
---
novelwriter/extensions/pageddialog.py | 130 --------------------------
1 file changed, 130 deletions(-)
delete mode 100644 novelwriter/extensions/pageddialog.py
diff --git a/novelwriter/extensions/pageddialog.py b/novelwriter/extensions/pageddialog.py
deleted file mode 100644
index a620cb74..00000000
--- a/novelwriter/extensions/pageddialog.py
+++ /dev/null
@@ -1,130 +0,0 @@
-"""
-novelWriter – Custom Widget: Paged Dialog
-=========================================
-
-File History:
-Created: 2020-05-17 [0.5.1]
-
-This file is a part of novelWriter
-Copyright 2018–2024, Veronica Berglyd Olsen
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program. If not, see .
-"""
-from __future__ import annotations
-
-from PyQt5.QtGui import QPaintEvent
-from PyQt5.QtCore import QRect, QPoint, QSize
-from PyQt5.QtWidgets import (
- QDialog, QHBoxLayout, QStyle, QStyleOptionTab, QStylePainter, QTabBar,
- QTabWidget, QVBoxLayout, QWidget
-)
-
-from novelwriter import CONFIG
-
-
-class NPagedDialog(QDialog):
-
- def __init__(self, parent: QWidget) -> None:
- super().__init__(parent=parent)
-
- self._tabBar = NVerticalTabBar(self)
- self._tabBar.setExpanding(False)
-
- self._tabBox = QTabWidget(self)
- self._tabBox.setTabBar(self._tabBar)
- self._tabBox.setTabPosition(QTabWidget.West)
-
- self._buttonBox = QHBoxLayout()
-
- self._outerBox = QVBoxLayout()
- self._outerBox.addWidget(self._tabBox)
- self._outerBox.addLayout(self._buttonBox)
-
- # Default Margins
- thisStyle = self.style()
- mL = thisStyle.pixelMetric(QStyle.PM_LayoutLeftMargin)
- mR = thisStyle.pixelMetric(QStyle.PM_LayoutRightMargin)
- mT = thisStyle.pixelMetric(QStyle.PM_LayoutLeftMargin)
- mB = thisStyle.pixelMetric(QStyle.PM_LayoutBottomMargin)
-
- # Set Margins
- self.setContentsMargins(0, 0, 0, 0)
- self._outerBox.setContentsMargins(0, 0, 0, mB)
- self._buttonBox.setContentsMargins(mL, 0, mR, 0)
- self._outerBox.setSpacing(mT)
-
- self.setLayout(self._outerBox)
-
- return
-
- def addTab(self, widget: QWidget, label: str) -> None:
- """Forward the adding of tabs to the QTabWidget."""
- self._tabBox.addTab(widget, label)
- return
-
- def addControls(self, buttonBar: QWidget) -> None:
- """Add a button bar to the dialog."""
- self._buttonBox.addWidget(buttonBar)
- return
-
- def setCurrentWidget(self, widget: QWidget) -> None:
- """Forward the changing of tab to the QTabWidget."""
- self._tabBox.setCurrentWidget(widget)
- return
-
-# END Class NPagedDialog
-
-
-class NVerticalTabBar(QTabBar):
-
- def __init__(self, parent: QWidget) -> None:
- super().__init__(parent=parent)
- self._mW = CONFIG.pxInt(150)
- return
-
- def tabSizeHint(self, index: int) -> QSize:
- """Return a transposed size hint for the rotated bar."""
- tSize = super().tabSizeHint(index)
- tSize.transpose()
- tSize.setWidth(min(tSize.width(), self._mW))
- return tSize
-
- def paintEvent(self, event: QPaintEvent) -> None:
- """Custom implementation of the label painter that rotates the
- label 90 degrees.
- """
- pObj = QStylePainter(self)
- oObj = QStyleOptionTab()
-
- for i in range(self.count()):
- self.initStyleOption(oObj, i)
- pObj.drawControl(QStyle.CE_TabBarTabShape, oObj)
- pObj.save()
-
- oSize = oObj.rect.size()
- oSize.transpose()
- oRect = QRect(QPoint(), oSize)
- oRect.moveCenter(oObj.rect.center())
- oObj.rect = oRect
-
- oCenter = self.tabRect(i).center()
- pObj.translate(oCenter)
- pObj.rotate(90)
- pObj.translate(-oCenter)
- pObj.drawControl(QStyle.CE_TabBarTabLabel, oObj)
- pObj.restore()
-
- return
-
-# END Class NVerticalTabBar
From 40a8d728bb205c912349c67b8901347c9d2be494 Mon Sep 17 00:00:00 2001
From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com>
Date: Fri, 26 Jan 2024 22:32:20 +0100
Subject: [PATCH 6/7] Update project settings tests
---
novelwriter/dialogs/projectsettings.py | 16 +-
...ettings.py => test_dlg_projectsettings.py} | 285 +++++++++---------
2 files changed, 143 insertions(+), 158 deletions(-)
rename tests/test_dialogs/{test_dlg_projsettings.py => test_dlg_projectsettings.py} (50%)
diff --git a/novelwriter/dialogs/projectsettings.py b/novelwriter/dialogs/projectsettings.py
index b7f50f24..f6ff7730 100644
--- a/novelwriter/dialogs/projectsettings.py
+++ b/novelwriter/dialogs/projectsettings.py
@@ -90,6 +90,8 @@ class GuiProjectSettings(QDialog):
self.buttonBox.rejected.connect(self.close)
# Content
+ SHARED.project.countStatus()
+
self.settingsPage = _SettingsPage(self)
self.statusPage = _StatusPage(self, True)
self.importPage = _StatusPage(self, False)
@@ -307,12 +309,12 @@ class _StatusPage(NFixedPage):
super().__init__(parent=parent)
if isStatus:
- self.theStatus = SHARED.project.data.itemStatus
- pageLabel = self.tr("Novel File Status Levels")
+ status = SHARED.project.data.itemStatus
+ pageLabel = self.tr("Novel Document Status Levels")
colSetting = "statusColW"
else:
- self.theStatus = SHARED.project.data.itemImport
- pageLabel = self.tr("Note File Importance Levels")
+ status = SHARED.project.data.itemImport
+ pageLabel = self.tr("Project Note Importance Levels")
colSetting = "importColW"
wCol0 = CONFIG.pxInt(
@@ -333,14 +335,12 @@ class _StatusPage(NFixedPage):
# List Box
self.listBox = QTreeWidget(self)
- self.listBox.setHeaderLabels([
- self.tr("Label"), self.tr("Usage"),
- ])
+ self.listBox.setHeaderLabels([self.tr("Label"), self.tr("Usage")])
self.listBox.itemSelectionChanged.connect(self._selectedItem)
self.listBox.setColumnWidth(self.COL_LABEL, wCol0)
self.listBox.setIndentation(0)
- for key, entry in self.theStatus.items():
+ for key, entry in status.items():
self._addItem(key, entry["name"], entry["cols"], entry["count"])
# List Controls
diff --git a/tests/test_dialogs/test_dlg_projsettings.py b/tests/test_dialogs/test_dlg_projectsettings.py
similarity index 50%
rename from tests/test_dialogs/test_dlg_projsettings.py
rename to tests/test_dialogs/test_dlg_projectsettings.py
index 37556245..5b4d5499 100644
--- a/tests/test_dialogs/test_dlg_projsettings.py
+++ b/tests/test_dialogs/test_dlg_projectsettings.py
@@ -31,7 +31,7 @@ from PyQt5.QtWidgets import QDialog, QAction, QColorDialog
from novelwriter import CONFIG, SHARED
from novelwriter.enum import nwItemType
from novelwriter.dialogs.editlabel import GuiEditLabel
-from novelwriter.dialogs.projsettings import GuiProjectSettings
+from novelwriter.dialogs.projectsettings import GuiProjectSettings
KEY_DELAY = 1
@@ -63,17 +63,17 @@ def testDlgProjSettings_Dialog(qtbot, monkeypatch, nwGUI):
qtbot.addWidget(projSettings)
# Switch Tabs
- projSettings._focusTab(GuiProjectSettings.TAB_REPLACE)
- assert projSettings._tabBox.currentWidget() == projSettings.tabReplace
+ projSettings.sidebar.button(GuiProjectSettings.PAGE_SETTINGS).click()
+ assert projSettings.mainStack.currentWidget() == projSettings.settingsPage
- projSettings._focusTab(GuiProjectSettings.TAB_IMPORT)
- assert projSettings._tabBox.currentWidget() == projSettings.tabImport
+ projSettings.sidebar.button(GuiProjectSettings.PAGE_STATUS).click()
+ assert projSettings.mainStack.currentWidget() == projSettings.statusPage
- projSettings._focusTab(GuiProjectSettings.TAB_STATUS)
- assert projSettings._tabBox.currentWidget() == projSettings.tabStatus
+ projSettings.sidebar.button(GuiProjectSettings.PAGE_IMPORT).click()
+ assert projSettings.mainStack.currentWidget() == projSettings.importPage
- projSettings._focusTab(GuiProjectSettings.TAB_MAIN)
- assert projSettings._tabBox.currentWidget() == projSettings.tabMain
+ projSettings.sidebar.button(GuiProjectSettings.PAGE_REPLACE).click()
+ assert projSettings.mainStack.currentWidget() == projSettings.replacePage
# Clean Up
projSettings.close()
@@ -83,9 +83,11 @@ def testDlgProjSettings_Dialog(qtbot, monkeypatch, nwGUI):
@pytest.mark.gui
-def testDlgProjSettings_Main(qtbot, monkeypatch, nwGUI, fncPath, projPath, mockRnd):
- """Test the main tab of the project settings dialog."""
- monkeypatch.setattr(SHARED._spelling, "listDictionaries", lambda: [("en", "English [en]")])
+def testDlgProjSettings_SettingsPage(qtbot, monkeypatch, nwGUI, fncPath, projPath, mockRnd):
+ """Test the settings page of the dialog."""
+ languages = [("en", "English"), ("de", "German")]
+ monkeypatch.setattr(SHARED._spelling, "listDictionaries", lambda *a: languages)
+ monkeypatch.setattr(CONFIG, "listLanguages", lambda *a: languages)
# Create new project
buildTestProject(nwGUI, projPath)
@@ -94,72 +96,57 @@ def testDlgProjSettings_Main(qtbot, monkeypatch, nwGUI, fncPath, projPath, mockR
# Set some values
project = SHARED.project
+ project.data.setLanguage("en")
project.data.setSpellLang("en")
project.data.setAuthor("Jane Smith")
project.data.setAutoReplace({"A": "B", "C": "D"})
# Create Dialog
- projSettings = GuiProjectSettings(nwGUI, GuiProjectSettings.TAB_MAIN)
+ projSettings = GuiProjectSettings(nwGUI, GuiProjectSettings.PAGE_SETTINGS)
projSettings.show()
qtbot.addWidget(projSettings)
# Settings Tab
- # ============
+ settings = projSettings.settingsPage
- tabMain = projSettings.tabMain
+ assert settings.projName.text() == "New Project"
+ assert settings.projAuthor.text() == "Jane Smith"
+ assert settings.projLang.currentData() == "en"
+ assert settings.spellLang.currentData() == "en"
+ assert settings.doBackup.isChecked() is False
- assert tabMain.editName.text() == "New Project"
- assert tabMain.editTitle.text() == "New Novel"
- assert tabMain.editAuthor.text() == "Jane Smith"
- assert tabMain.spellLang.currentData() == "en"
- assert tabMain.doBackup.isChecked() is False
-
- tabMain.editName.setText("")
- for c in "Project Name":
- qtbot.keyClick(tabMain.editName, c, delay=KEY_DELAY)
- tabMain.editTitle.setText("")
- for c in "Project Title":
- qtbot.keyClick(tabMain.editTitle, c, delay=KEY_DELAY)
-
- tabMain.editAuthor.clear()
- for c in "Jane Doe":
- qtbot.keyClick(tabMain.editAuthor, c, delay=KEY_DELAY)
-
- assert tabMain.editName.text() == "Project Name"
- assert tabMain.editTitle.text() == "Project Title"
- assert tabMain.editAuthor.text() == "Jane Doe"
+ settings.projName.setText("Project Name")
+ settings.projAuthor.setText("Jane Doe")
+ settings.projLang.setCurrentIndex(settings.projLang.findData("de"))
+ settings.spellLang.setCurrentIndex(settings.spellLang.findData("de"))
+ settings.doBackup.setChecked(True)
projSettings._doSave()
assert project.data.name == "Project Name"
- assert project.data.title == "Project Title"
assert project.data.author == "Jane Doe"
+ assert project.data.language == "de"
+ assert project.data.spellLang == "de"
+ assert project.data.doBackup is False
- nwGUI._processProjectSettingsChanges()
+ nwGUI._processProjectSettingsChanges(False)
assert nwGUI.windowTitle() == "novelWriter - Project Name"
# qtbot.stop()
-# END Test testDlgProjSettings_Main
+# END Test testDlgProjSettings_SettingsPage
@pytest.mark.gui
-def testDlgProjSettings_StatusImport(qtbot, monkeypatch, nwGUI, fncPath, projPath, mockRnd):
- """Test the status and importance tabs of the project settings
- dialog.
- """
+def testDlgProjSettings_StatusImport(qtbot, monkeypatch, nwGUI, projPath, mockRnd):
+ """Test the status and importance pages of the dialog."""
monkeypatch.setattr(GuiEditLabel, "getLabel", lambda *a, text: (text, True))
- monkeypatch.setattr(SHARED._spelling, "listDictionaries", lambda: [("en", "English [en]")])
-
- # Create new project
- mockRnd.reset()
buildTestProject(nwGUI, projPath)
- CONFIG.setBackupPath(fncPath)
# Set some values
- theProject = SHARED.project
- theProject.tree[C.hTitlePage].setStatus(C.sFinished) # type: ignore
- theProject.tree[C.hChapterDoc].setStatus(C.sDraft) # type: ignore
- theProject.tree[C.hSceneDoc].setStatus(C.sDraft) # type: ignore
+ project = SHARED.project
+ project.tree[C.hTitlePage].setStatus(C.sFinished) # type: ignore
+ project.tree[C.hChapterDoc].setStatus(C.sDraft) # type: ignore
+ project.tree[C.hSceneDoc].setStatus(C.sDraft) # type: ignore
nwGUI.projView.projTree.setSelectedHandle(C.hPlotRoot)
nwGUI.projView.projTree.newTreeItem(nwItemType.FILE, hLevel=1, isNote=True)
@@ -172,51 +159,54 @@ def testDlgProjSettings_StatusImport(qtbot, monkeypatch, nwGUI, fncPath, projPat
hCharNote = "0000000000011"
hWorldNote = "0000000000012"
- theProject.tree[hPlotNote].setImport(C.iMajor) # type: ignore
- theProject.tree[hCharNote].setImport(C.iMajor) # type: ignore
- theProject.tree[hWorldNote].setImport(C.iMain) # type: ignore
+ project.tree[hPlotNote].setImport(C.iMajor) # type: ignore
+ project.tree[hCharNote].setImport(C.iMajor) # type: ignore
+ project.tree[hWorldNote].setImport(C.iMain) # type: ignore
+
+ nwGUI.rebuildTrees()
+ project.countStatus()
+
+ assert [e["count"] for _, e in project.data.itemStatus.items()] == [2, 0, 2, 1]
+ assert [e["count"] for _, e in project.data.itemImport.items()] == [3, 0, 2, 1]
# Create Dialog
- projSettings = GuiProjectSettings(nwGUI, GuiProjectSettings.TAB_STATUS)
+ projSettings = GuiProjectSettings(nwGUI, GuiProjectSettings.PAGE_STATUS)
projSettings.show()
qtbot.addWidget(projSettings)
# Status Tab
# ==========
- tabStatus = projSettings.tabStatus
+ status = projSettings.statusPage
- assert tabStatus.colChanged is False
- assert tabStatus.getNewList() == ([], [])
- assert tabStatus.listBox.topLevelItemCount() == 4
+ assert status.wasChanged is False
+ assert status.getNewList() == ([], [])
+ assert status.listBox.topLevelItemCount() == 4
# Can't delete the first item (it's in use)
- tabStatus.listBox.clearSelection()
- tabStatus.listBox.setCurrentItem(tabStatus.listBox.topLevelItem(0))
- qtbot.mouseClick(tabStatus.delButton, Qt.LeftButton)
- assert tabStatus.listBox.topLevelItemCount() == 4
+ status.listBox.clearSelection()
+ status.listBox.setCurrentItem(status.listBox.topLevelItem(0))
+ qtbot.mouseClick(status.delButton, Qt.LeftButton)
+ assert status.listBox.topLevelItemCount() == 4
# Can delete the second item
- tabStatus.listBox.clearSelection()
- tabStatus.listBox.setCurrentItem(tabStatus.listBox.topLevelItem(1))
- qtbot.mouseClick(tabStatus.delButton, Qt.LeftButton)
- assert tabStatus.listBox.topLevelItemCount() == 3
+ status.listBox.clearSelection()
+ status.listBox.setCurrentItem(status.listBox.topLevelItem(1))
+ qtbot.mouseClick(status.delButton, Qt.LeftButton)
+ assert status.listBox.topLevelItemCount() == 3
# Add a new item
with monkeypatch.context() as mp:
mp.setattr(QColorDialog, "getColor", lambda *a: QColor(20, 30, 40))
- qtbot.mouseClick(tabStatus.addButton, Qt.LeftButton)
- tabStatus.listBox.setCurrentItem(tabStatus.listBox.topLevelItem(3))
- for _ in range(8):
- qtbot.keyClick(tabStatus.editName, Qt.Key_Backspace, delay=KEY_DELAY)
- for c in "Final":
- qtbot.keyClick(tabStatus.editName, c, delay=KEY_DELAY)
- qtbot.mouseClick(tabStatus.colButton, Qt.LeftButton)
- qtbot.mouseClick(tabStatus.saveButton, Qt.LeftButton)
- assert tabStatus.listBox.topLevelItemCount() == 4
+ status.addButton.click()
+ status.listBox.setCurrentItem(status.listBox.topLevelItem(3))
+ status.editName.setText("Final")
+ status.colButton.click()
+ status.saveButton.click()
+ assert status.listBox.topLevelItemCount() == 4
- assert tabStatus.colChanged is True
- assert tabStatus.getNewList() == (
+ assert status.wasChanged is True
+ assert status.getNewList() == (
[
{
"key": C.sNew,
@@ -241,62 +231,62 @@ def testDlgProjSettings_StatusImport(qtbot, monkeypatch, nwGUI, fncPath, projPat
)
# Move items, none selected -> no change
- tabStatus.listBox.clearSelection()
- tabStatus._moveItem(1)
- assert [x["key"] for x in tabStatus.getNewList()[0]] == [
+ status.listBox.clearSelection()
+ status._moveItem(1)
+ assert [x["key"] for x in status.getNewList()[0]] == [
C.sNew, C.sDraft, C.sFinished, None
]
# Move items, first selected, move up -> no change
- tabStatus.listBox.clearSelection()
- tabStatus.listBox.setCurrentItem(tabStatus.listBox.topLevelItem(0))
- tabStatus._moveItem(-1)
- assert [x["key"] for x in tabStatus.getNewList()[0]] == [
+ status.listBox.clearSelection()
+ status.listBox.setCurrentItem(status.listBox.topLevelItem(0))
+ status._moveItem(-1)
+ assert [x["key"] for x in status.getNewList()[0]] == [
C.sNew, C.sDraft, C.sFinished, None
]
# Move items, last selected, move up -> allowed
- tabStatus.listBox.clearSelection()
- tabStatus.listBox.setCurrentItem(tabStatus.listBox.topLevelItem(3))
- tabStatus._moveItem(-1)
- assert [x["key"] for x in tabStatus.getNewList()[0]] == [
+ status.listBox.clearSelection()
+ status.listBox.setCurrentItem(status.listBox.topLevelItem(3))
+ status._moveItem(-1)
+ assert [x["key"] for x in status.getNewList()[0]] == [
C.sNew, C.sDraft, None, C.sFinished
]
# Move items, same selected, move down -> allowed
- tabStatus._moveItem(1)
- assert [x["key"] for x in tabStatus.getNewList()[0]] == [
+ status._moveItem(1)
+ assert [x["key"] for x in status.getNewList()[0]] == [
C.sNew, C.sDraft, C.sFinished, None
]
# Importance Tab
# ==============
- tabImport = projSettings.tabImport
- projSettings._focusTab(GuiProjectSettings.TAB_IMPORT)
+ importance = projSettings.importPage
+ projSettings._sidebarClicked(GuiProjectSettings.PAGE_IMPORT)
# Delete unused entry
- tabImport.listBox.clearSelection()
- tabImport.listBox.setCurrentItem(tabImport.listBox.topLevelItem(1))
- qtbot.mouseClick(tabImport.delButton, Qt.LeftButton)
- assert tabImport.listBox.topLevelItemCount() == 3
+ importance.listBox.clearSelection()
+ importance.listBox.setCurrentItem(importance.listBox.topLevelItem(1))
+ qtbot.mouseClick(importance.delButton, Qt.LeftButton)
+ assert importance.listBox.topLevelItemCount() == 3
# Add a new entry
with monkeypatch.context() as mp:
mp.setattr(QColorDialog, "getColor", lambda *a: QColor(20, 30, 40))
- qtbot.mouseClick(tabImport.addButton, Qt.LeftButton)
- tabImport.listBox.clearSelection()
- tabImport.listBox.setCurrentItem(tabImport.listBox.topLevelItem(3))
+ qtbot.mouseClick(importance.addButton, Qt.LeftButton)
+ importance.listBox.clearSelection()
+ importance.listBox.setCurrentItem(importance.listBox.topLevelItem(3))
for _ in range(8):
- qtbot.keyClick(tabImport.editName, Qt.Key_Backspace, delay=KEY_DELAY)
+ qtbot.keyClick(importance.editName, Qt.Key_Backspace, delay=KEY_DELAY)
for c in "Final":
- qtbot.keyClick(tabImport.editName, c, delay=KEY_DELAY)
- qtbot.mouseClick(tabImport.colButton, Qt.LeftButton)
- qtbot.mouseClick(tabImport.saveButton, Qt.LeftButton)
- assert tabImport.listBox.topLevelItemCount() == 4
+ qtbot.keyClick(importance.editName, c, delay=KEY_DELAY)
+ qtbot.mouseClick(importance.colButton, Qt.LeftButton)
+ qtbot.mouseClick(importance.saveButton, Qt.LeftButton)
+ assert importance.listBox.topLevelItemCount() == 4
- assert tabImport.colChanged is True
- assert tabImport.getNewList() == (
+ assert importance.wasChanged is True
+ assert importance.getNewList() == (
[
{
"key": C.iNew,
@@ -323,13 +313,13 @@ def testDlgProjSettings_StatusImport(qtbot, monkeypatch, nwGUI, fncPath, projPat
# Check Project
projSettings._doSave()
- statusItems = dict(theProject.data.itemStatus.items())
+ statusItems = dict(project.data.itemStatus.items())
assert statusItems[C.sNew]["name"] == "New"
assert statusItems[C.sDraft]["name"] == "Draft"
assert statusItems[C.sFinished]["name"] == "Finished"
assert statusItems["s000013"]["name"] == "Final"
- importItems = dict(theProject.data.itemImport.items())
+ importItems = dict(project.data.itemImport.items())
assert importItems[C.iNew]["name"] == "New"
assert importItems[C.iMajor]["name"] == "Major"
assert importItems[C.iMain]["name"] == "Main"
@@ -341,83 +331,78 @@ def testDlgProjSettings_StatusImport(qtbot, monkeypatch, nwGUI, fncPath, projPat
@pytest.mark.gui
-def testDlgProjSettings_Replace(qtbot, monkeypatch, nwGUI, fncPath, projPath, mockRnd):
- """Test the auto-replace tab of the project settings dialog."""
+def testDlgProjSettings_Replace(qtbot, monkeypatch, nwGUI, projPath, mockRnd):
+ """Test the auto-replace page of the dialog."""
monkeypatch.setattr(GuiEditLabel, "getLabel", lambda *a, text: (text, True))
- monkeypatch.setattr(SHARED._spelling, "listDictionaries", lambda: [("en", "English [en]")])
-
- # Create new project
- mockRnd.reset()
buildTestProject(nwGUI, projPath)
- CONFIG.setBackupPath(fncPath)
# Set some values
- theProject = SHARED.project
- theProject.data.setAutoReplace({
+ project = SHARED.project
+ project.data.setAutoReplace({
"A": "B", "C": "D"
})
# Create Dialog
- projSettings = GuiProjectSettings(nwGUI, GuiProjectSettings.TAB_REPLACE)
+ projSettings = GuiProjectSettings(nwGUI, GuiProjectSettings.PAGE_REPLACE)
projSettings.show()
qtbot.addWidget(projSettings)
# Auto-Replace Tab
# ================
- tabReplace = projSettings.tabReplace
+ replace = projSettings.replacePage
- assert tabReplace.listBox.topLevelItem(0).text(0) == "" # type: ignore
- assert tabReplace.listBox.topLevelItem(0).text(1) == "B" # type: ignore
- assert tabReplace.listBox.topLevelItem(1).text(0) == "" # type: ignore
- assert tabReplace.listBox.topLevelItem(1).text(1) == "D" # type: ignore
- assert tabReplace.listBox.topLevelItemCount() == 2
+ assert replace.listBox.topLevelItem(0).text(0) == "" # type: ignore
+ assert replace.listBox.topLevelItem(0).text(1) == "B" # type: ignore
+ assert replace.listBox.topLevelItem(1).text(0) == "" # type: ignore
+ assert replace.listBox.topLevelItem(1).text(1) == "D" # type: ignore
+ assert replace.listBox.topLevelItemCount() == 2
# Nothing to save or delete
- tabReplace.listBox.clearSelection()
- tabReplace._saveEntry()
- tabReplace._delEntry()
- assert tabReplace.listBox.topLevelItemCount() == 2
+ replace.listBox.clearSelection()
+ replace._saveEntry()
+ replace._delEntry()
+ assert replace.listBox.topLevelItemCount() == 2
# Create a new entry
- qtbot.mouseClick(tabReplace.addButton, Qt.LeftButton)
- assert tabReplace.listBox.topLevelItemCount() == 3
- assert tabReplace.listBox.topLevelItem(2).text(0) == "" # type: ignore
- assert tabReplace.listBox.topLevelItem(2).text(1) == "" # type: ignore
+ qtbot.mouseClick(replace.addButton, Qt.LeftButton)
+ assert replace.listBox.topLevelItemCount() == 3
+ assert replace.listBox.topLevelItem(2).text(0) == "" # type: ignore
+ assert replace.listBox.topLevelItem(2).text(1) == "" # type: ignore
# Edit the entry
- tabReplace.listBox.setCurrentItem(tabReplace.listBox.topLevelItem(2))
- tabReplace.editKey.setText("")
+ replace.listBox.setCurrentItem(replace.listBox.topLevelItem(2))
+ replace.editKey.setText("")
for c in "Th is ":
- qtbot.keyClick(tabReplace.editKey, c, delay=KEY_DELAY)
- tabReplace.editValue.setText("")
+ qtbot.keyClick(replace.editKey, c, delay=KEY_DELAY)
+ replace.editValue.setText("")
for c in "With This Stuff ":
- qtbot.keyClick(tabReplace.editValue, c, delay=KEY_DELAY)
- qtbot.mouseClick(tabReplace.saveButton, Qt.LeftButton)
- assert tabReplace.listBox.topLevelItem(2).text(0) == "" # type: ignore
- assert tabReplace.listBox.topLevelItem(2).text(1) == "With This Stuff " # type: ignore
+ qtbot.keyClick(replace.editValue, c, delay=KEY_DELAY)
+ qtbot.mouseClick(replace.saveButton, Qt.LeftButton)
+ assert replace.listBox.topLevelItem(2).text(0) == "" # type: ignore
+ assert replace.listBox.topLevelItem(2).text(1) == "With This Stuff " # type: ignore
# Create a new entry again
- tabReplace.listBox.clearSelection()
- qtbot.mouseClick(tabReplace.addButton, Qt.LeftButton)
- assert tabReplace.listBox.topLevelItemCount() == 4
+ replace.listBox.clearSelection()
+ qtbot.mouseClick(replace.addButton, Qt.LeftButton)
+ assert replace.listBox.topLevelItemCount() == 4
# The list is sorted, so we must find it
newIdx = -1
- for i in range(tabReplace.listBox.topLevelItemCount()):
- if tabReplace.listBox.topLevelItem(i).text(0) == "": # type: ignore
+ for i in range(replace.listBox.topLevelItemCount()):
+ if replace.listBox.topLevelItem(i).text(0) == "": # type: ignore
newIdx = i
break
assert newIdx >= 0
# Then delete the new item
- tabReplace.listBox.setCurrentItem(tabReplace.listBox.topLevelItem(newIdx))
- qtbot.mouseClick(tabReplace.delButton, Qt.LeftButton)
- assert tabReplace.listBox.topLevelItemCount() == 3
+ replace.listBox.setCurrentItem(replace.listBox.topLevelItem(newIdx))
+ qtbot.mouseClick(replace.delButton, Qt.LeftButton)
+ assert replace.listBox.topLevelItemCount() == 3
# Check Project
projSettings._doSave()
- assert theProject.data.autoReplace == {
+ assert project.data.autoReplace == {
"A": "B", "C": "D", "This": "With This Stuff"
}
From 4c5f68242aab7b480e65aa91eb02c7adf0b331f1 Mon Sep 17 00:00:00 2001
From: Veronica Berglyd Olsen <1619840+vkbo@users.noreply.github.com>
Date: Fri, 26 Jan 2024 22:32:39 +0100
Subject: [PATCH 7/7] Remove unused code in old config layout classes
---
novelwriter/extensions/configlayout.py | 42 +++-----------------------
1 file changed, 5 insertions(+), 37 deletions(-)
diff --git a/novelwriter/extensions/configlayout.py b/novelwriter/extensions/configlayout.py
index 809068bc..99d38c03 100644
--- a/novelwriter/extensions/configlayout.py
+++ b/novelwriter/extensions/configlayout.py
@@ -30,7 +30,7 @@ from __future__ import annotations
from PyQt5.QtGui import QColor, QPalette
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (
- QAbstractButton, QFrame, QGridLayout, QHBoxLayout, QLabel, QLayout, QLineEdit,
+ QAbstractButton, QFrame, QGridLayout, QHBoxLayout, QLabel, QLayout,
QScrollArea, QSizePolicy, QVBoxLayout, QWidget
)
@@ -144,11 +144,6 @@ class NScrollableForm(QScrollArea):
self._indent = max(indent, 0)
return
- def setLayoutMargins(self, left: int, top: int, right: int, bottom: int) -> None:
- """Set the contents margins on the layout."""
- self._layout.setContentsMargins(left, top, right, bottom)
- return
-
##
# Methods
##
@@ -250,16 +245,6 @@ class NConfigLayout(QGridLayout):
return
- ##
- # Getters and Setters
- ##
-
- def setHelpTextStyle(self, color: QColor, scale: float = DEFAULT_SCALE) -> None:
- """Set the text color for the help text."""
- self._helpCol = color if isinstance(color, QColor) else QColor(*color)
- self._fontScale = scale
- return
-
##
# Class Methods
##
@@ -275,8 +260,8 @@ class NConfigLayout(QGridLayout):
self._nextRow += 1
return
- def addRow(self, label: str, widget: QWidget, helpText: str | None = None,
- unit: str | None = None, button: QWidget | None = None) -> int:
+ def addRow(self, label: str, widget: QWidget, unit: str | None = None,
+ button: QWidget | None = None) -> int:
"""Add a label and a widget as a new row of the grid."""
wSp = CONFIG.pxInt(8)
qLabel = QLabel(label)
@@ -284,19 +269,7 @@ class NConfigLayout(QGridLayout):
qLabel.setBuddy(widget)
qHelp = None
- if helpText is not None:
- qHelp = NColourLabel(
- str(helpText), self._helpCol,
- scale=self._fontScale, wrap=True, indent=wSp
- )
- labelBox = QVBoxLayout()
- labelBox.addWidget(qLabel)
- labelBox.addWidget(qHelp)
- labelBox.setSpacing(0)
- labelBox.addStretch(1)
- self.addLayout(labelBox, self._nextRow, 0, 1, 1, LEFT_TOP)
- else:
- self.addWidget(qLabel, self._nextRow, 0, 1, 1, LEFT_TOP)
+ self.addWidget(qLabel, self._nextRow, 0, 1, 1, LEFT_TOP)
if isinstance(unit, str):
controlBox = QHBoxLayout()
@@ -313,12 +286,7 @@ class NConfigLayout(QGridLayout):
self.addLayout(controlBox, self._nextRow, 1, 1, 1, RIGHT_TOP)
else:
- if isinstance(widget, QLineEdit):
- qLayout = QHBoxLayout()
- qLayout.addWidget(widget)
- self.addLayout(qLayout, self._nextRow, 1, 1, 1, RIGHT_TOP)
- else:
- self.addWidget(widget, self._nextRow, 1, 1, 1, RIGHT_TOP)
+ self.addWidget(widget, self._nextRow, 1, 1, 1, RIGHT_TOP)
self.setRowStretch(self._nextRow, 0)
self.setRowStretch(self._nextRow+1, 1)