novelWriter 2.2rc1__py3-none-any.whl → 2.3b1__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.3b1.dist-info}/METADATA +1 -1
- {novelWriter-2.2rc1.dist-info → novelWriter-2.3b1.dist-info}/RECORD +141 -129
- {novelWriter-2.2rc1.dist-info → novelWriter-2.3b1.dist-info}/WHEEL +1 -1
- 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_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_zh_CN.json +11 -0
- novelwriter/assets/icons/typicons_dark/icons.conf +9 -2
- 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-col.svg +8 -0
- 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_light/icons.conf +9 -2
- 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-col.svg +8 -0
- 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/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/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/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/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 +194 -155
- 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 +72 -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 +179 -141
- novelwriter/core/tohtml.py +6 -4
- novelwriter/core/tokenizer.py +74 -46
- 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 -46
- novelwriter/gui/noveltree.py +53 -61
- novelwriter/gui/outline.py +100 -76
- novelwriter/gui/projtree.py +193 -67
- novelwriter/gui/sidebar.py +9 -8
- novelwriter/gui/statusbar.py +49 -7
- novelwriter/gui/theme.py +65 -74
- novelwriter/guimain.py +173 -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 +802 -0
- novelwriter/tools/writingstats.py +26 -13
- 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.3b1.dist-info}/LICENSE.md +0 -0
- {novelWriter-2.2rc1.dist-info → novelWriter-2.3b1.dist-info}/entry_points.txt +0 -0
- {novelWriter-2.2rc1.dist-info → novelWriter-2.3b1.dist-info}/top_level.txt +0 -0
@@ -3,10 +3,11 @@ novelWriter – GUI Preferences
|
|
3
3
|
=============================
|
4
4
|
|
5
5
|
File History:
|
6
|
-
Created:
|
6
|
+
Created: 2019-06-10 [0.1.5] GuiPreferences
|
7
|
+
Rewritten: 2024-01-08 [2.3b1] GuiPreferences
|
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,23 +26,28 @@ from __future__ import annotations
|
|
25
26
|
|
26
27
|
import logging
|
27
28
|
|
28
|
-
from PyQt5.QtGui import QFont
|
29
|
-
from PyQt5.QtCore import Qt, pyqtSlot
|
29
|
+
from PyQt5.QtGui import QCloseEvent, QFont, QKeyEvent, QKeySequence
|
30
|
+
from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot
|
30
31
|
from PyQt5.QtWidgets import (
|
31
|
-
|
32
|
-
QLineEdit,
|
32
|
+
QAbstractButton, QCompleter, QDialog, QDialogButtonBox, QFileDialog,
|
33
|
+
QFontDialog, QHBoxLayout, QLineEdit, QPushButton, QToolButton, QVBoxLayout,
|
34
|
+
QWidget, qApp
|
33
35
|
)
|
34
36
|
|
35
37
|
from novelwriter import CONFIG, SHARED
|
38
|
+
from novelwriter.constants import nwConst, nwUnicode
|
36
39
|
from novelwriter.dialogs.quotes import GuiQuoteSelect
|
37
40
|
from novelwriter.extensions.switch import NSwitch
|
38
|
-
from novelwriter.extensions.
|
39
|
-
from novelwriter.extensions.configlayout import
|
41
|
+
from novelwriter.extensions.modified import NComboBox, NDoubleSpinBox, NSpinBox
|
42
|
+
from novelwriter.extensions.configlayout import NColourLabel, NScrollableForm
|
43
|
+
from novelwriter.extensions.pagedsidebar import NPagedSideBar
|
40
44
|
|
41
45
|
logger = logging.getLogger(__name__)
|
42
46
|
|
43
47
|
|
44
|
-
class GuiPreferences(
|
48
|
+
class GuiPreferences(QDialog):
|
49
|
+
|
50
|
+
newPreferencesReady = pyqtSignal(bool, bool, bool, bool)
|
45
51
|
|
46
52
|
def __init__(self, parent: QWidget) -> None:
|
47
53
|
super().__init__(parent=parent)
|
@@ -49,1089 +55,920 @@ class GuiPreferences(NPagedDialog):
|
|
49
55
|
logger.debug("Create: GuiPreferences")
|
50
56
|
self.setObjectName("GuiPreferences")
|
51
57
|
self.setWindowTitle(self.tr("Preferences"))
|
52
|
-
|
53
|
-
self.tabGeneral = GuiPreferencesGeneral(self)
|
54
|
-
self.tabProjects = GuiPreferencesProjects(self)
|
55
|
-
self.tabDocs = GuiPreferencesDocuments(self)
|
56
|
-
self.tabEditor = GuiPreferencesEditor(self)
|
57
|
-
self.tabSyntax = GuiPreferencesSyntax(self)
|
58
|
-
self.tabAuto = GuiPreferencesAutomation(self)
|
59
|
-
self.tabQuote = GuiPreferencesQuotes(self)
|
60
|
-
|
61
|
-
self.addTab(self.tabGeneral, self.tr("General"))
|
62
|
-
self.addTab(self.tabProjects, self.tr("Projects"))
|
63
|
-
self.addTab(self.tabDocs, self.tr("Documents"))
|
64
|
-
self.addTab(self.tabEditor, self.tr("Editor"))
|
65
|
-
self.addTab(self.tabSyntax, self.tr("Highlighting"))
|
66
|
-
self.addTab(self.tabAuto, self.tr("Automation"))
|
67
|
-
self.addTab(self.tabQuote, self.tr("Quotes"))
|
68
|
-
|
69
|
-
self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
|
70
|
-
self.buttonBox.accepted.connect(self._doSave)
|
71
|
-
self.buttonBox.rejected.connect(self._doClose)
|
72
|
-
self.addControls(self.buttonBox)
|
73
|
-
|
58
|
+
self.setMinimumSize(CONFIG.pxInt(600), CONFIG.pxInt(500))
|
74
59
|
self.resize(*CONFIG.preferencesWinSize)
|
75
60
|
|
76
|
-
#
|
77
|
-
self.
|
78
|
-
|
79
|
-
|
80
|
-
|
61
|
+
# Title
|
62
|
+
self.titleLabel = NColourLabel(
|
63
|
+
self.tr("Preferences"), SHARED.theme.helpText,
|
64
|
+
parent=self, scale=NColourLabel.HEADER_SCALE, indent=CONFIG.pxInt(4)
|
65
|
+
)
|
81
66
|
|
82
|
-
|
67
|
+
# Search Box
|
68
|
+
self.searchText = QLineEdit(self)
|
69
|
+
self.searchText.setPlaceholderText(self.tr("Search"))
|
70
|
+
self.searchText.setMinimumWidth(CONFIG.pxInt(200))
|
71
|
+
self.searchAction = self.searchText.addAction(
|
72
|
+
SHARED.theme.getIcon("search"), QLineEdit.ActionPosition.TrailingPosition
|
73
|
+
)
|
74
|
+
self.searchAction.triggered.connect(self._gotoSearch)
|
83
75
|
|
84
|
-
|
76
|
+
# SideBar
|
77
|
+
self.sidebar = NPagedSideBar(self)
|
78
|
+
self.sidebar.setLabelColor(SHARED.theme.helpText)
|
79
|
+
self.sidebar.buttonClicked.connect(self._sidebarClicked)
|
85
80
|
|
86
|
-
|
87
|
-
|
88
|
-
|
81
|
+
# Form
|
82
|
+
self.mainForm = NScrollableForm(self)
|
83
|
+
self.mainForm.setHelpTextStyle(SHARED.theme.helpText)
|
89
84
|
|
90
|
-
|
91
|
-
|
92
|
-
|
85
|
+
# Buttons
|
86
|
+
self.buttonBox = QDialogButtonBox(
|
87
|
+
QDialogButtonBox.StandardButton.Apply
|
88
|
+
| QDialogButtonBox.StandardButton.Save
|
89
|
+
| QDialogButtonBox.StandardButton.Close
|
90
|
+
)
|
91
|
+
self.buttonBox.clicked.connect(self._dialogButtonClicked)
|
93
92
|
|
94
|
-
|
95
|
-
|
96
|
-
|
93
|
+
# Assemble
|
94
|
+
self.searchBox = QHBoxLayout()
|
95
|
+
self.searchBox.addWidget(self.titleLabel)
|
96
|
+
self.searchBox.addStretch(1)
|
97
|
+
self.searchBox.addWidget(self.searchText, 1)
|
97
98
|
|
98
|
-
|
99
|
-
|
100
|
-
|
99
|
+
self.mainBox = QHBoxLayout()
|
100
|
+
self.mainBox.addWidget(self.sidebar)
|
101
|
+
self.mainBox.addWidget(self.mainForm)
|
102
|
+
self.mainBox.setContentsMargins(0, 0, 0, 0)
|
101
103
|
|
102
|
-
|
103
|
-
|
104
|
-
|
104
|
+
self.outerBox = QVBoxLayout()
|
105
|
+
self.outerBox.addLayout(self.searchBox)
|
106
|
+
self.outerBox.addLayout(self.mainBox)
|
107
|
+
self.outerBox.addWidget(self.buttonBox)
|
108
|
+
self.outerBox.setSpacing(CONFIG.pxInt(8))
|
105
109
|
|
106
|
-
|
107
|
-
|
108
|
-
return self._refreshTree
|
110
|
+
self.setLayout(self.outerBox)
|
111
|
+
self.setSizeGripEnabled(True)
|
109
112
|
|
110
|
-
|
111
|
-
|
112
|
-
##
|
113
|
+
# Build Form
|
114
|
+
self.buildForm()
|
113
115
|
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
logger.debug("Saving new preferences")
|
120
|
-
|
121
|
-
self.tabGeneral.saveValues()
|
122
|
-
self.tabProjects.saveValues()
|
123
|
-
self.tabDocs.saveValues()
|
124
|
-
self.tabEditor.saveValues()
|
125
|
-
self.tabSyntax.saveValues()
|
126
|
-
self.tabAuto.saveValues()
|
127
|
-
self.tabQuote.saveValues()
|
116
|
+
# Populate Search
|
117
|
+
self.searchCompleter = QCompleter(self.mainForm.labels, self)
|
118
|
+
self.searchCompleter.setCaseSensitivity(Qt.CaseSensitivity.CaseInsensitive)
|
119
|
+
self.searchCompleter.setFilterMode(Qt.MatchFlag.MatchContains)
|
120
|
+
self.searchCompleter.activated.connect(self._gotoSearch)
|
128
121
|
|
129
|
-
self.
|
130
|
-
CONFIG.saveConfig()
|
131
|
-
self.accept()
|
122
|
+
self.searchText.setCompleter(self.searchCompleter)
|
132
123
|
|
133
|
-
|
124
|
+
logger.debug("Ready: GuiPreferences")
|
134
125
|
|
135
|
-
@pyqtSlot()
|
136
|
-
def _doClose(self) -> None:
|
137
|
-
"""Close the preferences without saving the changes."""
|
138
|
-
self._saveWindowSize()
|
139
|
-
self.reject()
|
140
126
|
return
|
141
127
|
|
142
|
-
|
143
|
-
|
144
|
-
##
|
145
|
-
|
146
|
-
def _saveWindowSize(self) -> None:
|
147
|
-
"""Save the dialog window size."""
|
148
|
-
CONFIG.setPreferencesWinSize(self.width(), self.height())
|
128
|
+
def __del__(self) -> None: # pragma: no cover
|
129
|
+
logger.debug("Delete: GuiPreferences")
|
149
130
|
return
|
150
131
|
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
132
|
+
def buildForm(self) -> None:
|
133
|
+
"""Build the settings form."""
|
134
|
+
section = 0
|
135
|
+
minWidth = CONFIG.pxInt(200)
|
136
|
+
mIcon = SHARED.theme.getIcon("more")
|
155
137
|
|
156
|
-
|
157
|
-
|
138
|
+
# Label
|
139
|
+
self.sidebar.addLabel(self.tr("General"))
|
158
140
|
|
159
|
-
|
141
|
+
# Appearance
|
142
|
+
# ==========
|
160
143
|
|
161
|
-
|
162
|
-
|
163
|
-
self.
|
164
|
-
self.
|
144
|
+
title = self.tr("Appearance")
|
145
|
+
section += 1
|
146
|
+
self.sidebar.addButton(title, section)
|
147
|
+
self.mainForm.addGroupLabel(title, section)
|
165
148
|
|
166
|
-
#
|
167
|
-
|
168
|
-
self.mainForm.addGroupLabel(self.tr("Look and Feel"))
|
169
|
-
minWidth = CONFIG.pxInt(200)
|
170
|
-
|
171
|
-
# Select Locale
|
172
|
-
self.guiLocale = QComboBox()
|
149
|
+
# Display Language
|
150
|
+
self.guiLocale = NComboBox(self)
|
173
151
|
self.guiLocale.setMinimumWidth(minWidth)
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
if langIdx < 0:
|
179
|
-
langIdx = self.guiLocale.findData("en_GB")
|
180
|
-
if langIdx != -1:
|
181
|
-
self.guiLocale.setCurrentIndex(langIdx)
|
152
|
+
for lang, name in CONFIG.listLanguages(CONFIG.LANG_NW):
|
153
|
+
self.guiLocale.addItem(name, lang)
|
154
|
+
if (idx := self.guiLocale.findData(CONFIG.guiLocale)) != -1:
|
155
|
+
self.guiLocale.setCurrentIndex(idx)
|
182
156
|
|
183
157
|
self.mainForm.addRow(
|
184
|
-
self.tr("
|
185
|
-
self.
|
186
|
-
self.tr("Requires restart to take effect.")
|
158
|
+
self.tr("Display language"), self.guiLocale,
|
159
|
+
self.tr("Requires restart to take effect."), stretch=(3, 2)
|
187
160
|
)
|
188
161
|
|
189
|
-
#
|
190
|
-
self.guiTheme =
|
162
|
+
# Colour Theme
|
163
|
+
self.guiTheme = NComboBox(self)
|
191
164
|
self.guiTheme.setMinimumWidth(minWidth)
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
if themeIdx != -1:
|
197
|
-
self.guiTheme.setCurrentIndex(themeIdx)
|
165
|
+
for theme, name in SHARED.theme.listThemes():
|
166
|
+
self.guiTheme.addItem(name, theme)
|
167
|
+
if (idx := self.guiTheme.findData(CONFIG.guiTheme)) != -1:
|
168
|
+
self.guiTheme.setCurrentIndex(idx)
|
198
169
|
|
199
170
|
self.mainForm.addRow(
|
200
|
-
self.tr("
|
201
|
-
self.
|
202
|
-
self.tr("General colour theme and icons.")
|
171
|
+
self.tr("Colour theme"), self.guiTheme,
|
172
|
+
self.tr("General colour theme and icons."), stretch=(3, 2)
|
203
173
|
)
|
204
174
|
|
205
|
-
#
|
206
|
-
self.
|
207
|
-
self.guiSyntax.setMinimumWidth(CONFIG.pxInt(200))
|
208
|
-
self.theSyntaxes = SHARED.theme.listSyntax()
|
209
|
-
for syntaxFile, syntaxName in self.theSyntaxes:
|
210
|
-
self.guiSyntax.addItem(syntaxName, syntaxFile)
|
211
|
-
syntaxIdx = self.guiSyntax.findData(CONFIG.guiSyntax)
|
212
|
-
if syntaxIdx != -1:
|
213
|
-
self.guiSyntax.setCurrentIndex(syntaxIdx)
|
214
|
-
|
215
|
-
self.mainForm.addRow(
|
216
|
-
self.tr("Editor theme"),
|
217
|
-
self.guiSyntax,
|
218
|
-
self.tr("Colour theme for the editor and viewer.")
|
219
|
-
)
|
220
|
-
|
221
|
-
# Font Family
|
222
|
-
self.guiFont = QLineEdit()
|
175
|
+
# Application Font Family
|
176
|
+
self.guiFont = QLineEdit(self)
|
223
177
|
self.guiFont.setReadOnly(True)
|
224
|
-
self.guiFont.
|
178
|
+
self.guiFont.setMinimumWidth(CONFIG.pxInt(162))
|
225
179
|
self.guiFont.setText(CONFIG.guiFont)
|
226
|
-
self.
|
227
|
-
self.
|
228
|
-
self.
|
180
|
+
self.guiFontButton = QToolButton(self)
|
181
|
+
self.guiFontButton.setIcon(mIcon)
|
182
|
+
self.guiFontButton.clicked.connect(self._selectGuiFont)
|
229
183
|
self.mainForm.addRow(
|
230
|
-
self.tr("
|
231
|
-
self.
|
232
|
-
self.
|
233
|
-
button=self.fontButton
|
184
|
+
self.tr("Application font family"), self.guiFont,
|
185
|
+
self.tr("Requires restart to take effect."), stretch=(3, 2),
|
186
|
+
button=self.guiFontButton
|
234
187
|
)
|
235
188
|
|
236
|
-
# Font Size
|
237
|
-
self.guiFontSize =
|
189
|
+
# Application Font Size
|
190
|
+
self.guiFontSize = NSpinBox(self)
|
238
191
|
self.guiFontSize.setMinimum(8)
|
239
192
|
self.guiFontSize.setMaximum(60)
|
240
193
|
self.guiFontSize.setSingleStep(1)
|
241
194
|
self.guiFontSize.setValue(CONFIG.guiFontSize)
|
242
195
|
self.mainForm.addRow(
|
243
|
-
self.tr("
|
244
|
-
self.
|
245
|
-
self.tr("Requires restart to take effect."),
|
246
|
-
unit=self.tr("pt")
|
196
|
+
self.tr("Application font size"), self.guiFontSize,
|
197
|
+
self.tr("Requires restart to take effect."), unit=self.tr("pt")
|
247
198
|
)
|
248
199
|
|
249
|
-
#
|
250
|
-
|
251
|
-
self.mainForm.addGroupLabel(self.tr("GUI Settings"))
|
252
|
-
|
253
|
-
self.emphLabels = NSwitch()
|
254
|
-
self.emphLabels.setChecked(CONFIG.emphLabels)
|
255
|
-
self.mainForm.addRow(
|
256
|
-
self.tr("Emphasise partition and chapter labels"),
|
257
|
-
self.emphLabels,
|
258
|
-
self.tr("Makes them stand out in the project tree."),
|
259
|
-
)
|
260
|
-
|
261
|
-
self.showFullPath = NSwitch()
|
262
|
-
self.showFullPath.setChecked(CONFIG.showFullPath)
|
263
|
-
self.mainForm.addRow(
|
264
|
-
self.tr("Show full path in document header"),
|
265
|
-
self.showFullPath,
|
266
|
-
self.tr("Add the parent folder names to the header.")
|
267
|
-
)
|
268
|
-
|
269
|
-
self.hideVScroll = NSwitch()
|
200
|
+
# Vertical Scrollbars
|
201
|
+
self.hideVScroll = NSwitch(self)
|
270
202
|
self.hideVScroll.setChecked(CONFIG.hideVScroll)
|
271
203
|
self.mainForm.addRow(
|
272
|
-
self.tr("Hide vertical scroll bars in main windows"),
|
273
|
-
self.hideVScroll,
|
204
|
+
self.tr("Hide vertical scroll bars in main windows"), self.hideVScroll,
|
274
205
|
self.tr("Scrolling available with mouse wheel and keys only.")
|
275
206
|
)
|
276
207
|
|
277
|
-
|
208
|
+
# Horizontal Scrollbars
|
209
|
+
self.hideHScroll = NSwitch(self)
|
278
210
|
self.hideHScroll.setChecked(CONFIG.hideHScroll)
|
279
211
|
self.mainForm.addRow(
|
280
|
-
self.tr("Hide horizontal scroll bars in main windows"),
|
281
|
-
self.hideHScroll,
|
212
|
+
self.tr("Hide horizontal scroll bars in main windows"), self.hideHScroll,
|
282
213
|
self.tr("Scrolling available with mouse wheel and keys only.")
|
283
214
|
)
|
284
215
|
|
285
|
-
|
216
|
+
# Document Style
|
217
|
+
# ==============
|
286
218
|
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
guiSyntax = self.guiSyntax.currentData()
|
292
|
-
guiFont = self.guiFont.text()
|
293
|
-
guiFontSize = self.guiFontSize.value()
|
294
|
-
emphLabels = self.emphLabels.isChecked()
|
295
|
-
|
296
|
-
# Update Flags
|
297
|
-
self.prefsGui._updateTheme |= CONFIG.guiTheme != guiTheme
|
298
|
-
self.prefsGui._updateSyntax |= CONFIG.guiSyntax != guiSyntax
|
299
|
-
self.prefsGui._needsRestart |= CONFIG.guiLocale != guiLocale
|
300
|
-
self.prefsGui._needsRestart |= CONFIG.guiFont != guiFont
|
301
|
-
self.prefsGui._needsRestart |= CONFIG.guiFontSize != guiFontSize
|
302
|
-
self.prefsGui._refreshTree |= CONFIG.emphLabels != emphLabels
|
303
|
-
|
304
|
-
CONFIG.guiLocale = guiLocale
|
305
|
-
CONFIG.guiTheme = guiTheme
|
306
|
-
CONFIG.guiSyntax = guiSyntax
|
307
|
-
CONFIG.guiFont = guiFont
|
308
|
-
CONFIG.guiFontSize = guiFontSize
|
309
|
-
CONFIG.emphLabels = emphLabels
|
310
|
-
CONFIG.showFullPath = self.showFullPath.isChecked()
|
311
|
-
CONFIG.hideVScroll = self.hideVScroll.isChecked()
|
312
|
-
CONFIG.hideHScroll = self.hideHScroll.isChecked()
|
219
|
+
title = self.tr("Document Style")
|
220
|
+
section += 1
|
221
|
+
self.sidebar.addButton(title, section)
|
222
|
+
self.mainForm.addGroupLabel(title, section)
|
313
223
|
|
314
|
-
|
224
|
+
# Document Colour Theme
|
225
|
+
self.guiSyntax = NComboBox(self)
|
226
|
+
self.guiSyntax.setMinimumWidth(CONFIG.pxInt(200))
|
227
|
+
for syntax, name in SHARED.theme.listSyntax():
|
228
|
+
self.guiSyntax.addItem(name, syntax)
|
229
|
+
if (idx := self.guiSyntax.findData(CONFIG.guiSyntax)) != -1:
|
230
|
+
self.guiSyntax.setCurrentIndex(idx)
|
315
231
|
|
316
|
-
|
317
|
-
|
318
|
-
|
232
|
+
self.mainForm.addRow(
|
233
|
+
self.tr("Document colour theme"), self.guiSyntax,
|
234
|
+
self.tr("Colour theme for the editor and viewer."), stretch=(3, 2)
|
235
|
+
)
|
319
236
|
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
self.
|
330
|
-
|
237
|
+
# Document Font Family
|
238
|
+
self.textFont = QLineEdit(self)
|
239
|
+
self.textFont.setReadOnly(True)
|
240
|
+
self.textFont.setMinimumWidth(CONFIG.pxInt(162))
|
241
|
+
self.textFont.setText(CONFIG.textFont)
|
242
|
+
self.textFontButton = QToolButton(self)
|
243
|
+
self.textFontButton.setIcon(mIcon)
|
244
|
+
self.textFontButton.clicked.connect(self._selectTextFont)
|
245
|
+
self.mainForm.addRow(
|
246
|
+
self.tr("Document font family"), self.textFont,
|
247
|
+
self.tr("Applies to both document editor and viewer."), stretch=(3, 2),
|
248
|
+
button=self.textFontButton
|
249
|
+
)
|
331
250
|
|
332
|
-
#
|
251
|
+
# Document Font Size
|
252
|
+
self.textSize = NSpinBox(self)
|
253
|
+
self.textSize.setMinimum(8)
|
254
|
+
self.textSize.setMaximum(60)
|
255
|
+
self.textSize.setSingleStep(1)
|
256
|
+
self.textSize.setValue(CONFIG.textSize)
|
257
|
+
self.mainForm.addRow(
|
258
|
+
self.tr("Document font size"), self.textSize,
|
259
|
+
self.tr("Applies to both document editor and viewer."), unit=self.tr("pt")
|
260
|
+
)
|
333
261
|
|
262
|
+
# Emphasise Labels
|
263
|
+
self.emphLabels = NSwitch(self)
|
264
|
+
self.emphLabels.setChecked(CONFIG.emphLabels)
|
265
|
+
self.mainForm.addRow(
|
266
|
+
self.tr("Emphasise partition and chapter labels"), self.emphLabels,
|
267
|
+
self.tr("Makes them stand out in the project tree."),
|
268
|
+
)
|
334
269
|
|
335
|
-
|
270
|
+
# Document Path
|
271
|
+
self.showFullPath = NSwitch(self)
|
272
|
+
self.showFullPath.setChecked(CONFIG.showFullPath)
|
273
|
+
self.mainForm.addRow(
|
274
|
+
self.tr("Show full path in document header"), self.showFullPath,
|
275
|
+
self.tr("Add the parent folder names to the header.")
|
276
|
+
)
|
336
277
|
|
337
|
-
|
338
|
-
|
278
|
+
# Include Notes in Word Count
|
279
|
+
self.incNotesWCount = NSwitch(self)
|
280
|
+
self.incNotesWCount.setChecked(CONFIG.incNotesWCount)
|
281
|
+
self.mainForm.addRow(
|
282
|
+
self.tr("Include project notes in status bar word count"), self.incNotesWCount
|
283
|
+
)
|
339
284
|
|
340
|
-
#
|
341
|
-
|
342
|
-
self.mainForm.setHelpTextStyle(SHARED.theme.helpText)
|
343
|
-
self.setLayout(self.mainForm)
|
285
|
+
# Auto Save
|
286
|
+
# =========
|
344
287
|
|
345
|
-
|
346
|
-
|
347
|
-
self.
|
288
|
+
title = self.tr("Auto Save")
|
289
|
+
section += 1
|
290
|
+
self.sidebar.addButton(title, section)
|
291
|
+
self.mainForm.addGroupLabel(title, section)
|
348
292
|
|
349
293
|
# Document Save Timer
|
350
|
-
self.autoSaveDoc =
|
294
|
+
self.autoSaveDoc = NSpinBox(self)
|
351
295
|
self.autoSaveDoc.setMinimum(5)
|
352
296
|
self.autoSaveDoc.setMaximum(600)
|
353
297
|
self.autoSaveDoc.setSingleStep(1)
|
354
298
|
self.autoSaveDoc.setValue(CONFIG.autoSaveDoc)
|
355
299
|
self.mainForm.addRow(
|
356
|
-
self.tr("Save document interval"),
|
357
|
-
self.
|
358
|
-
self.tr("How often the document is automatically saved."),
|
359
|
-
unit=self.tr("seconds")
|
300
|
+
self.tr("Save document interval"), self.autoSaveDoc,
|
301
|
+
self.tr("How often the document is automatically saved."), unit=self.tr("seconds")
|
360
302
|
)
|
361
303
|
|
362
304
|
# Project Save Timer
|
363
|
-
self.autoSaveProj =
|
305
|
+
self.autoSaveProj = NSpinBox(self)
|
364
306
|
self.autoSaveProj.setMinimum(5)
|
365
307
|
self.autoSaveProj.setMaximum(600)
|
366
308
|
self.autoSaveProj.setSingleStep(1)
|
367
309
|
self.autoSaveProj.setValue(CONFIG.autoSaveProj)
|
368
310
|
self.mainForm.addRow(
|
369
|
-
self.tr("Save project interval"),
|
370
|
-
self.
|
371
|
-
self.tr("How often the project is automatically saved."),
|
372
|
-
unit=self.tr("seconds")
|
311
|
+
self.tr("Save project interval"), self.autoSaveProj,
|
312
|
+
self.tr("How often the project is automatically saved."), unit=self.tr("seconds")
|
373
313
|
)
|
374
314
|
|
375
315
|
# Project Backup
|
376
316
|
# ==============
|
377
|
-
|
317
|
+
|
318
|
+
title = self.tr("Project Backup")
|
319
|
+
section += 1
|
320
|
+
self.sidebar.addButton(title, section)
|
321
|
+
self.mainForm.addGroupLabel(title, section)
|
378
322
|
|
379
323
|
# Backup Path
|
380
324
|
self.backupPath = CONFIG.backupPath()
|
381
|
-
self.backupGetPath = QPushButton(self.tr("Browse"))
|
325
|
+
self.backupGetPath = QPushButton(SHARED.theme.getIcon("browse"), self.tr("Browse"), self)
|
382
326
|
self.backupGetPath.clicked.connect(self._backupFolder)
|
383
|
-
self.
|
384
|
-
self.tr("Backup storage location"),
|
385
|
-
self.
|
386
|
-
self.tr("Path: {0}").format(self.backupPath)
|
327
|
+
self.mainForm.addRow(
|
328
|
+
self.tr("Backup storage location"), self.backupGetPath,
|
329
|
+
self.tr("Path: {0}").format(self.backupPath), editable="backupPath"
|
387
330
|
)
|
388
331
|
|
389
|
-
# Run
|
390
|
-
self.backupOnClose = NSwitch()
|
332
|
+
# Run When Closing
|
333
|
+
self.backupOnClose = NSwitch(self)
|
391
334
|
self.backupOnClose.setChecked(CONFIG.backupOnClose)
|
392
335
|
self.backupOnClose.toggled.connect(self._toggledBackupOnClose)
|
393
336
|
self.mainForm.addRow(
|
394
|
-
self.tr("Run backup when the project is closed"),
|
395
|
-
self.backupOnClose,
|
337
|
+
self.tr("Run backup when the project is closed"), self.backupOnClose,
|
396
338
|
self.tr("Can be overridden for individual projects in Project Settings.")
|
397
339
|
)
|
398
340
|
|
399
|
-
# Ask
|
341
|
+
# Ask Before Backup
|
400
342
|
# Only enabled when "Run when closing" is checked
|
401
|
-
self.askBeforeBackup = NSwitch()
|
343
|
+
self.askBeforeBackup = NSwitch(self)
|
402
344
|
self.askBeforeBackup.setChecked(CONFIG.askBeforeBackup)
|
403
345
|
self.askBeforeBackup.setEnabled(CONFIG.backupOnClose)
|
404
346
|
self.mainForm.addRow(
|
405
|
-
self.tr("Ask before running backup"),
|
406
|
-
self.askBeforeBackup,
|
347
|
+
self.tr("Ask before running backup"), self.askBeforeBackup,
|
407
348
|
self.tr("If off, backups will run in the background.")
|
408
349
|
)
|
409
350
|
|
410
351
|
# Session Timer
|
411
352
|
# =============
|
412
|
-
self.mainForm.addGroupLabel(self.tr("Session Timer"))
|
413
353
|
|
414
|
-
|
415
|
-
|
354
|
+
title = self.tr("Session Timer")
|
355
|
+
section += 1
|
356
|
+
self.sidebar.addButton(title, section)
|
357
|
+
self.mainForm.addGroupLabel(title, section)
|
358
|
+
|
359
|
+
# Pause When Idle
|
360
|
+
self.stopWhenIdle = NSwitch(self)
|
416
361
|
self.stopWhenIdle.setChecked(CONFIG.stopWhenIdle)
|
417
362
|
self.mainForm.addRow(
|
418
|
-
self.tr("Pause the session timer when not writing"),
|
419
|
-
self.stopWhenIdle,
|
363
|
+
self.tr("Pause the session timer when not writing"), self.stopWhenIdle,
|
420
364
|
self.tr("Also pauses when the application window does not have focus.")
|
421
365
|
)
|
422
366
|
|
423
|
-
# Inactive
|
424
|
-
self.userIdleTime =
|
367
|
+
# Inactive Time for Idle
|
368
|
+
self.userIdleTime = NDoubleSpinBox(self)
|
425
369
|
self.userIdleTime.setMinimum(0.5)
|
426
370
|
self.userIdleTime.setMaximum(600.0)
|
427
371
|
self.userIdleTime.setSingleStep(0.5)
|
428
372
|
self.userIdleTime.setDecimals(1)
|
429
373
|
self.userIdleTime.setValue(CONFIG.userIdleTime/60.0)
|
430
374
|
self.mainForm.addRow(
|
431
|
-
self.tr("Editor inactive time before pausing timer"),
|
432
|
-
self.userIdleTime,
|
375
|
+
self.tr("Editor inactive time before pausing timer"), self.userIdleTime,
|
433
376
|
self.tr("User activity includes typing and changing the content."),
|
434
377
|
unit=self.tr("minutes")
|
435
378
|
)
|
436
379
|
|
437
|
-
|
438
|
-
|
439
|
-
def saveValues(self) -> None:
|
440
|
-
"""Save the values set for this tab."""
|
441
|
-
# Automatic Save
|
442
|
-
CONFIG.autoSaveDoc = self.autoSaveDoc.value()
|
443
|
-
CONFIG.autoSaveProj = self.autoSaveProj.value()
|
444
|
-
|
445
|
-
# Project Backup
|
446
|
-
CONFIG.setBackupPath(self.backupPath)
|
447
|
-
CONFIG.backupOnClose = self.backupOnClose.isChecked()
|
448
|
-
CONFIG.askBeforeBackup = self.askBeforeBackup.isChecked()
|
449
|
-
|
450
|
-
# Session Timer
|
451
|
-
CONFIG.stopWhenIdle = self.stopWhenIdle.isChecked()
|
452
|
-
CONFIG.userIdleTime = round(self.userIdleTime.value() * 60)
|
453
|
-
|
454
|
-
return
|
455
|
-
|
456
|
-
##
|
457
|
-
# Private Slots
|
458
|
-
##
|
459
|
-
|
460
|
-
@pyqtSlot()
|
461
|
-
def _backupFolder(self) -> None:
|
462
|
-
"""Open a dialog to select the backup folder."""
|
463
|
-
currDir = self.backupPath or ""
|
464
|
-
newDir = QFileDialog.getExistingDirectory(
|
465
|
-
self, self.tr("Backup Directory"), str(currDir), options=QFileDialog.ShowDirsOnly
|
466
|
-
)
|
467
|
-
if newDir:
|
468
|
-
self.backupPath = newDir
|
469
|
-
self.mainForm.setHelpText(
|
470
|
-
self.backupPathRow, self.tr("Path: {0}").format(self.backupPath)
|
471
|
-
)
|
472
|
-
return
|
473
|
-
return
|
474
|
-
|
475
|
-
@pyqtSlot(bool)
|
476
|
-
def _toggledBackupOnClose(self, state: bool) -> None:
|
477
|
-
"""Toggle switch that depends on the backup on close switch."""
|
478
|
-
self.askBeforeBackup.setEnabled(state)
|
479
|
-
return
|
480
|
-
|
481
|
-
# END Class GuiPreferencesProjects
|
482
|
-
|
483
|
-
|
484
|
-
class GuiPreferencesDocuments(QWidget):
|
485
|
-
|
486
|
-
def __init__(self, prefsGui: GuiPreferences) -> None:
|
487
|
-
super().__init__(parent=prefsGui)
|
488
|
-
|
489
|
-
# The Form
|
490
|
-
self.mainForm = NConfigLayout()
|
491
|
-
self.mainForm.setHelpTextStyle(SHARED.theme.helpText)
|
492
|
-
self.setLayout(self.mainForm)
|
493
|
-
|
494
|
-
# Text Style
|
495
|
-
# ==========
|
496
|
-
self.mainForm.addGroupLabel(self.tr("Text Style"))
|
497
|
-
|
498
|
-
# Font Family
|
499
|
-
self.textFont = QLineEdit()
|
500
|
-
self.textFont.setReadOnly(True)
|
501
|
-
self.textFont.setFixedWidth(CONFIG.pxInt(162))
|
502
|
-
self.textFont.setText(CONFIG.textFont)
|
503
|
-
self.fontButton = QPushButton("...")
|
504
|
-
self.fontButton.setMaximumWidth(int(2.5*SHARED.theme.getTextWidth("...")))
|
505
|
-
self.fontButton.clicked.connect(self._selectFont)
|
506
|
-
self.mainForm.addRow(
|
507
|
-
self.tr("Font family"),
|
508
|
-
self.textFont,
|
509
|
-
self.tr("Applies to both document editor and viewer."),
|
510
|
-
button=self.fontButton
|
511
|
-
)
|
512
|
-
|
513
|
-
# Font Size
|
514
|
-
self.textSize = QSpinBox(self)
|
515
|
-
self.textSize.setMinimum(8)
|
516
|
-
self.textSize.setMaximum(60)
|
517
|
-
self.textSize.setSingleStep(1)
|
518
|
-
self.textSize.setValue(CONFIG.textSize)
|
519
|
-
self.mainForm.addRow(
|
520
|
-
self.tr("Font size"),
|
521
|
-
self.textSize,
|
522
|
-
self.tr("Applies to both document editor and viewer."),
|
523
|
-
unit=self.tr("pt")
|
524
|
-
)
|
380
|
+
# Label
|
381
|
+
self.sidebar.addLabel(self.tr("Writing"))
|
525
382
|
|
526
383
|
# Text Flow
|
527
384
|
# =========
|
528
|
-
|
385
|
+
|
386
|
+
title = self.tr("Text Flow")
|
387
|
+
section += 1
|
388
|
+
self.sidebar.addButton(title, section)
|
389
|
+
self.mainForm.addGroupLabel(title, section)
|
529
390
|
|
530
391
|
# Max Text Width in Normal Mode
|
531
|
-
self.textWidth =
|
392
|
+
self.textWidth = NSpinBox(self)
|
532
393
|
self.textWidth.setMinimum(0)
|
533
394
|
self.textWidth.setMaximum(10000)
|
534
395
|
self.textWidth.setSingleStep(10)
|
535
396
|
self.textWidth.setValue(CONFIG.textWidth)
|
536
397
|
self.mainForm.addRow(
|
537
|
-
self.tr("Maximum text width in \"Normal Mode\""),
|
538
|
-
self.
|
539
|
-
self.tr("Set to 0 to disable this feature."),
|
540
|
-
unit=self.tr("px")
|
398
|
+
self.tr("Maximum text width in \"Normal Mode\""), self.textWidth,
|
399
|
+
self.tr("Set to 0 to disable this feature."), unit=self.tr("px")
|
541
400
|
)
|
542
401
|
|
543
402
|
# Max Text Width in Focus Mode
|
544
|
-
self.focusWidth =
|
403
|
+
self.focusWidth = NSpinBox(self)
|
545
404
|
self.focusWidth.setMinimum(200)
|
546
405
|
self.focusWidth.setMaximum(10000)
|
547
406
|
self.focusWidth.setSingleStep(10)
|
548
407
|
self.focusWidth.setValue(CONFIG.focusWidth)
|
549
408
|
self.mainForm.addRow(
|
550
|
-
self.tr("Maximum text width in \"Focus Mode\""),
|
551
|
-
self.
|
552
|
-
self.tr("The maximum width cannot be disabled."),
|
553
|
-
unit=self.tr("px")
|
409
|
+
self.tr("Maximum text width in \"Focus Mode\""), self.focusWidth,
|
410
|
+
self.tr("The maximum width cannot be disabled."), unit=self.tr("px")
|
554
411
|
)
|
555
412
|
|
556
413
|
# Focus Mode Footer
|
557
|
-
self.hideFocusFooter = NSwitch()
|
414
|
+
self.hideFocusFooter = NSwitch(self)
|
558
415
|
self.hideFocusFooter.setChecked(CONFIG.hideFocusFooter)
|
559
416
|
self.mainForm.addRow(
|
560
|
-
self.tr("Hide document footer in \"Focus Mode\""),
|
561
|
-
self.hideFocusFooter,
|
417
|
+
self.tr("Hide document footer in \"Focus Mode\""), self.hideFocusFooter,
|
562
418
|
self.tr("Hide the information bar in the document editor.")
|
563
419
|
)
|
564
420
|
|
565
421
|
# Justify Text
|
566
|
-
self.doJustify = NSwitch()
|
422
|
+
self.doJustify = NSwitch(self)
|
567
423
|
self.doJustify.setChecked(CONFIG.doJustify)
|
568
424
|
self.mainForm.addRow(
|
569
|
-
self.tr("Justify the text margins"),
|
570
|
-
self.doJustify,
|
425
|
+
self.tr("Justify the text margins"), self.doJustify,
|
571
426
|
self.tr("Applies to both document editor and viewer."),
|
572
427
|
)
|
573
428
|
|
574
429
|
# Document Margins
|
575
|
-
self.textMargin =
|
430
|
+
self.textMargin = NSpinBox(self)
|
576
431
|
self.textMargin.setMinimum(0)
|
577
432
|
self.textMargin.setMaximum(900)
|
578
433
|
self.textMargin.setSingleStep(1)
|
579
434
|
self.textMargin.setValue(CONFIG.textMargin)
|
580
435
|
self.mainForm.addRow(
|
581
|
-
self.tr("Minimum text margin"),
|
582
|
-
self.textMargin,
|
436
|
+
self.tr("Minimum text margin"), self.textMargin,
|
583
437
|
self.tr("Applies to both document editor and viewer."),
|
584
438
|
unit=self.tr("px")
|
585
439
|
)
|
586
440
|
|
587
441
|
# Tab Width
|
588
|
-
self.tabWidth =
|
442
|
+
self.tabWidth = NSpinBox(self)
|
589
443
|
self.tabWidth.setMinimum(0)
|
590
444
|
self.tabWidth.setMaximum(200)
|
591
445
|
self.tabWidth.setSingleStep(1)
|
592
446
|
self.tabWidth.setValue(CONFIG.tabWidth)
|
593
447
|
self.mainForm.addRow(
|
594
|
-
self.tr("Tab width"),
|
595
|
-
self.tabWidth,
|
448
|
+
self.tr("Tab width"), self.tabWidth,
|
596
449
|
self.tr("The width of a tab key press in the editor and viewer."),
|
597
450
|
unit=self.tr("px")
|
598
451
|
)
|
599
452
|
|
600
|
-
|
601
|
-
|
602
|
-
def saveValues(self) -> None:
|
603
|
-
"""Save the values set for this tab."""
|
604
|
-
# Text Style
|
605
|
-
CONFIG.setTextFont(self.textFont.text(), self.textSize.value())
|
606
|
-
|
607
|
-
# Text Flow
|
608
|
-
CONFIG.textWidth = self.textWidth.value()
|
609
|
-
CONFIG.focusWidth = self.focusWidth.value()
|
610
|
-
CONFIG.hideFocusFooter = self.hideFocusFooter.isChecked()
|
611
|
-
CONFIG.doJustify = self.doJustify.isChecked()
|
612
|
-
CONFIG.textMargin = self.textMargin.value()
|
613
|
-
CONFIG.tabWidth = self.tabWidth.value()
|
614
|
-
|
615
|
-
return
|
616
|
-
|
617
|
-
##
|
618
|
-
# Private Slots
|
619
|
-
##
|
620
|
-
|
621
|
-
@pyqtSlot()
|
622
|
-
def _selectFont(self):
|
623
|
-
"""Open the QFontDialog and set a font for the font style."""
|
624
|
-
currFont = QFont()
|
625
|
-
currFont.setFamily(CONFIG.textFont)
|
626
|
-
currFont.setPointSize(CONFIG.textSize)
|
627
|
-
theFont, theStatus = QFontDialog.getFont(currFont, self)
|
628
|
-
if theStatus:
|
629
|
-
self.textFont.setText(theFont.family())
|
630
|
-
self.textSize.setValue(theFont.pointSize())
|
631
|
-
|
632
|
-
return
|
633
|
-
|
634
|
-
# END Class GuiPreferencesDocuments
|
635
|
-
|
636
|
-
|
637
|
-
class GuiPreferencesEditor(QWidget):
|
638
|
-
|
639
|
-
def __init__(self, prefsGui: GuiPreferences) -> None:
|
640
|
-
super().__init__(parent=prefsGui)
|
641
|
-
|
642
|
-
# The Form
|
643
|
-
self.mainForm = NConfigLayout()
|
644
|
-
self.mainForm.setHelpTextStyle(SHARED.theme.helpText)
|
645
|
-
self.setLayout(self.mainForm)
|
453
|
+
# Text Editing
|
454
|
+
# ============
|
646
455
|
|
647
|
-
|
456
|
+
title = self.tr("Text Editing")
|
457
|
+
section += 1
|
458
|
+
self.sidebar.addButton(title, section)
|
459
|
+
self.mainForm.addGroupLabel(title, section)
|
648
460
|
|
649
461
|
# Spell Checking
|
650
|
-
|
651
|
-
self.
|
652
|
-
|
653
|
-
# Spell Check Provider and Language
|
654
|
-
self.spellLanguage = QComboBox(self)
|
655
|
-
self.spellLanguage.setMaximumWidth(mW)
|
462
|
+
self.spellLanguage = NComboBox(self)
|
463
|
+
self.spellLanguage.setMinimumWidth(minWidth)
|
656
464
|
|
657
465
|
if CONFIG.hasEnchant:
|
658
466
|
for tag, language in SHARED.spelling.listDictionaries():
|
659
467
|
self.spellLanguage.addItem(language, tag)
|
660
468
|
else:
|
661
|
-
self.spellLanguage.addItem(
|
469
|
+
self.spellLanguage.addItem(nwUnicode.U_EMDASH, "")
|
662
470
|
self.spellLanguage.setEnabled(False)
|
663
471
|
|
664
|
-
|
665
|
-
|
666
|
-
self.spellLanguage.setCurrentIndex(spellIdx)
|
472
|
+
if (idx := self.spellLanguage.findData(CONFIG.spellLanguage)) != -1:
|
473
|
+
self.spellLanguage.setCurrentIndex(idx)
|
667
474
|
|
668
475
|
self.mainForm.addRow(
|
669
|
-
self.tr("Spell check language"),
|
670
|
-
self.
|
671
|
-
self.tr("Available languages are determined by your system.")
|
476
|
+
self.tr("Spell check language"), self.spellLanguage,
|
477
|
+
self.tr("Available languages are determined by your system."), stretch=(3, 2)
|
672
478
|
)
|
673
479
|
|
674
|
-
# Word
|
675
|
-
|
676
|
-
self.
|
677
|
-
|
678
|
-
# Word Count Timer
|
679
|
-
self.wordCountTimer = QDoubleSpinBox(self)
|
680
|
-
self.wordCountTimer.setDecimals(1)
|
681
|
-
self.wordCountTimer.setMinimum(2.0)
|
682
|
-
self.wordCountTimer.setMaximum(600.0)
|
683
|
-
self.wordCountTimer.setSingleStep(0.1)
|
684
|
-
self.wordCountTimer.setValue(CONFIG.wordCountTimer)
|
685
|
-
self.mainForm.addRow(
|
686
|
-
self.tr("Word count interval"),
|
687
|
-
self.wordCountTimer,
|
688
|
-
unit=self.tr("seconds")
|
689
|
-
)
|
690
|
-
|
691
|
-
# Include Notes in Word Count
|
692
|
-
self.incNotesWCount = NSwitch()
|
693
|
-
self.incNotesWCount.setChecked(CONFIG.incNotesWCount)
|
480
|
+
# Auto-Select Word Under Cursor
|
481
|
+
self.autoSelect = NSwitch(self)
|
482
|
+
self.autoSelect.setChecked(CONFIG.autoSelect)
|
694
483
|
self.mainForm.addRow(
|
695
|
-
self.tr("
|
696
|
-
self.
|
484
|
+
self.tr("Auto-select word under cursor"), self.autoSelect,
|
485
|
+
self.tr("Apply formatting to word under cursor if no selection is made.")
|
697
486
|
)
|
698
487
|
|
699
|
-
# Writing Guides
|
700
|
-
# ==============
|
701
|
-
self.mainForm.addGroupLabel(self.tr("Writing Guides"))
|
702
|
-
|
703
488
|
# Show Tabs and Spaces
|
704
|
-
self.showTabsNSpaces = NSwitch()
|
489
|
+
self.showTabsNSpaces = NSwitch(self)
|
705
490
|
self.showTabsNSpaces.setChecked(CONFIG.showTabsNSpaces)
|
706
491
|
self.mainForm.addRow(
|
707
|
-
self.tr("Show tabs and spaces"),
|
708
|
-
self.showTabsNSpaces
|
492
|
+
self.tr("Show tabs and spaces"), self.showTabsNSpaces
|
709
493
|
)
|
710
494
|
|
711
495
|
# Show Line Endings
|
712
|
-
self.showLineEndings = NSwitch()
|
496
|
+
self.showLineEndings = NSwitch(self)
|
713
497
|
self.showLineEndings.setChecked(CONFIG.showLineEndings)
|
714
498
|
self.mainForm.addRow(
|
715
|
-
self.tr("Show line endings"),
|
716
|
-
self.showLineEndings
|
499
|
+
self.tr("Show line endings"), self.showLineEndings
|
717
500
|
)
|
718
501
|
|
719
|
-
#
|
502
|
+
# Editor Scrolling
|
720
503
|
# ================
|
721
|
-
|
504
|
+
|
505
|
+
title = self.tr("Editor Scrolling")
|
506
|
+
section += 1
|
507
|
+
self.sidebar.addButton(title, section)
|
508
|
+
self.mainForm.addGroupLabel(title, section)
|
722
509
|
|
723
510
|
# Scroll Past End
|
724
|
-
self.scrollPastEnd = NSwitch()
|
511
|
+
self.scrollPastEnd = NSwitch(self)
|
725
512
|
self.scrollPastEnd.setChecked(CONFIG.scrollPastEnd)
|
726
513
|
self.mainForm.addRow(
|
727
|
-
self.tr("Scroll past end of the document"),
|
728
|
-
self.scrollPastEnd,
|
514
|
+
self.tr("Scroll past end of the document"), self.scrollPastEnd,
|
729
515
|
self.tr("Also centres the cursor when scrolling.")
|
730
516
|
)
|
731
517
|
|
732
518
|
# Typewriter Scrolling
|
733
|
-
self.autoScroll = NSwitch()
|
519
|
+
self.autoScroll = NSwitch(self)
|
734
520
|
self.autoScroll.setChecked(CONFIG.autoScroll)
|
735
521
|
self.mainForm.addRow(
|
736
|
-
self.tr("Typewriter style scrolling when you type"),
|
737
|
-
self.autoScroll,
|
522
|
+
self.tr("Typewriter style scrolling when you type"), self.autoScroll,
|
738
523
|
self.tr("Keeps the cursor at a fixed vertical position.")
|
739
524
|
)
|
740
525
|
|
741
526
|
# Typewriter Position
|
742
|
-
self.autoScrollPos =
|
527
|
+
self.autoScrollPos = NSpinBox(self)
|
743
528
|
self.autoScrollPos.setMinimum(10)
|
744
529
|
self.autoScrollPos.setMaximum(90)
|
745
530
|
self.autoScrollPos.setSingleStep(1)
|
746
531
|
self.autoScrollPos.setValue(int(CONFIG.autoScrollPos))
|
747
532
|
self.mainForm.addRow(
|
748
|
-
self.tr("Minimum position for Typewriter scrolling"),
|
749
|
-
self.
|
750
|
-
self.tr("Percentage of the editor height from the top."),
|
751
|
-
unit="%"
|
533
|
+
self.tr("Minimum position for Typewriter scrolling"), self.autoScrollPos,
|
534
|
+
self.tr("Percentage of the editor height from the top."), unit="%"
|
752
535
|
)
|
753
536
|
|
754
|
-
|
755
|
-
|
756
|
-
def saveValues(self) -> None:
|
757
|
-
"""Save the values set for this tab."""
|
758
|
-
# Spell Checking
|
759
|
-
CONFIG.spellLanguage = self.spellLanguage.currentData()
|
760
|
-
|
761
|
-
# Word Count
|
762
|
-
CONFIG.wordCountTimer = self.wordCountTimer.value()
|
763
|
-
CONFIG.incNotesWCount = self.incNotesWCount.isChecked()
|
764
|
-
|
765
|
-
# Writing Guides
|
766
|
-
CONFIG.showTabsNSpaces = self.showTabsNSpaces.isChecked()
|
767
|
-
CONFIG.showLineEndings = self.showLineEndings.isChecked()
|
768
|
-
|
769
|
-
# Scroll Behaviour
|
770
|
-
CONFIG.autoScroll = self.autoScroll.isChecked()
|
771
|
-
CONFIG.autoScrollPos = self.autoScrollPos.value()
|
772
|
-
CONFIG.scrollPastEnd = self.scrollPastEnd.isChecked()
|
773
|
-
|
774
|
-
return
|
775
|
-
|
776
|
-
# END Class GuiPreferencesEditor
|
777
|
-
|
778
|
-
|
779
|
-
class GuiPreferencesSyntax(QWidget):
|
780
|
-
|
781
|
-
def __init__(self, prefsGui: GuiPreferences) -> None:
|
782
|
-
super().__init__(parent=prefsGui)
|
783
|
-
|
784
|
-
self.prefsGui = prefsGui
|
785
|
-
|
786
|
-
# The Form
|
787
|
-
self.mainForm = NConfigLayout()
|
788
|
-
self.mainForm.setHelpTextStyle(SHARED.theme.helpText)
|
789
|
-
self.setLayout(self.mainForm)
|
790
|
-
|
791
|
-
# Quotes & Dialogue
|
537
|
+
# Text Highlighting
|
792
538
|
# =================
|
793
|
-
self.mainForm.addGroupLabel(self.tr("Quotes & Dialogue"))
|
794
539
|
|
795
|
-
|
540
|
+
title = self.tr("Text Highlighting")
|
541
|
+
section += 1
|
542
|
+
self.sidebar.addButton(title, section)
|
543
|
+
self.mainForm.addGroupLabel(title, section)
|
544
|
+
|
545
|
+
self.highlightQuotes = NSwitch(self)
|
796
546
|
self.highlightQuotes.setChecked(CONFIG.highlightQuotes)
|
797
547
|
self.highlightQuotes.toggled.connect(self._toggleHighlightQuotes)
|
798
548
|
self.mainForm.addRow(
|
799
|
-
self.tr("Highlight text wrapped in quotes"),
|
800
|
-
self.highlightQuotes,
|
549
|
+
self.tr("Highlight text wrapped in quotes"), self.highlightQuotes,
|
801
550
|
self.tr("Applies to the document editor only.")
|
802
551
|
)
|
803
552
|
|
804
|
-
self.allowOpenSQuote = NSwitch()
|
553
|
+
self.allowOpenSQuote = NSwitch(self)
|
805
554
|
self.allowOpenSQuote.setChecked(CONFIG.allowOpenSQuote)
|
806
555
|
self.mainForm.addRow(
|
807
|
-
self.tr("Allow open-ended single quotes"),
|
808
|
-
self.allowOpenSQuote,
|
556
|
+
self.tr("Allow open-ended single quotes"), self.allowOpenSQuote,
|
809
557
|
self.tr("Highlight single-quoted line with no closing quote.")
|
810
558
|
)
|
811
559
|
|
812
|
-
self.allowOpenDQuote = NSwitch()
|
560
|
+
self.allowOpenDQuote = NSwitch(self)
|
813
561
|
self.allowOpenDQuote.setChecked(CONFIG.allowOpenDQuote)
|
814
562
|
self.mainForm.addRow(
|
815
|
-
self.tr("Allow open-ended double quotes"),
|
816
|
-
self.allowOpenDQuote,
|
563
|
+
self.tr("Allow open-ended double quotes"), self.allowOpenDQuote,
|
817
564
|
self.tr("Highlight double-quoted line with no closing quote.")
|
818
565
|
)
|
819
566
|
|
820
|
-
|
821
|
-
# =============
|
822
|
-
self.mainForm.addGroupLabel(self.tr("Text Emphasis"))
|
823
|
-
|
824
|
-
self.highlightEmph = NSwitch()
|
567
|
+
self.highlightEmph = NSwitch(self)
|
825
568
|
self.highlightEmph.setChecked(CONFIG.highlightEmph)
|
826
569
|
self.mainForm.addRow(
|
827
|
-
self.tr("Add highlight colour to emphasised text"),
|
828
|
-
self.highlightEmph,
|
570
|
+
self.tr("Add highlight colour to emphasised text"), self.highlightEmph,
|
829
571
|
self.tr("Applies to the document editor only.")
|
830
572
|
)
|
831
573
|
|
832
|
-
|
833
|
-
# ===========
|
834
|
-
|
835
|
-
self.mainForm.addGroupLabel(self.tr("Text Errors"))
|
836
|
-
|
837
|
-
self.showMultiSpaces = NSwitch()
|
574
|
+
self.showMultiSpaces = NSwitch(self)
|
838
575
|
self.showMultiSpaces.setChecked(CONFIG.showMultiSpaces)
|
839
576
|
self.mainForm.addRow(
|
840
|
-
self.tr("Highlight multiple or trailing spaces"),
|
841
|
-
self.showMultiSpaces,
|
577
|
+
self.tr("Highlight multiple or trailing spaces"), self.showMultiSpaces,
|
842
578
|
self.tr("Applies to the document editor only.")
|
843
579
|
)
|
844
580
|
|
845
|
-
|
846
|
-
|
847
|
-
def saveValues(self) -> None:
|
848
|
-
"""Save the values set for this tab."""
|
849
|
-
highlightQuotes = self.highlightQuotes.isChecked()
|
850
|
-
allowOpenSQuote = self.allowOpenSQuote.isChecked()
|
851
|
-
allowOpenDQuote = self.allowOpenDQuote.isChecked()
|
852
|
-
highlightEmph = self.highlightEmph.isChecked()
|
853
|
-
showMultiSpaces = self.showMultiSpaces.isChecked()
|
854
|
-
|
855
|
-
self.prefsGui._updateSyntax |= CONFIG.highlightQuotes != highlightQuotes
|
856
|
-
self.prefsGui._updateSyntax |= CONFIG.highlightEmph != highlightEmph
|
857
|
-
self.prefsGui._updateSyntax |= CONFIG.showMultiSpaces != showMultiSpaces
|
858
|
-
|
859
|
-
CONFIG.highlightQuotes = highlightQuotes
|
860
|
-
CONFIG.allowOpenSQuote = allowOpenSQuote
|
861
|
-
CONFIG.allowOpenDQuote = allowOpenDQuote
|
862
|
-
CONFIG.highlightEmph = highlightEmph
|
863
|
-
CONFIG.showMultiSpaces = showMultiSpaces
|
864
|
-
|
865
|
-
return
|
866
|
-
|
867
|
-
##
|
868
|
-
# Private Slots
|
869
|
-
##
|
870
|
-
|
871
|
-
@pyqtSlot(bool)
|
872
|
-
def _toggleHighlightQuotes(self, state: bool) -> None:
|
873
|
-
"""Toggle switches controlled by the highlight quotes switch."""
|
874
|
-
self.allowOpenSQuote.setEnabled(state)
|
875
|
-
self.allowOpenDQuote.setEnabled(state)
|
876
|
-
return
|
877
|
-
|
878
|
-
# END Class GuiPreferencesSyntax
|
879
|
-
|
880
|
-
|
881
|
-
class GuiPreferencesAutomation(QWidget):
|
882
|
-
|
883
|
-
def __init__(self, prefsGui: GuiPreferences) -> None:
|
884
|
-
super().__init__(parent=prefsGui)
|
581
|
+
# Text Automation
|
582
|
+
# ===============
|
885
583
|
|
886
|
-
|
887
|
-
|
888
|
-
self.
|
889
|
-
self.
|
584
|
+
title = self.tr("Text Automation")
|
585
|
+
section += 1
|
586
|
+
self.sidebar.addButton(title, section)
|
587
|
+
self.mainForm.addGroupLabel(title, section)
|
890
588
|
|
891
|
-
|
892
|
-
# ==================
|
893
|
-
self.mainForm.addGroupLabel(self.tr("Automatic Features"))
|
894
|
-
|
895
|
-
# Auto-Select Word Under Cursor
|
896
|
-
self.autoSelect = NSwitch()
|
897
|
-
self.autoSelect.setChecked(CONFIG.autoSelect)
|
898
|
-
self.mainForm.addRow(
|
899
|
-
self.tr("Auto-select word under cursor"),
|
900
|
-
self.autoSelect,
|
901
|
-
self.tr("Apply formatting to word under cursor if no selection is made.")
|
902
|
-
)
|
589
|
+
boxWidth = CONFIG.pxInt(150)
|
903
590
|
|
904
591
|
# Auto-Replace as You Type Main Switch
|
905
|
-
self.doReplace = NSwitch()
|
592
|
+
self.doReplace = NSwitch(self)
|
906
593
|
self.doReplace.setChecked(CONFIG.doReplace)
|
907
594
|
self.doReplace.toggled.connect(self._toggleAutoReplaceMain)
|
908
595
|
self.mainForm.addRow(
|
909
|
-
self.tr("Auto-replace text as you type"),
|
910
|
-
self.doReplace,
|
596
|
+
self.tr("Auto-replace text as you type"), self.doReplace,
|
911
597
|
self.tr("Allow the editor to replace symbols as you type.")
|
912
598
|
)
|
913
599
|
|
914
|
-
# Replace as You Type
|
915
|
-
# ===================
|
916
|
-
self.mainForm.addGroupLabel(self.tr("Replace as You Type"))
|
917
|
-
|
918
600
|
# Auto-Replace Single Quotes
|
919
|
-
self.doReplaceSQuote = NSwitch()
|
601
|
+
self.doReplaceSQuote = NSwitch(self)
|
920
602
|
self.doReplaceSQuote.setChecked(CONFIG.doReplaceSQuote)
|
921
603
|
self.doReplaceSQuote.setEnabled(CONFIG.doReplace)
|
922
604
|
self.mainForm.addRow(
|
923
|
-
self.tr("Auto-replace single quotes"),
|
924
|
-
self.doReplaceSQuote,
|
605
|
+
self.tr("Auto-replace single quotes"), self.doReplaceSQuote,
|
925
606
|
self.tr("Try to guess which is an opening or a closing quote.")
|
926
607
|
)
|
927
608
|
|
928
609
|
# Auto-Replace Double Quotes
|
929
|
-
self.doReplaceDQuote = NSwitch()
|
610
|
+
self.doReplaceDQuote = NSwitch(self)
|
930
611
|
self.doReplaceDQuote.setChecked(CONFIG.doReplaceDQuote)
|
931
612
|
self.doReplaceDQuote.setEnabled(CONFIG.doReplace)
|
932
613
|
self.mainForm.addRow(
|
933
|
-
self.tr("Auto-replace double quotes"),
|
934
|
-
self.doReplaceDQuote,
|
614
|
+
self.tr("Auto-replace double quotes"), self.doReplaceDQuote,
|
935
615
|
self.tr("Try to guess which is an opening or a closing quote.")
|
936
616
|
)
|
937
617
|
|
938
618
|
# Auto-Replace Hyphens
|
939
|
-
self.doReplaceDash = NSwitch()
|
619
|
+
self.doReplaceDash = NSwitch(self)
|
940
620
|
self.doReplaceDash.setChecked(CONFIG.doReplaceDash)
|
941
621
|
self.doReplaceDash.setEnabled(CONFIG.doReplace)
|
942
622
|
self.mainForm.addRow(
|
943
|
-
self.tr("Auto-replace dashes"),
|
944
|
-
self.doReplaceDash,
|
623
|
+
self.tr("Auto-replace dashes"), self.doReplaceDash,
|
945
624
|
self.tr("Double and triple hyphens become short and long dashes.")
|
946
625
|
)
|
947
626
|
|
948
627
|
# Auto-Replace Dots
|
949
|
-
self.doReplaceDots = NSwitch()
|
628
|
+
self.doReplaceDots = NSwitch(self)
|
950
629
|
self.doReplaceDots.setChecked(CONFIG.doReplaceDots)
|
951
630
|
self.doReplaceDots.setEnabled(CONFIG.doReplace)
|
952
631
|
self.mainForm.addRow(
|
953
|
-
self.tr("Auto-replace dots"),
|
954
|
-
self.doReplaceDots,
|
632
|
+
self.tr("Auto-replace dots"), self.doReplaceDots,
|
955
633
|
self.tr("Three consecutive dots become ellipsis.")
|
956
634
|
)
|
957
635
|
|
958
|
-
# Automatic Padding
|
959
|
-
# =================
|
960
|
-
self.mainForm.addGroupLabel(self.tr("Automatic Padding"))
|
961
|
-
|
962
636
|
# Pad Before
|
963
|
-
self.fmtPadBefore = QLineEdit()
|
637
|
+
self.fmtPadBefore = QLineEdit(self)
|
964
638
|
self.fmtPadBefore.setMaxLength(32)
|
639
|
+
self.fmtPadBefore.setMinimumWidth(boxWidth)
|
965
640
|
self.fmtPadBefore.setText(CONFIG.fmtPadBefore)
|
966
641
|
self.mainForm.addRow(
|
967
|
-
self.tr("Insert non-breaking space before"),
|
968
|
-
self.
|
969
|
-
self.tr("Automatically add space before any of these symbols."),
|
642
|
+
self.tr("Insert non-breaking space before"), self.fmtPadBefore,
|
643
|
+
self.tr("Automatically add space before any of these symbols."), stretch=(2, 1)
|
970
644
|
)
|
971
645
|
|
972
646
|
# Pad After
|
973
|
-
self.fmtPadAfter = QLineEdit()
|
647
|
+
self.fmtPadAfter = QLineEdit(self)
|
974
648
|
self.fmtPadAfter.setMaxLength(32)
|
649
|
+
self.fmtPadAfter.setMinimumWidth(boxWidth)
|
975
650
|
self.fmtPadAfter.setText(CONFIG.fmtPadAfter)
|
976
651
|
self.mainForm.addRow(
|
977
|
-
self.tr("Insert non-breaking space after"),
|
978
|
-
self.
|
979
|
-
self.tr("Automatically add space after any of these symbols."),
|
652
|
+
self.tr("Insert non-breaking space after"), self.fmtPadAfter,
|
653
|
+
self.tr("Automatically add space after any of these symbols."), stretch=(2, 1)
|
980
654
|
)
|
981
655
|
|
982
656
|
# Use Thin Space
|
983
|
-
self.fmtPadThin = NSwitch()
|
657
|
+
self.fmtPadThin = NSwitch(self)
|
984
658
|
self.fmtPadThin.setChecked(CONFIG.fmtPadThin)
|
985
659
|
self.fmtPadThin.setEnabled(CONFIG.doReplace)
|
986
660
|
self.mainForm.addRow(
|
987
|
-
self.tr("Use thin space instead"),
|
988
|
-
self.fmtPadThin,
|
661
|
+
self.tr("Use thin space instead"), self.fmtPadThin,
|
989
662
|
self.tr("Inserts a thin space instead of a regular space.")
|
990
663
|
)
|
991
664
|
|
992
|
-
return
|
993
|
-
|
994
|
-
def saveValues(self) -> None:
|
995
|
-
"""Save the values set for this tab."""
|
996
|
-
# Automatic Features
|
997
|
-
CONFIG.autoSelect = self.autoSelect.isChecked()
|
998
|
-
CONFIG.doReplace = self.doReplace.isChecked()
|
999
|
-
|
1000
|
-
# Replace as You Type
|
1001
|
-
CONFIG.doReplaceSQuote = self.doReplaceSQuote.isChecked()
|
1002
|
-
CONFIG.doReplaceDQuote = self.doReplaceDQuote.isChecked()
|
1003
|
-
CONFIG.doReplaceDash = self.doReplaceDash.isChecked()
|
1004
|
-
CONFIG.doReplaceDots = self.doReplaceDots.isChecked()
|
1005
|
-
|
1006
|
-
# Automatic Padding
|
1007
|
-
CONFIG.fmtPadBefore = self.fmtPadBefore.text().strip()
|
1008
|
-
CONFIG.fmtPadAfter = self.fmtPadAfter.text().strip()
|
1009
|
-
CONFIG.fmtPadThin = self.fmtPadThin.isChecked()
|
1010
|
-
|
1011
|
-
return
|
1012
|
-
|
1013
|
-
##
|
1014
|
-
# Private Slots
|
1015
|
-
##
|
1016
|
-
|
1017
|
-
@pyqtSlot(bool)
|
1018
|
-
def _toggleAutoReplaceMain(self, state: bool) -> None:
|
1019
|
-
"""Toggle switches controlled by the auto replace switch."""
|
1020
|
-
self.doReplaceSQuote.setEnabled(state)
|
1021
|
-
self.doReplaceDQuote.setEnabled(state)
|
1022
|
-
self.doReplaceDash.setEnabled(state)
|
1023
|
-
self.doReplaceDots.setEnabled(state)
|
1024
|
-
self.fmtPadThin.setEnabled(state)
|
1025
|
-
return
|
1026
|
-
|
1027
|
-
# END Class GuiPreferencesAutomation
|
1028
|
-
|
1029
|
-
|
1030
|
-
class GuiPreferencesQuotes(QWidget):
|
1031
|
-
|
1032
|
-
def __init__(self, prefsGui: GuiPreferences) -> None:
|
1033
|
-
super().__init__(parent=prefsGui)
|
1034
|
-
|
1035
|
-
# The Form
|
1036
|
-
self.mainForm = NConfigLayout()
|
1037
|
-
self.mainForm.setHelpTextStyle(SHARED.theme.helpText)
|
1038
|
-
self.setLayout(self.mainForm)
|
1039
|
-
|
1040
665
|
# Quotation Style
|
1041
666
|
# ===============
|
1042
|
-
self.mainForm.addGroupLabel(self.tr("Quotation Style"))
|
1043
667
|
|
1044
|
-
|
1045
|
-
|
668
|
+
title = self.tr("Quotation Style")
|
669
|
+
section += 1
|
670
|
+
self.sidebar.addButton(title, section)
|
671
|
+
self.mainForm.addGroupLabel(title, section)
|
672
|
+
|
1046
673
|
self.quoteSym = {}
|
674
|
+
qWidth = CONFIG.pxInt(40)
|
1047
675
|
|
1048
676
|
# Single Quote Style
|
1049
|
-
self.quoteSym["SO"] = QLineEdit()
|
677
|
+
self.quoteSym["SO"] = QLineEdit(self)
|
1050
678
|
self.quoteSym["SO"].setMaxLength(1)
|
1051
679
|
self.quoteSym["SO"].setReadOnly(True)
|
1052
680
|
self.quoteSym["SO"].setFixedWidth(qWidth)
|
1053
681
|
self.quoteSym["SO"].setAlignment(Qt.AlignCenter)
|
1054
682
|
self.quoteSym["SO"].setText(CONFIG.fmtSQuoteOpen)
|
1055
|
-
self.btnSingleStyleO =
|
1056
|
-
self.btnSingleStyleO.
|
683
|
+
self.btnSingleStyleO = QToolButton(self)
|
684
|
+
self.btnSingleStyleO.setIcon(mIcon)
|
1057
685
|
self.btnSingleStyleO.clicked.connect(lambda: self._getQuote("SO"))
|
1058
686
|
self.mainForm.addRow(
|
1059
|
-
self.tr("Single quote open style"),
|
1060
|
-
self.quoteSym["SO"],
|
687
|
+
self.tr("Single quote open style"), self.quoteSym["SO"],
|
1061
688
|
self.tr("The symbol to use for a leading single quote."),
|
1062
689
|
button=self.btnSingleStyleO
|
1063
690
|
)
|
1064
691
|
|
1065
|
-
self.quoteSym["SC"] = QLineEdit()
|
692
|
+
self.quoteSym["SC"] = QLineEdit(self)
|
1066
693
|
self.quoteSym["SC"].setMaxLength(1)
|
1067
694
|
self.quoteSym["SC"].setReadOnly(True)
|
1068
695
|
self.quoteSym["SC"].setFixedWidth(qWidth)
|
1069
696
|
self.quoteSym["SC"].setAlignment(Qt.AlignCenter)
|
1070
697
|
self.quoteSym["SC"].setText(CONFIG.fmtSQuoteClose)
|
1071
|
-
self.btnSingleStyleC =
|
1072
|
-
self.btnSingleStyleC.
|
698
|
+
self.btnSingleStyleC = QToolButton(self)
|
699
|
+
self.btnSingleStyleC.setIcon(mIcon)
|
1073
700
|
self.btnSingleStyleC.clicked.connect(lambda: self._getQuote("SC"))
|
1074
701
|
self.mainForm.addRow(
|
1075
|
-
self.tr("Single quote close style"),
|
1076
|
-
self.quoteSym["SC"],
|
702
|
+
self.tr("Single quote close style"), self.quoteSym["SC"],
|
1077
703
|
self.tr("The symbol to use for a trailing single quote."),
|
1078
704
|
button=self.btnSingleStyleC
|
1079
705
|
)
|
1080
706
|
|
1081
707
|
# Double Quote Style
|
1082
|
-
self.quoteSym["DO"] = QLineEdit()
|
708
|
+
self.quoteSym["DO"] = QLineEdit(self)
|
1083
709
|
self.quoteSym["DO"].setMaxLength(1)
|
1084
710
|
self.quoteSym["DO"].setReadOnly(True)
|
1085
711
|
self.quoteSym["DO"].setFixedWidth(qWidth)
|
1086
712
|
self.quoteSym["DO"].setAlignment(Qt.AlignCenter)
|
1087
713
|
self.quoteSym["DO"].setText(CONFIG.fmtDQuoteOpen)
|
1088
|
-
self.btnDoubleStyleO =
|
1089
|
-
self.btnDoubleStyleO.
|
714
|
+
self.btnDoubleStyleO = QToolButton(self)
|
715
|
+
self.btnDoubleStyleO.setIcon(mIcon)
|
1090
716
|
self.btnDoubleStyleO.clicked.connect(lambda: self._getQuote("DO"))
|
1091
717
|
self.mainForm.addRow(
|
1092
|
-
self.tr("Double quote open style"),
|
1093
|
-
self.quoteSym["DO"],
|
718
|
+
self.tr("Double quote open style"), self.quoteSym["DO"],
|
1094
719
|
self.tr("The symbol to use for a leading double quote."),
|
1095
720
|
button=self.btnDoubleStyleO
|
1096
721
|
)
|
1097
722
|
|
1098
|
-
self.quoteSym["DC"] = QLineEdit()
|
723
|
+
self.quoteSym["DC"] = QLineEdit(self)
|
1099
724
|
self.quoteSym["DC"].setMaxLength(1)
|
1100
725
|
self.quoteSym["DC"].setReadOnly(True)
|
1101
726
|
self.quoteSym["DC"].setFixedWidth(qWidth)
|
1102
727
|
self.quoteSym["DC"].setAlignment(Qt.AlignCenter)
|
1103
728
|
self.quoteSym["DC"].setText(CONFIG.fmtDQuoteClose)
|
1104
|
-
self.btnDoubleStyleC =
|
1105
|
-
self.btnDoubleStyleC.
|
729
|
+
self.btnDoubleStyleC = QToolButton(self)
|
730
|
+
self.btnDoubleStyleC.setIcon(mIcon)
|
1106
731
|
self.btnDoubleStyleC.clicked.connect(lambda: self._getQuote("DC"))
|
1107
732
|
self.mainForm.addRow(
|
1108
|
-
self.tr("Double quote close style"),
|
1109
|
-
self.quoteSym["DC"],
|
733
|
+
self.tr("Double quote close style"), self.quoteSym["DC"],
|
1110
734
|
self.tr("The symbol to use for a trailing double quote."),
|
1111
735
|
button=self.btnDoubleStyleC
|
1112
736
|
)
|
1113
737
|
|
738
|
+
self.mainForm.finalise()
|
739
|
+
self.sidebar.setSelected(1)
|
740
|
+
|
1114
741
|
return
|
1115
742
|
|
1116
|
-
|
1117
|
-
|
1118
|
-
|
1119
|
-
|
1120
|
-
|
1121
|
-
|
1122
|
-
|
743
|
+
##
|
744
|
+
# Events
|
745
|
+
##
|
746
|
+
|
747
|
+
def closeEvent(self, event: QCloseEvent) -> None:
|
748
|
+
"""Capture the close event and perform cleanup."""
|
749
|
+
logger.debug("Close: GuiPreferences")
|
750
|
+
self._saveWindowSize()
|
751
|
+
event.accept()
|
752
|
+
qApp.processEvents()
|
753
|
+
self.done(nwConst.DLG_FINISHED)
|
754
|
+
self.deleteLater()
|
755
|
+
return
|
756
|
+
|
757
|
+
def keyPressEvent(self, event: QKeyEvent) -> None:
|
758
|
+
"""Overload keyPressEvent to block enter key to save."""
|
759
|
+
if event.matches(QKeySequence.StandardKey.Cancel):
|
760
|
+
self.close()
|
761
|
+
event.ignore()
|
1123
762
|
return
|
1124
763
|
|
1125
764
|
##
|
1126
|
-
#
|
765
|
+
# Private Slots
|
1127
766
|
##
|
1128
767
|
|
768
|
+
@pyqtSlot("QAbstractButton*")
|
769
|
+
def _dialogButtonClicked(self, button: QAbstractButton) -> None:
|
770
|
+
"""Handle button clicks from the dialog button box."""
|
771
|
+
role = self.buttonBox.buttonRole(button)
|
772
|
+
if role == QDialogButtonBox.ButtonRole.ApplyRole:
|
773
|
+
self._saveValues()
|
774
|
+
elif role == QDialogButtonBox.ButtonRole.AcceptRole:
|
775
|
+
self._saveValues()
|
776
|
+
self.close()
|
777
|
+
elif role == QDialogButtonBox.ButtonRole.RejectRole:
|
778
|
+
self.close()
|
779
|
+
return
|
780
|
+
|
781
|
+
@pyqtSlot(int)
|
782
|
+
def _sidebarClicked(self, section: int) -> None:
|
783
|
+
"""Process a user request to switch page."""
|
784
|
+
self.mainForm.scrollToSection(section)
|
785
|
+
return
|
786
|
+
|
787
|
+
@pyqtSlot()
|
788
|
+
def _gotoSearch(self) -> None:
|
789
|
+
"""Go to the setting indicated by the search text."""
|
790
|
+
self.mainForm.scrollToLabel(self.searchText.text().strip())
|
791
|
+
return
|
792
|
+
|
793
|
+
@pyqtSlot()
|
794
|
+
def _selectGuiFont(self) -> None:
|
795
|
+
"""Open the QFontDialog and set a font for the font style."""
|
796
|
+
current = QFont()
|
797
|
+
current.setFamily(CONFIG.guiFont)
|
798
|
+
current.setPointSize(CONFIG.guiFontSize)
|
799
|
+
font, status = QFontDialog.getFont(current, self)
|
800
|
+
if status:
|
801
|
+
self.guiFont.setText(font.family())
|
802
|
+
self.guiFontSize.setValue(font.pointSize())
|
803
|
+
return
|
804
|
+
|
805
|
+
@pyqtSlot()
|
806
|
+
def _selectTextFont(self):
|
807
|
+
"""Open the QFontDialog and set a font for the font style."""
|
808
|
+
current = QFont()
|
809
|
+
current.setFamily(CONFIG.textFont)
|
810
|
+
current.setPointSize(CONFIG.textSize)
|
811
|
+
font, status = QFontDialog.getFont(current, self)
|
812
|
+
if status:
|
813
|
+
self.textFont.setText(font.family())
|
814
|
+
self.textSize.setValue(font.pointSize())
|
815
|
+
return
|
816
|
+
|
817
|
+
@pyqtSlot()
|
818
|
+
def _backupFolder(self) -> None:
|
819
|
+
"""Open a dialog to select the backup folder."""
|
820
|
+
if path := QFileDialog.getExistingDirectory(
|
821
|
+
self, self.tr("Backup Directory"), str(self.backupPath) or "",
|
822
|
+
options=QFileDialog.ShowDirsOnly
|
823
|
+
):
|
824
|
+
self.backupPath = path
|
825
|
+
self.mainForm.setHelpText("backupPath", self.tr("Path: {0}").format(path))
|
826
|
+
return
|
827
|
+
|
828
|
+
@pyqtSlot(bool)
|
829
|
+
def _toggledBackupOnClose(self, state: bool) -> None:
|
830
|
+
"""Toggle switch that depends on the backup on close switch."""
|
831
|
+
self.askBeforeBackup.setEnabled(state)
|
832
|
+
return
|
833
|
+
|
834
|
+
@pyqtSlot(bool)
|
835
|
+
def _toggleHighlightQuotes(self, state: bool) -> None:
|
836
|
+
"""Toggle switches controlled by the highlight quotes switch."""
|
837
|
+
self.allowOpenSQuote.setEnabled(state)
|
838
|
+
self.allowOpenDQuote.setEnabled(state)
|
839
|
+
return
|
840
|
+
|
841
|
+
@pyqtSlot(bool)
|
842
|
+
def _toggleAutoReplaceMain(self, state: bool) -> None:
|
843
|
+
"""Toggle switches controlled by the auto replace switch."""
|
844
|
+
self.doReplaceSQuote.setEnabled(state)
|
845
|
+
self.doReplaceDQuote.setEnabled(state)
|
846
|
+
self.doReplaceDash.setEnabled(state)
|
847
|
+
self.doReplaceDots.setEnabled(state)
|
848
|
+
self.fmtPadThin.setEnabled(state)
|
849
|
+
return
|
850
|
+
|
1129
851
|
def _getQuote(self, qType: str) -> None:
|
1130
852
|
"""Dialog for single quote open."""
|
1131
|
-
|
1132
|
-
if
|
1133
|
-
self.quoteSym[qType].setText(
|
853
|
+
quote, status = GuiQuoteSelect.getQuote(self, current=self.quoteSym[qType].text())
|
854
|
+
if status:
|
855
|
+
self.quoteSym[qType].setText(quote)
|
856
|
+
return
|
857
|
+
|
858
|
+
##
|
859
|
+
# Internal Functions
|
860
|
+
##
|
861
|
+
|
862
|
+
def _saveWindowSize(self) -> None:
|
863
|
+
"""Save the dialog window size."""
|
864
|
+
CONFIG.setPreferencesWinSize(self.width(), self.height())
|
865
|
+
return
|
866
|
+
|
867
|
+
def _saveValues(self) -> None:
|
868
|
+
"""Save the values set in the form."""
|
869
|
+
updateTheme = False
|
870
|
+
needsRestart = False
|
871
|
+
updateSyntax = False
|
872
|
+
refreshTree = False
|
873
|
+
|
874
|
+
# Appearance
|
875
|
+
guiLocale = self.guiLocale.currentData()
|
876
|
+
guiTheme = self.guiTheme.currentData()
|
877
|
+
guiFont = self.guiFont.text()
|
878
|
+
guiFontSize = self.guiFontSize.value()
|
879
|
+
|
880
|
+
updateTheme |= CONFIG.guiTheme != guiTheme
|
881
|
+
needsRestart |= CONFIG.guiLocale != guiLocale
|
882
|
+
needsRestart |= CONFIG.guiFont != guiFont
|
883
|
+
needsRestart |= CONFIG.guiFontSize != guiFontSize
|
884
|
+
|
885
|
+
CONFIG.guiLocale = guiLocale
|
886
|
+
CONFIG.guiTheme = guiTheme
|
887
|
+
CONFIG.guiFont = guiFont
|
888
|
+
CONFIG.guiFontSize = guiFontSize
|
889
|
+
CONFIG.hideVScroll = self.hideVScroll.isChecked()
|
890
|
+
CONFIG.hideHScroll = self.hideHScroll.isChecked()
|
891
|
+
|
892
|
+
# Document Style
|
893
|
+
guiSyntax = self.guiSyntax.currentData()
|
894
|
+
emphLabels = self.emphLabels.isChecked()
|
895
|
+
|
896
|
+
updateSyntax |= CONFIG.guiSyntax != guiSyntax
|
897
|
+
refreshTree |= CONFIG.emphLabels != emphLabels
|
898
|
+
|
899
|
+
CONFIG.guiSyntax = guiSyntax
|
900
|
+
CONFIG.emphLabels = emphLabels
|
901
|
+
CONFIG.showFullPath = self.showFullPath.isChecked()
|
902
|
+
CONFIG.incNotesWCount = self.incNotesWCount.isChecked()
|
903
|
+
CONFIG.setTextFont(self.textFont.text(), self.textSize.value())
|
904
|
+
|
905
|
+
# Auto Save
|
906
|
+
CONFIG.autoSaveDoc = self.autoSaveDoc.value()
|
907
|
+
CONFIG.autoSaveProj = self.autoSaveProj.value()
|
908
|
+
|
909
|
+
# Project Backup
|
910
|
+
CONFIG.setBackupPath(self.backupPath)
|
911
|
+
CONFIG.backupOnClose = self.backupOnClose.isChecked()
|
912
|
+
CONFIG.askBeforeBackup = self.askBeforeBackup.isChecked()
|
913
|
+
|
914
|
+
# Session Timer
|
915
|
+
CONFIG.stopWhenIdle = self.stopWhenIdle.isChecked()
|
916
|
+
CONFIG.userIdleTime = round(self.userIdleTime.value() * 60)
|
917
|
+
|
918
|
+
# Text Flow
|
919
|
+
CONFIG.textWidth = self.textWidth.value()
|
920
|
+
CONFIG.focusWidth = self.focusWidth.value()
|
921
|
+
CONFIG.hideFocusFooter = self.hideFocusFooter.isChecked()
|
922
|
+
CONFIG.doJustify = self.doJustify.isChecked()
|
923
|
+
CONFIG.textMargin = self.textMargin.value()
|
924
|
+
CONFIG.tabWidth = self.tabWidth.value()
|
925
|
+
|
926
|
+
# Text Editing
|
927
|
+
CONFIG.spellLanguage = self.spellLanguage.currentData()
|
928
|
+
CONFIG.autoSelect = self.autoSelect.isChecked()
|
929
|
+
CONFIG.showTabsNSpaces = self.showTabsNSpaces.isChecked()
|
930
|
+
CONFIG.showLineEndings = self.showLineEndings.isChecked()
|
931
|
+
|
932
|
+
# Editor Scrolling
|
933
|
+
CONFIG.autoScroll = self.autoScroll.isChecked()
|
934
|
+
CONFIG.autoScrollPos = self.autoScrollPos.value()
|
935
|
+
CONFIG.scrollPastEnd = self.scrollPastEnd.isChecked()
|
936
|
+
|
937
|
+
# Text Highlighting
|
938
|
+
highlightQuotes = self.highlightQuotes.isChecked()
|
939
|
+
highlightEmph = self.highlightEmph.isChecked()
|
940
|
+
showMultiSpaces = self.showMultiSpaces.isChecked()
|
941
|
+
|
942
|
+
updateSyntax |= CONFIG.highlightQuotes != highlightQuotes
|
943
|
+
updateSyntax |= CONFIG.highlightEmph != highlightEmph
|
944
|
+
updateSyntax |= CONFIG.showMultiSpaces != showMultiSpaces
|
945
|
+
|
946
|
+
CONFIG.highlightQuotes = highlightQuotes
|
947
|
+
CONFIG.highlightEmph = highlightEmph
|
948
|
+
CONFIG.showMultiSpaces = showMultiSpaces
|
949
|
+
CONFIG.allowOpenSQuote = self.allowOpenSQuote.isChecked()
|
950
|
+
CONFIG.allowOpenDQuote = self.allowOpenDQuote.isChecked()
|
951
|
+
|
952
|
+
# Text Automation
|
953
|
+
CONFIG.doReplace = self.doReplace.isChecked()
|
954
|
+
CONFIG.doReplaceSQuote = self.doReplaceSQuote.isChecked()
|
955
|
+
CONFIG.doReplaceDQuote = self.doReplaceDQuote.isChecked()
|
956
|
+
CONFIG.doReplaceDash = self.doReplaceDash.isChecked()
|
957
|
+
CONFIG.doReplaceDots = self.doReplaceDots.isChecked()
|
958
|
+
CONFIG.fmtPadBefore = self.fmtPadBefore.text().strip()
|
959
|
+
CONFIG.fmtPadAfter = self.fmtPadAfter.text().strip()
|
960
|
+
CONFIG.fmtPadThin = self.fmtPadThin.isChecked()
|
961
|
+
|
962
|
+
# Quotation Style
|
963
|
+
CONFIG.fmtSQuoteOpen = self.quoteSym["SO"].text()
|
964
|
+
CONFIG.fmtSQuoteClose = self.quoteSym["SC"].text()
|
965
|
+
CONFIG.fmtDQuoteOpen = self.quoteSym["DO"].text()
|
966
|
+
CONFIG.fmtDQuoteClose = self.quoteSym["DC"].text()
|
967
|
+
|
968
|
+
# Finalise
|
969
|
+
CONFIG.saveConfig()
|
970
|
+
self.newPreferencesReady.emit(needsRestart, refreshTree, updateTheme, updateSyntax)
|
1134
971
|
|
1135
972
|
return
|
1136
973
|
|
1137
|
-
# END Class
|
974
|
+
# END Class GuiPreferences
|