novelWriter 2.2rc1__py3-none-any.whl → 2.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {novelWriter-2.2rc1.dist-info → novelWriter-2.3.dist-info}/METADATA +1 -1
- {novelWriter-2.2rc1.dist-info → novelWriter-2.3.dist-info}/RECORD +149 -132
- {novelWriter-2.2rc1.dist-info → novelWriter-2.3.dist-info}/WHEEL +1 -1
- novelWriter-2.3.dist-info/entry_points.txt +2 -0
- novelwriter/__init__.py +11 -6
- novelwriter/assets/i18n/nw_de_DE.qm +0 -0
- novelwriter/assets/i18n/nw_en_US.qm +0 -0
- novelwriter/assets/i18n/nw_es_419.qm +0 -0
- novelwriter/assets/i18n/nw_fr_FR.qm +0 -0
- novelwriter/assets/i18n/nw_it_IT.qm +0 -0
- novelwriter/assets/i18n/nw_ja_JP.qm +0 -0
- novelwriter/assets/i18n/nw_nb_NO.qm +0 -0
- novelwriter/assets/i18n/nw_nl_NL.qm +0 -0
- novelwriter/assets/i18n/nw_zh_CN.qm +0 -0
- novelwriter/assets/i18n/project_de_DE.json +1 -0
- novelwriter/assets/i18n/project_en_US.json +1 -0
- novelwriter/assets/i18n/project_es_419.json +11 -0
- novelwriter/assets/i18n/project_fr_FR.json +11 -0
- novelwriter/assets/i18n/project_it_IT.json +11 -0
- novelwriter/assets/i18n/project_ja_JP.json +2 -1
- novelwriter/assets/i18n/project_nb_NO.json +1 -0
- novelwriter/assets/i18n/project_nl_NL.json +11 -0
- novelwriter/assets/i18n/project_pt_BR.json +11 -0
- novelwriter/assets/i18n/project_zh_CN.json +11 -0
- novelwriter/assets/icons/typicons_dark/icons.conf +11 -2
- novelwriter/assets/icons/typicons_dark/mixed_document-new.svg +6 -0
- novelwriter/assets/icons/typicons_dark/mixed_import.svg +5 -0
- novelwriter/assets/icons/typicons_dark/nw_tb-bold-md.svg +4 -0
- novelwriter/assets/icons/typicons_dark/nw_tb-bold.svg +3 -1
- novelwriter/assets/icons/typicons_dark/nw_tb-italic-md.svg +4 -0
- novelwriter/assets/icons/typicons_dark/nw_tb-italic.svg +3 -1
- novelwriter/assets/icons/typicons_dark/nw_tb-strike-md.svg +4 -0
- novelwriter/assets/icons/typicons_dark/nw_tb-strike.svg +3 -1
- novelwriter/assets/icons/typicons_dark/nw_tb-subscript.svg +4 -2
- novelwriter/assets/icons/typicons_dark/nw_tb-superscript.svg +4 -2
- novelwriter/assets/icons/typicons_dark/nw_tb-underline.svg +4 -2
- novelwriter/assets/icons/typicons_dark/typ_document-add.svg +4 -0
- novelwriter/assets/icons/typicons_dark/typ_document.svg +4 -0
- novelwriter/assets/icons/typicons_dark/typ_th-dot-more.svg +4 -0
- novelwriter/assets/icons/typicons_dark/typ_th-list.svg +9 -0
- novelwriter/assets/icons/typicons_light/icons.conf +11 -2
- novelwriter/assets/icons/typicons_light/mixed_document-new.svg +6 -0
- novelwriter/assets/icons/typicons_light/mixed_import.svg +5 -0
- novelwriter/assets/icons/typicons_light/nw_tb-bold-md.svg +4 -0
- novelwriter/assets/icons/typicons_light/nw_tb-bold.svg +3 -1
- novelwriter/assets/icons/typicons_light/nw_tb-italic-md.svg +4 -0
- novelwriter/assets/icons/typicons_light/nw_tb-italic.svg +3 -1
- novelwriter/assets/icons/typicons_light/nw_tb-strike-md.svg +4 -0
- novelwriter/assets/icons/typicons_light/nw_tb-strike.svg +3 -1
- novelwriter/assets/icons/typicons_light/nw_tb-subscript.svg +4 -2
- novelwriter/assets/icons/typicons_light/nw_tb-superscript.svg +4 -2
- novelwriter/assets/icons/typicons_light/nw_tb-underline.svg +4 -2
- novelwriter/assets/icons/typicons_light/typ_document-add.svg +4 -0
- novelwriter/assets/icons/typicons_light/typ_document.svg +4 -0
- novelwriter/assets/icons/typicons_light/typ_th-dot-more.svg +4 -0
- novelwriter/assets/icons/typicons_light/typ_th-list.svg +9 -0
- novelwriter/assets/images/novelwriter-text-dark.svg +4 -0
- novelwriter/assets/images/novelwriter-text-light.svg +4 -0
- novelwriter/assets/images/welcome-dark.jpg +0 -0
- novelwriter/assets/images/welcome-light.jpg +0 -0
- novelwriter/assets/manual.pdf +0 -0
- novelwriter/assets/sample.zip +0 -0
- novelwriter/assets/syntax/cyberpunk_night.conf +26 -0
- novelwriter/assets/syntax/default_dark.conf +1 -0
- novelwriter/assets/syntax/default_light.conf +1 -0
- novelwriter/assets/syntax/grey_dark.conf +1 -0
- novelwriter/assets/syntax/grey_light.conf +1 -0
- novelwriter/assets/syntax/light_owl.conf +1 -0
- novelwriter/assets/syntax/night_owl.conf +1 -0
- novelwriter/assets/syntax/solarized_dark.conf +1 -0
- novelwriter/assets/syntax/solarized_light.conf +1 -0
- novelwriter/assets/syntax/tango.conf +23 -0
- novelwriter/assets/syntax/tomorrow.conf +1 -0
- novelwriter/assets/syntax/tomorrow_night.conf +1 -0
- novelwriter/assets/syntax/tomorrow_night_blue.conf +1 -0
- novelwriter/assets/syntax/tomorrow_night_bright.conf +1 -0
- novelwriter/assets/syntax/tomorrow_night_eighties.conf +1 -0
- novelwriter/assets/text/credits_en.htm +4 -2
- novelwriter/assets/themes/cyberpunk_night.conf +29 -0
- novelwriter/assets/themes/default_dark.conf +2 -2
- novelwriter/assets/themes/default_light.conf +2 -2
- novelwriter/common.py +64 -66
- novelwriter/config.py +39 -44
- novelwriter/constants.py +39 -17
- novelwriter/core/buildsettings.py +8 -8
- novelwriter/core/coretools.py +198 -157
- novelwriter/core/docbuild.py +7 -4
- novelwriter/core/document.py +7 -7
- novelwriter/core/index.py +90 -57
- novelwriter/core/item.py +23 -5
- novelwriter/core/options.py +11 -10
- novelwriter/core/project.py +73 -47
- novelwriter/core/projectdata.py +3 -16
- novelwriter/core/projectxml.py +14 -42
- novelwriter/core/sessions.py +4 -3
- novelwriter/core/spellcheck.py +6 -4
- novelwriter/core/status.py +5 -4
- novelwriter/core/storage.py +183 -141
- novelwriter/core/tohtml.py +6 -4
- novelwriter/core/tokenizer.py +110 -83
- novelwriter/core/tomd.py +2 -2
- novelwriter/core/toodt.py +41 -31
- novelwriter/core/tree.py +5 -4
- novelwriter/dialogs/about.py +88 -179
- novelwriter/dialogs/docmerge.py +30 -20
- novelwriter/dialogs/docsplit.py +33 -22
- novelwriter/dialogs/editlabel.py +20 -8
- novelwriter/dialogs/preferences.py +562 -725
- novelwriter/dialogs/{projsettings.py → projectsettings.py} +301 -270
- novelwriter/dialogs/quotes.py +47 -36
- novelwriter/dialogs/wordlist.py +128 -59
- novelwriter/enum.py +25 -22
- novelwriter/error.py +2 -2
- novelwriter/extensions/circularprogress.py +12 -12
- novelwriter/extensions/configlayout.py +185 -146
- novelwriter/extensions/{wheeleventfilter.py → eventfilters.py} +15 -5
- novelwriter/extensions/modified.py +81 -0
- novelwriter/extensions/novelselector.py +27 -13
- novelwriter/extensions/pagedsidebar.py +15 -20
- novelwriter/extensions/simpleprogress.py +8 -9
- novelwriter/extensions/statusled.py +9 -9
- novelwriter/extensions/switch.py +32 -64
- novelwriter/extensions/switchbox.py +2 -7
- novelwriter/extensions/versioninfo.py +153 -0
- novelwriter/gui/doceditor.py +250 -214
- novelwriter/gui/dochighlight.py +66 -94
- novelwriter/gui/docviewer.py +71 -98
- novelwriter/gui/docviewerpanel.py +140 -47
- novelwriter/gui/editordocument.py +3 -3
- novelwriter/gui/itemdetails.py +9 -9
- novelwriter/gui/mainmenu.py +47 -47
- novelwriter/gui/noveltree.py +53 -61
- novelwriter/gui/outline.py +100 -76
- novelwriter/gui/projtree.py +246 -112
- novelwriter/gui/sidebar.py +9 -8
- novelwriter/gui/statusbar.py +49 -7
- novelwriter/gui/theme.py +74 -76
- novelwriter/guimain.py +175 -330
- novelwriter/shared.py +68 -30
- novelwriter/tools/dictionaries.py +7 -8
- novelwriter/tools/lipsum.py +34 -28
- novelwriter/tools/manusbuild.py +3 -4
- novelwriter/tools/manuscript.py +25 -32
- novelwriter/tools/manussettings.py +194 -225
- novelwriter/tools/noveldetails.py +525 -0
- novelwriter/tools/welcome.py +819 -0
- novelwriter/tools/writingstats.py +26 -13
- novelWriter-2.2rc1.dist-info/entry_points.txt +0 -5
- novelwriter/assets/icons/typicons_dark/nw_tb-markdown.svg +0 -8
- novelwriter/assets/icons/typicons_dark/nw_tb-shortcode.svg +0 -8
- novelwriter/assets/icons/typicons_light/nw_tb-markdown.svg +0 -8
- novelwriter/assets/icons/typicons_light/nw_tb-shortcode.svg +0 -8
- novelwriter/assets/images/wizard-back.jpg +0 -0
- novelwriter/assets/text/gplv3_en.htm +0 -641
- novelwriter/assets/text/release_notes.htm +0 -17
- novelwriter/dialogs/projdetails.py +0 -525
- novelwriter/dialogs/projload.py +0 -298
- novelwriter/dialogs/updates.py +0 -182
- novelwriter/extensions/pageddialog.py +0 -130
- novelwriter/tools/projwizard.py +0 -478
- {novelWriter-2.2rc1.dist-info → novelWriter-2.3.dist-info}/LICENSE.md +0 -0
- {novelWriter-2.2rc1.dist-info → novelWriter-2.3.dist-info}/top_level.txt +0 -0
@@ -3,10 +3,11 @@ novelWriter – GUI Project Settings
|
|
3
3
|
==================================
|
4
4
|
|
5
5
|
File History:
|
6
|
-
Created:
|
6
|
+
Created: 2018-09-29 [0.0.1] GuiProjectSettings
|
7
|
+
Rewritten: 2024-01-26 [2.3b1] GuiProjectSettings
|
7
8
|
|
8
9
|
This file is a part of novelWriter
|
9
|
-
Copyright 2018–
|
10
|
+
Copyright 2018–2024, Veronica Berglyd Olsen
|
10
11
|
|
11
12
|
This program is free software: you can redistribute it and/or modify
|
12
13
|
it under the terms of the GNU General Public License as published by
|
@@ -25,72 +26,105 @@ from __future__ import annotations
|
|
25
26
|
|
26
27
|
import logging
|
27
28
|
|
28
|
-
from
|
29
|
-
|
30
|
-
from PyQt5.QtGui import QIcon, QPixmap, QColor
|
31
|
-
from PyQt5.QtCore import Qt, pyqtSlot
|
29
|
+
from PyQt5.QtGui import QCloseEvent, QColor, QIcon, QPixmap
|
30
|
+
from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot
|
32
31
|
from PyQt5.QtWidgets import (
|
33
|
-
QColorDialog,
|
34
|
-
QPushButton, QTreeWidget, QTreeWidgetItem, QVBoxLayout,
|
32
|
+
QColorDialog, QDialog, QDialogButtonBox, QHBoxLayout, QLineEdit,
|
33
|
+
QPushButton, QStackedWidget, QTreeWidget, QTreeWidgetItem, QVBoxLayout,
|
34
|
+
QWidget, qApp
|
35
35
|
)
|
36
36
|
|
37
37
|
from novelwriter import CONFIG, SHARED
|
38
38
|
from novelwriter.common import simplified
|
39
39
|
from novelwriter.extensions.switch import NSwitch
|
40
|
-
from novelwriter.extensions.
|
41
|
-
from novelwriter.extensions.configlayout import
|
42
|
-
|
43
|
-
if TYPE_CHECKING: # pragma: no cover
|
44
|
-
from novelwriter.guimain import GuiMain
|
40
|
+
from novelwriter.extensions.modified import NComboBox
|
41
|
+
from novelwriter.extensions.configlayout import NColourLabel, NFixedPage, NScrollableForm
|
42
|
+
from novelwriter.extensions.pagedsidebar import NPagedSideBar
|
45
43
|
|
46
44
|
logger = logging.getLogger(__name__)
|
47
45
|
|
48
46
|
|
49
|
-
class GuiProjectSettings(
|
47
|
+
class GuiProjectSettings(QDialog):
|
48
|
+
|
49
|
+
PAGE_SETTINGS = 0
|
50
|
+
PAGE_STATUS = 1
|
51
|
+
PAGE_IMPORT = 2
|
52
|
+
PAGE_REPLACE = 3
|
50
53
|
|
51
|
-
|
52
|
-
TAB_STATUS = 1
|
53
|
-
TAB_IMPORT = 2
|
54
|
-
TAB_REPLACE = 3
|
54
|
+
newProjectSettingsReady = pyqtSignal(bool)
|
55
55
|
|
56
|
-
def __init__(self,
|
57
|
-
super().__init__(parent=
|
56
|
+
def __init__(self, parent: QWidget, gotoPage: int = PAGE_SETTINGS) -> None:
|
57
|
+
super().__init__(parent=parent)
|
58
58
|
|
59
59
|
logger.debug("Create: GuiProjectSettings")
|
60
60
|
self.setObjectName("GuiProjectSettings")
|
61
|
-
|
62
|
-
self.mainGui = mainGui
|
63
|
-
SHARED.project.countStatus()
|
64
61
|
self.setWindowTitle(self.tr("Project Settings"))
|
65
62
|
|
66
|
-
|
67
|
-
|
68
|
-
pOptions = SHARED.project.options
|
69
|
-
|
70
|
-
self.setMinimumWidth(wW)
|
71
|
-
self.setMinimumHeight(wH)
|
63
|
+
options = SHARED.project.options
|
64
|
+
self.setMinimumSize(CONFIG.pxInt(500), CONFIG.pxInt(400))
|
72
65
|
self.resize(
|
73
|
-
CONFIG.pxInt(
|
74
|
-
CONFIG.pxInt(
|
66
|
+
CONFIG.pxInt(options.getInt("GuiProjectSettings", "winWidth", CONFIG.pxInt(650))),
|
67
|
+
CONFIG.pxInt(options.getInt("GuiProjectSettings", "winHeight", CONFIG.pxInt(500)))
|
75
68
|
)
|
76
69
|
|
77
|
-
|
78
|
-
self.
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
self.addTab(self.tabMain, self.tr("Settings"))
|
83
|
-
self.addTab(self.tabStatus, self.tr("Status"))
|
84
|
-
self.addTab(self.tabImport, self.tr("Importance"))
|
85
|
-
self.addTab(self.tabReplace, self.tr("Auto-Replace"))
|
70
|
+
# Title
|
71
|
+
self.titleLabel = NColourLabel(
|
72
|
+
self.tr("Project Settings"), SHARED.theme.helpText,
|
73
|
+
parent=self, scale=NColourLabel.HEADER_SCALE, indent=CONFIG.pxInt(4)
|
74
|
+
)
|
86
75
|
|
87
|
-
|
76
|
+
# SideBar
|
77
|
+
self.sidebar = NPagedSideBar(self)
|
78
|
+
self.sidebar.setLabelColor(SHARED.theme.helpText)
|
79
|
+
self.sidebar.addButton(self.tr("Settings"), self.PAGE_SETTINGS)
|
80
|
+
self.sidebar.addButton(self.tr("Status"), self.PAGE_STATUS)
|
81
|
+
self.sidebar.addButton(self.tr("Importance"), self.PAGE_IMPORT)
|
82
|
+
self.sidebar.addButton(self.tr("Auto-Replace"), self.PAGE_REPLACE)
|
83
|
+
self.sidebar.buttonClicked.connect(self._sidebarClicked)
|
84
|
+
|
85
|
+
# Buttons
|
86
|
+
self.buttonBox = QDialogButtonBox(
|
87
|
+
QDialogButtonBox.StandardButton.Save | QDialogButtonBox.StandardButton.Cancel
|
88
|
+
)
|
88
89
|
self.buttonBox.accepted.connect(self._doSave)
|
89
|
-
self.buttonBox.rejected.connect(self.
|
90
|
-
|
90
|
+
self.buttonBox.rejected.connect(self.close)
|
91
|
+
|
92
|
+
# Content
|
93
|
+
SHARED.project.countStatus()
|
91
94
|
|
92
|
-
|
93
|
-
self.
|
95
|
+
self.settingsPage = _SettingsPage(self)
|
96
|
+
self.statusPage = _StatusPage(self, True)
|
97
|
+
self.importPage = _StatusPage(self, False)
|
98
|
+
self.replacePage = _ReplacePage(self)
|
99
|
+
|
100
|
+
self.mainStack = QStackedWidget(self)
|
101
|
+
self.mainStack.addWidget(self.settingsPage)
|
102
|
+
self.mainStack.addWidget(self.statusPage)
|
103
|
+
self.mainStack.addWidget(self.importPage)
|
104
|
+
self.mainStack.addWidget(self.replacePage)
|
105
|
+
|
106
|
+
# Assemble
|
107
|
+
self.topBox = QHBoxLayout()
|
108
|
+
self.topBox.addWidget(self.titleLabel)
|
109
|
+
self.topBox.addStretch(1)
|
110
|
+
|
111
|
+
self.mainBox = QHBoxLayout()
|
112
|
+
self.mainBox.addWidget(self.sidebar)
|
113
|
+
self.mainBox.addWidget(self.mainStack)
|
114
|
+
self.mainBox.setContentsMargins(0, 0, 0, 0)
|
115
|
+
|
116
|
+
self.outerBox = QVBoxLayout()
|
117
|
+
self.outerBox.addLayout(self.topBox)
|
118
|
+
self.outerBox.addLayout(self.mainBox)
|
119
|
+
self.outerBox.addWidget(self.buttonBox)
|
120
|
+
self.outerBox.setSpacing(CONFIG.pxInt(8))
|
121
|
+
|
122
|
+
self.setLayout(self.outerBox)
|
123
|
+
self.setSizeGripEnabled(True)
|
124
|
+
|
125
|
+
# Jump to Specified Page
|
126
|
+
self.sidebar.setSelected(gotoPage)
|
127
|
+
self._sidebarClicked(gotoPage)
|
94
128
|
|
95
129
|
logger.debug("Ready: GuiProjectSettings")
|
96
130
|
|
@@ -100,186 +134,173 @@ class GuiProjectSettings(NPagedDialog):
|
|
100
134
|
logger.debug("Delete: GuiProjectSettings")
|
101
135
|
return
|
102
136
|
|
137
|
+
##
|
138
|
+
# Events
|
139
|
+
##
|
140
|
+
|
141
|
+
def closeEvent(self, event: QCloseEvent) -> None:
|
142
|
+
"""Capture the user closing the window and save settings."""
|
143
|
+
self._saveSettings()
|
144
|
+
event.accept()
|
145
|
+
self.deleteLater()
|
146
|
+
return
|
147
|
+
|
103
148
|
##
|
104
149
|
# Private Slots
|
105
150
|
##
|
106
151
|
|
152
|
+
@pyqtSlot(int)
|
153
|
+
def _sidebarClicked(self, pageId: int) -> None:
|
154
|
+
"""Process a user request to switch page."""
|
155
|
+
if pageId == self.PAGE_SETTINGS:
|
156
|
+
self.mainStack.setCurrentWidget(self.settingsPage)
|
157
|
+
elif pageId == self.PAGE_STATUS:
|
158
|
+
self.mainStack.setCurrentWidget(self.statusPage)
|
159
|
+
elif pageId == self.PAGE_IMPORT:
|
160
|
+
self.mainStack.setCurrentWidget(self.importPage)
|
161
|
+
elif pageId == self.PAGE_REPLACE:
|
162
|
+
self.mainStack.setCurrentWidget(self.replacePage)
|
163
|
+
return
|
164
|
+
|
107
165
|
@pyqtSlot()
|
108
166
|
def _doSave(self) -> None:
|
109
167
|
"""Save settings and close dialog."""
|
110
168
|
project = SHARED.project
|
111
|
-
projName = self.
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
doBackup = not self.tabMain.doBackup.isChecked()
|
169
|
+
projName = self.settingsPage.projName.text()
|
170
|
+
projAuthor = self.settingsPage.projAuthor.text()
|
171
|
+
projLang = self.settingsPage.projLang.currentData()
|
172
|
+
spellLang = self.settingsPage.spellLang.currentData()
|
173
|
+
doBackup = not self.settingsPage.doBackup.isChecked()
|
117
174
|
|
118
175
|
project.data.setName(projName)
|
119
|
-
project.data.
|
120
|
-
project.data.setAuthor(bookAuthor)
|
176
|
+
project.data.setAuthor(projAuthor)
|
121
177
|
project.data.setDoBackup(doBackup)
|
122
178
|
project.data.setSpellLang(spellLang)
|
123
179
|
project.setProjectLang(projLang)
|
124
180
|
|
125
|
-
|
126
|
-
|
181
|
+
rebuildTrees = False
|
182
|
+
|
183
|
+
if self.statusPage.wasChanged:
|
184
|
+
newList, delList = self.statusPage.getNewList()
|
127
185
|
project.setStatusColours(newList, delList)
|
186
|
+
rebuildTrees = True
|
128
187
|
|
129
|
-
if self.
|
130
|
-
newList, delList = self.
|
188
|
+
if self.importPage.wasChanged:
|
189
|
+
newList, delList = self.importPage.getNewList()
|
131
190
|
project.setImportColours(newList, delList)
|
191
|
+
rebuildTrees = True
|
132
192
|
|
133
|
-
if self.
|
134
|
-
self.
|
135
|
-
|
136
|
-
if self.tabReplace.arChanged:
|
137
|
-
newList = self.tabReplace.getNewList()
|
193
|
+
if self.replacePage.wasChanged:
|
194
|
+
newList = self.replacePage.getNewList()
|
138
195
|
project.data.setAutoReplace(newList)
|
139
196
|
|
140
|
-
self.
|
141
|
-
|
142
|
-
|
143
|
-
return
|
197
|
+
self.newProjectSettingsReady.emit(rebuildTrees)
|
198
|
+
qApp.processEvents()
|
199
|
+
self.close()
|
144
200
|
|
145
|
-
@pyqtSlot()
|
146
|
-
def _doClose(self) -> None:
|
147
|
-
"""Save settings and close the dialog."""
|
148
|
-
self._saveGuiSettings()
|
149
|
-
self.reject()
|
150
201
|
return
|
151
202
|
|
152
203
|
##
|
153
204
|
# Internal Functions
|
154
205
|
##
|
155
206
|
|
156
|
-
def
|
157
|
-
"""Change which is the focused tab."""
|
158
|
-
if tab == self.TAB_MAIN:
|
159
|
-
self.setCurrentWidget(self.tabMain)
|
160
|
-
elif tab == self.TAB_STATUS:
|
161
|
-
self.setCurrentWidget(self.tabStatus)
|
162
|
-
elif tab == self.TAB_IMPORT:
|
163
|
-
self.setCurrentWidget(self.tabImport)
|
164
|
-
elif tab == self.TAB_REPLACE:
|
165
|
-
self.setCurrentWidget(self.tabReplace)
|
166
|
-
return
|
167
|
-
|
168
|
-
def _saveGuiSettings(self) -> None:
|
207
|
+
def _saveSettings(self) -> None:
|
169
208
|
"""Save GUI settings."""
|
170
209
|
winWidth = CONFIG.rpxInt(self.width())
|
171
210
|
winHeight = CONFIG.rpxInt(self.height())
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
211
|
+
statusColW = CONFIG.rpxInt(self.statusPage.columnWidth())
|
212
|
+
importColW = CONFIG.rpxInt(self.importPage.columnWidth())
|
213
|
+
replaceColW = CONFIG.rpxInt(self.replacePage.columnWidth())
|
214
|
+
|
215
|
+
logger.debug("Saving State: GuiProjectSettings")
|
216
|
+
options = SHARED.project.options
|
217
|
+
options.setValue("GuiProjectSettings", "winWidth", winWidth)
|
218
|
+
options.setValue("GuiProjectSettings", "winHeight", winHeight)
|
219
|
+
options.setValue("GuiProjectSettings", "statusColW", statusColW)
|
220
|
+
options.setValue("GuiProjectSettings", "importColW", importColW)
|
221
|
+
options.setValue("GuiProjectSettings", "replaceColW", replaceColW)
|
182
222
|
|
183
223
|
return
|
184
224
|
|
185
225
|
# END Class GuiProjectSettings
|
186
226
|
|
187
227
|
|
188
|
-
class
|
228
|
+
class _SettingsPage(NScrollableForm):
|
189
229
|
|
190
230
|
def __init__(self, parent: QWidget) -> None:
|
191
231
|
super().__init__(parent=parent)
|
192
232
|
|
193
|
-
|
194
|
-
|
195
|
-
self.
|
196
|
-
self.
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
self.
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
self.mainForm.addRow(
|
208
|
-
self.tr("Project name"),
|
209
|
-
self.editName,
|
210
|
-
self.tr("Should be set only once.")
|
211
|
-
)
|
212
|
-
|
213
|
-
self.editTitle = QLineEdit()
|
214
|
-
self.editTitle.setMaxLength(200)
|
215
|
-
self.editTitle.setMaximumWidth(xW)
|
216
|
-
self.editTitle.setText(pData.title)
|
217
|
-
self.mainForm.addRow(
|
218
|
-
self.tr("Novel title"),
|
219
|
-
self.editTitle,
|
220
|
-
self.tr("Change whenever you want!")
|
233
|
+
xW = CONFIG.pxInt(200)
|
234
|
+
data = SHARED.project.data
|
235
|
+
self.setHelpTextStyle(SHARED.theme.helpText)
|
236
|
+
self.setRowIndent(0)
|
237
|
+
|
238
|
+
# Project Name
|
239
|
+
self.projName = QLineEdit(self)
|
240
|
+
self.projName.setMaxLength(200)
|
241
|
+
self.projName.setMinimumWidth(xW)
|
242
|
+
self.projName.setText(data.name)
|
243
|
+
self.addRow(
|
244
|
+
self.tr("Project name"), self.projName,
|
245
|
+
self.tr("Changing this will affect the backup path."),
|
246
|
+
stretch=(3, 2)
|
221
247
|
)
|
222
248
|
|
223
|
-
|
224
|
-
self.
|
225
|
-
self.
|
226
|
-
self.
|
227
|
-
self.
|
228
|
-
|
229
|
-
self.
|
230
|
-
self.tr("
|
249
|
+
# Project Author
|
250
|
+
self.projAuthor = QLineEdit(self)
|
251
|
+
self.projAuthor.setMaxLength(200)
|
252
|
+
self.projAuthor.setMinimumWidth(xW)
|
253
|
+
self.projAuthor.setText(data.author)
|
254
|
+
self.addRow(
|
255
|
+
self.tr("Author(s)"), self.projAuthor,
|
256
|
+
self.tr("Only used when building the manuscript."),
|
257
|
+
stretch=(3, 2)
|
231
258
|
)
|
232
259
|
|
233
|
-
|
234
|
-
self.projLang
|
260
|
+
# Project Language
|
261
|
+
self.projLang = NComboBox(self)
|
262
|
+
self.projLang.setMinimumWidth(xW)
|
235
263
|
for tag, language in CONFIG.listLanguages(CONFIG.LANG_PROJ):
|
236
264
|
self.projLang.addItem(language, tag)
|
237
|
-
self.
|
238
|
-
self.tr("Project language"),
|
239
|
-
self.
|
240
|
-
|
265
|
+
self.addRow(
|
266
|
+
self.tr("Project language"), self.projLang,
|
267
|
+
self.tr("Only used when building the manuscript."),
|
268
|
+
stretch=(3, 2)
|
241
269
|
)
|
270
|
+
if (idx := self.projLang.findData(data.language)) != -1:
|
271
|
+
self.projLang.setCurrentIndex(idx)
|
242
272
|
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
if langIdx == -1:
|
247
|
-
langIdx = self.projLang.findData("en_GB")
|
248
|
-
if langIdx != -1:
|
249
|
-
self.projLang.setCurrentIndex(langIdx)
|
250
|
-
|
251
|
-
self.spellLang = QComboBox(self)
|
252
|
-
self.spellLang.setMaximumWidth(xW)
|
273
|
+
# Spell Check Language
|
274
|
+
self.spellLang = NComboBox(self)
|
275
|
+
self.spellLang.setMinimumWidth(xW)
|
253
276
|
self.spellLang.addItem(self.tr("Default"), "None")
|
254
277
|
if CONFIG.hasEnchant:
|
255
278
|
for tag, language in SHARED.spelling.listDictionaries():
|
256
279
|
self.spellLang.addItem(language, tag)
|
257
|
-
self.
|
258
|
-
self.tr("Spell check language"),
|
259
|
-
self.
|
260
|
-
|
280
|
+
self.addRow(
|
281
|
+
self.tr("Spell check language"), self.spellLang,
|
282
|
+
self.tr("Overrides main preferences."),
|
283
|
+
stretch=(3, 2)
|
261
284
|
)
|
285
|
+
if (idx := self.spellLang.findData(data.spellLang)) != -1:
|
286
|
+
self.spellLang.setCurrentIndex(idx)
|
262
287
|
|
263
|
-
|
264
|
-
if pData.spellLang is not None:
|
265
|
-
langIdx = self.spellLang.findData(pData.spellLang)
|
266
|
-
if langIdx != -1:
|
267
|
-
self.spellLang.setCurrentIndex(langIdx)
|
268
|
-
|
288
|
+
# Backup on Close
|
269
289
|
self.doBackup = NSwitch(self)
|
270
|
-
self.doBackup.setChecked(not
|
271
|
-
self.
|
272
|
-
self.tr("
|
273
|
-
self.doBackup,
|
290
|
+
self.doBackup.setChecked(not data.doBackup)
|
291
|
+
self.addRow(
|
292
|
+
self.tr("Disable backup on close"), self.doBackup,
|
274
293
|
self.tr("Overrides main preferences.")
|
275
294
|
)
|
276
295
|
|
296
|
+
self.finalise()
|
297
|
+
|
277
298
|
return
|
278
299
|
|
279
|
-
# END Class
|
300
|
+
# END Class _SettingsPage
|
280
301
|
|
281
302
|
|
282
|
-
class
|
303
|
+
class _StatusPage(NFixedPage):
|
283
304
|
|
284
305
|
COL_LABEL = 0
|
285
306
|
COL_USAGE = 1
|
@@ -292,57 +313,55 @@ class GuiProjectEditStatus(QWidget):
|
|
292
313
|
super().__init__(parent=parent)
|
293
314
|
|
294
315
|
if isStatus:
|
295
|
-
|
296
|
-
pageLabel = self.tr("Novel
|
316
|
+
status = SHARED.project.data.itemStatus
|
317
|
+
pageLabel = self.tr("Novel Document Status Levels")
|
297
318
|
colSetting = "statusColW"
|
298
319
|
else:
|
299
|
-
|
300
|
-
pageLabel = self.tr("Note
|
320
|
+
status = SHARED.project.data.itemImport
|
321
|
+
pageLabel = self.tr("Project Note Importance Levels")
|
301
322
|
colSetting = "importColW"
|
302
323
|
|
303
324
|
wCol0 = CONFIG.pxInt(
|
304
325
|
SHARED.project.options.getInt("GuiProjectSettings", colSetting, 130)
|
305
326
|
)
|
306
327
|
|
307
|
-
self.
|
308
|
-
self.
|
309
|
-
self.
|
328
|
+
self._changed = False
|
329
|
+
self._colDeleted = []
|
330
|
+
self._selColour = QColor(100, 100, 100)
|
310
331
|
|
311
332
|
self.iPx = SHARED.theme.baseIconSize
|
312
333
|
|
313
|
-
#
|
314
|
-
|
334
|
+
# Title
|
335
|
+
self.pageTitle = NColourLabel(
|
336
|
+
pageLabel, SHARED.theme.helpText, parent=self,
|
337
|
+
scale=NColourLabel.HEADER_SCALE
|
338
|
+
)
|
315
339
|
|
316
|
-
|
317
|
-
self.listBox
|
318
|
-
|
319
|
-
])
|
340
|
+
# List Box
|
341
|
+
self.listBox = QTreeWidget(self)
|
342
|
+
self.listBox.setHeaderLabels([self.tr("Label"), self.tr("Usage")])
|
320
343
|
self.listBox.itemSelectionChanged.connect(self._selectedItem)
|
321
344
|
self.listBox.setColumnWidth(self.COL_LABEL, wCol0)
|
322
345
|
self.listBox.setIndentation(0)
|
323
346
|
|
324
|
-
for key, entry in
|
347
|
+
for key, entry in status.items():
|
325
348
|
self._addItem(key, entry["name"], entry["cols"], entry["count"])
|
326
349
|
|
327
350
|
# List Controls
|
328
|
-
|
329
|
-
|
330
|
-
self.addButton = QPushButton(SHARED.theme.getIcon("add"), "")
|
351
|
+
self.addButton = QPushButton(SHARED.theme.getIcon("add"), "", self)
|
331
352
|
self.addButton.clicked.connect(self._newItem)
|
332
353
|
|
333
|
-
self.delButton = QPushButton(SHARED.theme.getIcon("remove"), "")
|
354
|
+
self.delButton = QPushButton(SHARED.theme.getIcon("remove"), "", self)
|
334
355
|
self.delButton.clicked.connect(self._delItem)
|
335
356
|
|
336
|
-
self.upButton = QPushButton(SHARED.theme.getIcon("up"), "")
|
357
|
+
self.upButton = QPushButton(SHARED.theme.getIcon("up"), "", self)
|
337
358
|
self.upButton.clicked.connect(lambda: self._moveItem(-1))
|
338
359
|
|
339
|
-
self.dnButton = QPushButton(SHARED.theme.getIcon("down"), "")
|
360
|
+
self.dnButton = QPushButton(SHARED.theme.getIcon("down"), "", self)
|
340
361
|
self.dnButton.clicked.connect(lambda: self._moveItem(1))
|
341
362
|
|
342
363
|
# Edit Form
|
343
|
-
|
344
|
-
|
345
|
-
self.editName = QLineEdit()
|
364
|
+
self.editName = QLineEdit(self)
|
346
365
|
self.editName.setMaxLength(40)
|
347
366
|
self.editName.setPlaceholderText(self.tr("Select item to edit"))
|
348
367
|
self.editName.setEnabled(False)
|
@@ -359,8 +378,6 @@ class GuiProjectEditStatus(QWidget):
|
|
359
378
|
self.saveButton.clicked.connect(self._saveItem)
|
360
379
|
|
361
380
|
# Assemble
|
362
|
-
# ========
|
363
|
-
|
364
381
|
self.listControls = QVBoxLayout()
|
365
382
|
self.listControls.addWidget(self.addButton)
|
366
383
|
self.listControls.addWidget(self.delButton)
|
@@ -382,16 +399,25 @@ class GuiProjectEditStatus(QWidget):
|
|
382
399
|
self.innerBox.addLayout(self.listControls)
|
383
400
|
|
384
401
|
self.outerBox = QVBoxLayout()
|
385
|
-
self.outerBox.addWidget(
|
402
|
+
self.outerBox.addWidget(self.pageTitle)
|
386
403
|
self.outerBox.addLayout(self.innerBox)
|
387
404
|
|
388
|
-
self.
|
405
|
+
self.setCentralLayout(self.outerBox)
|
389
406
|
|
390
407
|
return
|
391
408
|
|
409
|
+
@property
|
410
|
+
def wasChanged(self) -> bool:
|
411
|
+
"""The user changed these settings."""
|
412
|
+
return self._changed
|
413
|
+
|
414
|
+
##
|
415
|
+
# Methods
|
416
|
+
##
|
417
|
+
|
392
418
|
def getNewList(self) -> tuple[list, list]:
|
393
419
|
"""Return list of entries."""
|
394
|
-
if self.
|
420
|
+
if self._changed:
|
395
421
|
newList = []
|
396
422
|
for n in range(self.listBox.topLevelItemCount()):
|
397
423
|
item = self.listBox.topLevelItem(n)
|
@@ -401,10 +427,13 @@ class GuiProjectEditStatus(QWidget):
|
|
401
427
|
"name": item.text(self.COL_LABEL),
|
402
428
|
"cols": item.data(self.COL_LABEL, self.COL_ROLE),
|
403
429
|
})
|
404
|
-
return newList, self.
|
405
|
-
|
430
|
+
return newList, self._colDeleted
|
406
431
|
return [], []
|
407
432
|
|
433
|
+
def columnWidth(self) -> int:
|
434
|
+
"""Return the size of the header column."""
|
435
|
+
return self.listBox.columnWidth(0)
|
436
|
+
|
408
437
|
##
|
409
438
|
# Private Slots
|
410
439
|
##
|
@@ -412,12 +441,12 @@ class GuiProjectEditStatus(QWidget):
|
|
412
441
|
@pyqtSlot()
|
413
442
|
def _selectColour(self) -> None:
|
414
443
|
"""Open a dialog to select the status icon colour."""
|
415
|
-
if self.
|
444
|
+
if self._selColour is not None:
|
416
445
|
newCol = QColorDialog.getColor(
|
417
|
-
self.
|
446
|
+
self._selColour, self, self.tr("Select Colour")
|
418
447
|
)
|
419
448
|
if newCol.isValid():
|
420
|
-
self.
|
449
|
+
self._selColour = newCol
|
421
450
|
pixmap = QPixmap(self.iPx, self.iPx)
|
422
451
|
pixmap.fill(newCol)
|
423
452
|
self.colButton.setIcon(QIcon(pixmap))
|
@@ -428,7 +457,7 @@ class GuiProjectEditStatus(QWidget):
|
|
428
457
|
def _newItem(self) -> None:
|
429
458
|
"""Create a new status item."""
|
430
459
|
self._addItem(None, self.tr("New Item"), (100, 100, 100), 0)
|
431
|
-
self.
|
460
|
+
self._changed = True
|
432
461
|
return
|
433
462
|
|
434
463
|
@pyqtSlot()
|
@@ -441,8 +470,8 @@ class GuiProjectEditStatus(QWidget):
|
|
441
470
|
SHARED.error(self.tr("Cannot delete a status item that is in use."))
|
442
471
|
else:
|
443
472
|
self.listBox.takeTopLevelItem(iRow)
|
444
|
-
self.
|
445
|
-
self.
|
473
|
+
self._colDeleted.append(selItem.data(self.COL_LABEL, self.KEY_ROLE))
|
474
|
+
self._changed = True
|
446
475
|
return
|
447
476
|
|
448
477
|
@pyqtSlot()
|
@@ -453,9 +482,9 @@ class GuiProjectEditStatus(QWidget):
|
|
453
482
|
selItem.setText(self.COL_LABEL, simplified(self.editName.text()))
|
454
483
|
selItem.setIcon(self.COL_LABEL, self.colButton.icon())
|
455
484
|
selItem.setData(self.COL_LABEL, self.COL_ROLE, (
|
456
|
-
self.
|
485
|
+
self._selColour.red(), self._selColour.green(), self._selColour.blue()
|
457
486
|
))
|
458
|
-
self.
|
487
|
+
self._changed = True
|
459
488
|
return
|
460
489
|
|
461
490
|
@pyqtSlot()
|
@@ -469,7 +498,7 @@ class GuiProjectEditStatus(QWidget):
|
|
469
498
|
name = selItem.text(self.COL_LABEL)
|
470
499
|
pixmap = QPixmap(self.iPx, self.iPx)
|
471
500
|
pixmap.fill(QColor(*cols))
|
472
|
-
self.
|
501
|
+
self._selColour = QColor(*cols)
|
473
502
|
self.editName.setText(name)
|
474
503
|
self.colButton.setIcon(QIcon(pixmap))
|
475
504
|
self.editName.selectAll()
|
@@ -480,7 +509,7 @@ class GuiProjectEditStatus(QWidget):
|
|
480
509
|
else:
|
481
510
|
pixmap = QPixmap(self.iPx, self.iPx)
|
482
511
|
pixmap.fill(QColor(100, 100, 100))
|
483
|
-
self.
|
512
|
+
self._selColour = QColor(100, 100, 100)
|
484
513
|
self.editName.setText("")
|
485
514
|
self.colButton.setIcon(QIcon(pixmap))
|
486
515
|
self.editName.setEnabled(False)
|
@@ -493,16 +522,16 @@ class GuiProjectEditStatus(QWidget):
|
|
493
522
|
##
|
494
523
|
|
495
524
|
def _addItem(self, key: str | None, name: str,
|
496
|
-
|
525
|
+
colour: tuple[int, int, int], count: int) -> None:
|
497
526
|
"""Add a status item to the list."""
|
498
527
|
pixmap = QPixmap(self.iPx, self.iPx)
|
499
|
-
pixmap.fill(QColor(*
|
528
|
+
pixmap.fill(QColor(*colour))
|
500
529
|
|
501
530
|
item = QTreeWidgetItem()
|
502
531
|
item.setText(self.COL_LABEL, name)
|
503
532
|
item.setIcon(self.COL_LABEL, QIcon(pixmap))
|
504
533
|
item.setData(self.COL_LABEL, self.KEY_ROLE, key)
|
505
|
-
item.setData(self.COL_LABEL, self.COL_ROLE,
|
534
|
+
item.setData(self.COL_LABEL, self.COL_ROLE, colour)
|
506
535
|
item.setData(self.COL_LABEL, self.NUM_ROLE, count)
|
507
536
|
item.setText(self.COL_USAGE, self._usageString(count))
|
508
537
|
|
@@ -528,30 +557,29 @@ class GuiProjectEditStatus(QWidget):
|
|
528
557
|
|
529
558
|
if cItem is not None:
|
530
559
|
cItem.setSelected(True)
|
531
|
-
self.
|
560
|
+
self._changed = True
|
532
561
|
|
533
562
|
return
|
534
563
|
|
535
564
|
def _getSelectedItem(self) -> QTreeWidgetItem | None:
|
536
565
|
"""Get the currently selected item."""
|
537
|
-
|
538
|
-
|
539
|
-
return selItem[0]
|
566
|
+
if items := self.listBox.selectedItems():
|
567
|
+
return items[0]
|
540
568
|
return None
|
541
569
|
|
542
|
-
def _usageString(self,
|
570
|
+
def _usageString(self, count: int) -> str:
|
543
571
|
"""Generate usage string."""
|
544
|
-
if
|
572
|
+
if count == 0:
|
545
573
|
return self.tr("Not in use")
|
546
|
-
elif
|
574
|
+
elif count == 1:
|
547
575
|
return self.tr("Used once")
|
548
576
|
else:
|
549
|
-
return self.tr("Used by {0} items").format(
|
577
|
+
return self.tr("Used by {0} items").format(count)
|
550
578
|
|
551
|
-
# END Class
|
579
|
+
# END Class _StatusPage
|
552
580
|
|
553
581
|
|
554
|
-
class
|
582
|
+
class _ReplacePage(NFixedPage):
|
555
583
|
|
556
584
|
COL_KEY = 0
|
557
585
|
COL_REPL = 1
|
@@ -559,24 +587,24 @@ class GuiProjectEditReplace(QWidget):
|
|
559
587
|
def __init__(self, parent: QWidget) -> None:
|
560
588
|
super().__init__(parent=parent)
|
561
589
|
|
562
|
-
self.
|
590
|
+
self._changed = False
|
563
591
|
|
564
592
|
wCol0 = CONFIG.pxInt(
|
565
593
|
SHARED.project.options.getInt("GuiProjectSettings", "replaceColW", 130)
|
566
594
|
)
|
567
|
-
pageLabel = self.tr("Text Replace List for Preview and Export")
|
568
595
|
|
569
|
-
#
|
570
|
-
|
596
|
+
# Title
|
597
|
+
self.pageTitle = NColourLabel(
|
598
|
+
self.tr("Text Auto-Replace for Preview and Build"),
|
599
|
+
SHARED.theme.helpText, parent=self, scale=NColourLabel.HEADER_SCALE
|
600
|
+
)
|
571
601
|
|
602
|
+
# List Box
|
572
603
|
self.listBox = QTreeWidget()
|
573
|
-
self.listBox.setHeaderLabels([
|
574
|
-
self.tr("Keyword"),
|
575
|
-
self.tr("Replace With"),
|
576
|
-
])
|
577
|
-
self.listBox.itemSelectionChanged.connect(self._selectedItem)
|
604
|
+
self.listBox.setHeaderLabels([self.tr("Keyword"), self.tr("Replace With")])
|
578
605
|
self.listBox.setColumnWidth(self.COL_KEY, wCol0)
|
579
606
|
self.listBox.setIndentation(0)
|
607
|
+
self.listBox.itemSelectionChanged.connect(self._selectedItem)
|
580
608
|
|
581
609
|
for aKey, aVal in SHARED.project.data.autoReplace.items():
|
582
610
|
newItem = QTreeWidgetItem(["<%s>" % aKey, aVal])
|
@@ -586,8 +614,6 @@ class GuiProjectEditReplace(QWidget):
|
|
586
614
|
self.listBox.setSortingEnabled(True)
|
587
615
|
|
588
616
|
# List Controls
|
589
|
-
# =============
|
590
|
-
|
591
617
|
self.addButton = QPushButton(SHARED.theme.getIcon("add"), "")
|
592
618
|
self.addButton.clicked.connect(self._addEntry)
|
593
619
|
|
@@ -595,14 +621,12 @@ class GuiProjectEditReplace(QWidget):
|
|
595
621
|
self.delButton.clicked.connect(self._delEntry)
|
596
622
|
|
597
623
|
# Edit Form
|
598
|
-
|
599
|
-
|
600
|
-
self.editKey = QLineEdit()
|
624
|
+
self.editKey = QLineEdit(self)
|
601
625
|
self.editKey.setPlaceholderText(self.tr("Select item to edit"))
|
602
626
|
self.editKey.setEnabled(False)
|
603
627
|
self.editKey.setMaxLength(40)
|
604
628
|
|
605
|
-
self.editValue = QLineEdit()
|
629
|
+
self.editValue = QLineEdit(self)
|
606
630
|
self.editValue.setEnabled(False)
|
607
631
|
self.editValue.setMaxLength(80)
|
608
632
|
|
@@ -610,8 +634,6 @@ class GuiProjectEditReplace(QWidget):
|
|
610
634
|
self.saveButton.clicked.connect(self._saveEntry)
|
611
635
|
|
612
636
|
# Assemble
|
613
|
-
# ========
|
614
|
-
|
615
637
|
self.listControls = QVBoxLayout()
|
616
638
|
self.listControls.addWidget(self.addButton)
|
617
639
|
self.listControls.addWidget(self.delButton)
|
@@ -631,50 +653,61 @@ class GuiProjectEditReplace(QWidget):
|
|
631
653
|
self.innerBox.addLayout(self.listControls)
|
632
654
|
|
633
655
|
self.outerBox = QVBoxLayout()
|
634
|
-
self.outerBox.addWidget(
|
656
|
+
self.outerBox.addWidget(self.pageTitle)
|
635
657
|
self.outerBox.addLayout(self.innerBox)
|
636
658
|
|
637
|
-
self.
|
659
|
+
self.setCentralLayout(self.outerBox)
|
638
660
|
|
639
661
|
return
|
640
662
|
|
663
|
+
@property
|
664
|
+
def wasChanged(self) -> bool:
|
665
|
+
"""The user changed these settings."""
|
666
|
+
return self._changed
|
667
|
+
|
668
|
+
##
|
669
|
+
# Methods
|
670
|
+
##
|
671
|
+
|
641
672
|
def getNewList(self) -> dict:
|
642
673
|
"""Extract the list from the widget."""
|
643
674
|
new = {}
|
644
675
|
for n in range(self.listBox.topLevelItemCount()):
|
645
|
-
tItem
|
646
|
-
if tItem is not None:
|
676
|
+
if tItem := self.listBox.topLevelItem(n):
|
647
677
|
aKey = self._stripNotAllowed(tItem.text(0))
|
648
678
|
aVal = tItem.text(1)
|
649
679
|
if len(aKey) > 0:
|
650
680
|
new[aKey] = aVal
|
651
681
|
return new
|
652
682
|
|
683
|
+
def columnWidth(self) -> int:
|
684
|
+
"""Return the size of the header column."""
|
685
|
+
return self.listBox.columnWidth(0)
|
686
|
+
|
653
687
|
##
|
654
|
-
#
|
688
|
+
# Private Slots
|
655
689
|
##
|
656
690
|
|
657
|
-
|
691
|
+
@pyqtSlot()
|
692
|
+
def _selectedItem(self) -> None:
|
658
693
|
"""Extract the details from the selected item and populate the
|
659
694
|
edit form.
|
660
695
|
"""
|
661
|
-
selItem
|
662
|
-
|
663
|
-
|
664
|
-
|
665
|
-
|
666
|
-
|
667
|
-
|
668
|
-
|
669
|
-
|
670
|
-
|
671
|
-
self.editKey.setFocus()
|
672
|
-
return True
|
696
|
+
if selItem := self._getSelectedItem():
|
697
|
+
editKey = self._stripNotAllowed(selItem.text(0))
|
698
|
+
editVal = selItem.text(1)
|
699
|
+
self.editKey.setText(editKey)
|
700
|
+
self.editValue.setText(editVal)
|
701
|
+
self.editKey.setEnabled(True)
|
702
|
+
self.editValue.setEnabled(True)
|
703
|
+
self.editKey.selectAll()
|
704
|
+
self.editKey.setFocus()
|
705
|
+
return
|
673
706
|
|
707
|
+
@pyqtSlot()
|
674
708
|
def _saveEntry(self) -> None:
|
675
709
|
"""Save the form data into the list widget."""
|
676
|
-
selItem
|
677
|
-
if selItem:
|
710
|
+
if selItem := self._getSelectedItem():
|
678
711
|
newKey = self.editKey.text()
|
679
712
|
newVal = self.editValue.text()
|
680
713
|
saveKey = self._stripNotAllowed(newKey)
|
@@ -686,38 +719,36 @@ class GuiProjectEditReplace(QWidget):
|
|
686
719
|
self.editKey.setEnabled(False)
|
687
720
|
self.editValue.setEnabled(False)
|
688
721
|
self.listBox.clearSelection()
|
689
|
-
self.
|
722
|
+
self._changed = True
|
690
723
|
return
|
691
724
|
|
725
|
+
@pyqtSlot()
|
692
726
|
def _addEntry(self) -> None:
|
693
727
|
"""Add a new list entry."""
|
694
728
|
saveKey = "<keyword%d>" % (self.listBox.topLevelItemCount() + 1)
|
695
|
-
|
696
|
-
newItem = QTreeWidgetItem([saveKey, newVal])
|
697
|
-
self.listBox.addTopLevelItem(newItem)
|
729
|
+
self.listBox.addTopLevelItem(QTreeWidgetItem([saveKey, ""]))
|
698
730
|
return
|
699
731
|
|
732
|
+
@pyqtSlot()
|
700
733
|
def _delEntry(self) -> None:
|
701
734
|
"""Delete the selected entry."""
|
702
|
-
selItem
|
703
|
-
if selItem:
|
735
|
+
if selItem := self._getSelectedItem():
|
704
736
|
self.listBox.takeTopLevelItem(self.listBox.indexOfTopLevelItem(selItem))
|
705
|
-
self.
|
737
|
+
self._changed = True
|
706
738
|
return
|
707
739
|
|
740
|
+
##
|
741
|
+
# Internal Functions
|
742
|
+
##
|
743
|
+
|
708
744
|
def _getSelectedItem(self) -> QTreeWidgetItem | None:
|
709
745
|
"""Extract the currently selected item."""
|
710
|
-
|
711
|
-
|
712
|
-
|
713
|
-
return selItem[0]
|
746
|
+
if items := self.listBox.selectedItems():
|
747
|
+
return items[0]
|
748
|
+
return None
|
714
749
|
|
715
750
|
def _stripNotAllowed(self, key: str) -> str:
|
716
751
|
"""Clean up the replace key string."""
|
717
|
-
|
718
|
-
for c in key:
|
719
|
-
if c.isalnum():
|
720
|
-
result += c
|
721
|
-
return result
|
752
|
+
return "".join(c for c in key if c.isalnum())
|
722
753
|
|
723
|
-
# END Class
|
754
|
+
# END Class _ReplacePage
|