novelWriter 2.2b1__py3-none-any.whl → 2.2.1__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.2b1.dist-info → novelWriter-2.2.1.dist-info}/METADATA +3 -3
- {novelWriter-2.2b1.dist-info → novelWriter-2.2.1.dist-info}/RECORD +128 -114
- {novelWriter-2.2b1.dist-info → novelWriter-2.2.1.dist-info}/WHEEL +1 -1
- novelwriter/__init__.py +10 -5
- 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_GB.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/novelwriter.ico +0 -0
- novelwriter/assets/icons/typicons_dark/icons.conf +11 -3
- novelwriter/assets/icons/typicons_dark/nw_deco-h2-narrow.svg +4 -0
- novelwriter/assets/icons/typicons_dark/nw_deco-h3-narrow.svg +4 -0
- novelwriter/assets/icons/typicons_dark/nw_deco-h4-narrow.svg +4 -0
- novelwriter/assets/icons/typicons_dark/nw_deco-note.svg +4 -0
- novelwriter/assets/icons/typicons_dark/nw_panel.svg +4 -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_eye.svg +4 -0
- novelwriter/assets/icons/typicons_light/icons.conf +11 -3
- novelwriter/assets/icons/typicons_light/nw_deco-h2-narrow.svg +4 -0
- novelwriter/assets/icons/typicons_light/nw_deco-h3-narrow.svg +4 -0
- novelwriter/assets/icons/typicons_light/nw_deco-h4-narrow.svg +4 -0
- novelwriter/assets/icons/typicons_light/nw_deco-note.svg +4 -0
- novelwriter/assets/icons/typicons_light/nw_panel.svg +4 -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_eye.svg +4 -0
- novelwriter/assets/icons/x-novelwriter-project.ico +0 -0
- novelwriter/assets/manual.pdf +0 -0
- novelwriter/assets/sample.zip +0 -0
- novelwriter/assets/text/release_notes.htm +50 -7
- novelwriter/common.py +35 -27
- novelwriter/config.py +13 -28
- novelwriter/constants.py +21 -4
- novelwriter/core/buildsettings.py +2 -2
- novelwriter/core/coretools.py +8 -2
- novelwriter/core/docbuild.py +1 -1
- novelwriter/core/document.py +1 -1
- novelwriter/core/index.py +102 -36
- novelwriter/core/item.py +2 -2
- novelwriter/core/options.py +6 -3
- novelwriter/core/project.py +5 -5
- novelwriter/core/projectdata.py +3 -3
- novelwriter/core/projectxml.py +1 -1
- novelwriter/core/sessions.py +2 -2
- novelwriter/core/spellcheck.py +4 -3
- novelwriter/core/status.py +3 -3
- novelwriter/core/storage.py +1 -1
- novelwriter/core/tohtml.py +11 -5
- novelwriter/core/tokenizer.py +28 -21
- novelwriter/core/tomd.py +6 -2
- novelwriter/core/toodt.py +12 -5
- novelwriter/core/tree.py +2 -2
- novelwriter/dialogs/about.py +30 -31
- novelwriter/dialogs/docmerge.py +24 -15
- novelwriter/dialogs/docsplit.py +27 -16
- novelwriter/dialogs/editlabel.py +19 -7
- novelwriter/dialogs/preferences.py +116 -131
- novelwriter/dialogs/projdetails.py +29 -36
- novelwriter/dialogs/projload.py +32 -36
- novelwriter/dialogs/projsettings.py +20 -15
- novelwriter/dialogs/quotes.py +32 -25
- novelwriter/dialogs/updates.py +17 -16
- novelwriter/dialogs/wordlist.py +34 -21
- novelwriter/enum.py +19 -8
- novelwriter/error.py +1 -1
- novelwriter/extensions/circularprogress.py +1 -1
- novelwriter/extensions/configlayout.py +3 -15
- novelwriter/extensions/{wheeleventfilter.py → eventfilters.py} +15 -5
- novelwriter/extensions/novelselector.py +1 -1
- novelwriter/extensions/pageddialog.py +1 -1
- novelwriter/extensions/pagedsidebar.py +2 -5
- novelwriter/extensions/simpleprogress.py +8 -9
- novelwriter/extensions/statusled.py +1 -1
- novelwriter/extensions/switch.py +4 -4
- novelwriter/extensions/switchbox.py +1 -6
- novelwriter/gui/doceditor.py +349 -236
- novelwriter/gui/dochighlight.py +10 -11
- novelwriter/gui/docviewer.py +158 -360
- novelwriter/gui/docviewerpanel.py +502 -0
- novelwriter/gui/editordocument.py +4 -4
- novelwriter/gui/itemdetails.py +2 -2
- novelwriter/gui/mainmenu.py +50 -36
- novelwriter/gui/noveltree.py +44 -53
- novelwriter/gui/outline.py +12 -7
- novelwriter/gui/projtree.py +465 -381
- novelwriter/gui/sidebar.py +9 -7
- novelwriter/gui/statusbar.py +48 -5
- novelwriter/gui/theme.py +26 -8
- novelwriter/guimain.py +212 -208
- novelwriter/shared.py +76 -30
- novelwriter/tools/dictionaries.py +268 -0
- novelwriter/tools/lipsum.py +34 -28
- novelwriter/tools/manusbuild.py +20 -10
- novelwriter/tools/manuscript.py +20 -27
- novelwriter/tools/manussettings.py +2 -4
- novelwriter/tools/projwizard.py +3 -3
- novelwriter/tools/writingstats.py +18 -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_dark/typ_at.svg +0 -4
- novelwriter/assets/icons/typicons_light/nw_tb-markdown.svg +0 -8
- novelwriter/assets/icons/typicons_light/nw_tb-shortcode.svg +0 -8
- novelwriter/assets/icons/typicons_light/typ_at.svg +0 -4
- {novelWriter-2.2b1.dist-info → novelWriter-2.2.1.dist-info}/LICENSE.md +0 -0
- {novelWriter-2.2b1.dist-info → novelWriter-2.2.1.dist-info}/entry_points.txt +0 -0
- {novelWriter-2.2b1.dist-info → novelWriter-2.2.1.dist-info}/top_level.txt +0 -0
novelwriter/guimain.py
CHANGED
@@ -6,7 +6,7 @@ File History:
|
|
6
6
|
Created: 2018-09-22 [0.0.1] GuiMain
|
7
7
|
|
8
8
|
This file is a part of novelWriter
|
9
|
-
Copyright 2018–
|
9
|
+
Copyright 2018–2024, Veronica Berglyd Olsen
|
10
10
|
|
11
11
|
This program is free software: you can redistribute it and/or modify
|
12
12
|
it under the terms of the GNU General Public License as published by
|
@@ -44,10 +44,11 @@ from novelwriter.gui.outline import GuiOutlineView
|
|
44
44
|
from novelwriter.gui.mainmenu import GuiMainMenu
|
45
45
|
from novelwriter.gui.projtree import GuiProjectView
|
46
46
|
from novelwriter.gui.doceditor import GuiDocEditor
|
47
|
-
from novelwriter.gui.docviewer import
|
47
|
+
from novelwriter.gui.docviewer import GuiDocViewer
|
48
48
|
from novelwriter.gui.noveltree import GuiNovelView
|
49
49
|
from novelwriter.gui.statusbar import GuiMainStatus
|
50
50
|
from novelwriter.gui.itemdetails import GuiItemDetails
|
51
|
+
from novelwriter.gui.docviewerpanel import GuiDocViewerPanel
|
51
52
|
from novelwriter.dialogs.about import GuiAbout
|
52
53
|
from novelwriter.dialogs.updates import GuiUpdates
|
53
54
|
from novelwriter.dialogs.projload import GuiProjectLoad
|
@@ -55,16 +56,16 @@ from novelwriter.dialogs.wordlist import GuiWordList
|
|
55
56
|
from novelwriter.dialogs.preferences import GuiPreferences
|
56
57
|
from novelwriter.dialogs.projdetails import GuiProjectDetails
|
57
58
|
from novelwriter.dialogs.projsettings import GuiProjectSettings
|
58
|
-
from novelwriter.tools.lipsum import GuiLipsum
|
59
59
|
from novelwriter.tools.manuscript import GuiManuscript
|
60
60
|
from novelwriter.tools.projwizard import GuiProjectWizard
|
61
|
+
from novelwriter.tools.dictionaries import GuiDictionaries
|
61
62
|
from novelwriter.tools.writingstats import GuiWritingStats
|
62
63
|
from novelwriter.core.coretools import ProjectBuilder
|
63
64
|
|
64
65
|
from novelwriter.enum import (
|
65
66
|
nwDocAction, nwDocInsert, nwDocMode, nwItemType, nwItemClass, nwWidget, nwView
|
66
67
|
)
|
67
|
-
from novelwriter.common import
|
68
|
+
from novelwriter.common import hexToInt
|
68
69
|
from novelwriter.constants import nwFiles
|
69
70
|
|
70
71
|
logger = logging.getLogger(__name__)
|
@@ -133,16 +134,16 @@ class GuiMain(QMainWindow):
|
|
133
134
|
hWd = CONFIG.pxInt(4)
|
134
135
|
|
135
136
|
# Main GUI Elements
|
136
|
-
self.mainStatus
|
137
|
-
self.projView
|
138
|
-
self.novelView
|
139
|
-
self.docEditor
|
140
|
-
self.
|
141
|
-
self.
|
142
|
-
self.itemDetails
|
143
|
-
self.outlineView
|
144
|
-
self.mainMenu
|
145
|
-
self.sideBar
|
137
|
+
self.mainStatus = GuiMainStatus(self)
|
138
|
+
self.projView = GuiProjectView(self)
|
139
|
+
self.novelView = GuiNovelView(self)
|
140
|
+
self.docEditor = GuiDocEditor(self)
|
141
|
+
self.docViewer = GuiDocViewer(self)
|
142
|
+
self.docViewerPanel = GuiDocViewerPanel(self)
|
143
|
+
self.itemDetails = GuiItemDetails(self)
|
144
|
+
self.outlineView = GuiOutlineView(self)
|
145
|
+
self.mainMenu = GuiMainMenu(self)
|
146
|
+
self.sideBar = GuiSideBar(self)
|
146
147
|
|
147
148
|
# Project Tree Stack
|
148
149
|
self.projStack = QStackedWidget(self)
|
@@ -162,7 +163,7 @@ class GuiMain(QMainWindow):
|
|
162
163
|
# Splitter : Document Viewer / Document Meta
|
163
164
|
self.splitView = QSplitter(Qt.Vertical, self)
|
164
165
|
self.splitView.addWidget(self.docViewer)
|
165
|
-
self.splitView.addWidget(self.
|
166
|
+
self.splitView.addWidget(self.docViewerPanel)
|
166
167
|
self.splitView.setHandleWidth(hWd)
|
167
168
|
self.splitView.setOpaqueResize(False)
|
168
169
|
self.splitView.setSizes(CONFIG.viewPanePos)
|
@@ -190,12 +191,12 @@ class GuiMain(QMainWindow):
|
|
190
191
|
self.mainStack.currentChanged.connect(self._mainStackChanged)
|
191
192
|
|
192
193
|
# Indices of Splitter Widgets
|
193
|
-
self.idxTree
|
194
|
-
self.idxMain
|
195
|
-
self.idxEditor
|
196
|
-
self.idxViewer
|
197
|
-
self.idxViewDoc
|
198
|
-
self.
|
194
|
+
self.idxTree = self.splitMain.indexOf(self.treePane)
|
195
|
+
self.idxMain = self.splitMain.indexOf(self.splitDocs)
|
196
|
+
self.idxEditor = self.splitDocs.indexOf(self.docEditor)
|
197
|
+
self.idxViewer = self.splitDocs.indexOf(self.splitView)
|
198
|
+
self.idxViewDoc = self.splitView.indexOf(self.docViewer)
|
199
|
+
self.idxViewDocPanel = self.splitView.indexOf(self.docViewerPanel)
|
199
200
|
|
200
201
|
# Indices of Stack Widgets
|
201
202
|
self.idxEditorView = self.mainStack.indexOf(self.splitMain)
|
@@ -209,7 +210,7 @@ class GuiMain(QMainWindow):
|
|
209
210
|
self.splitDocs.setCollapsible(self.idxEditor, False)
|
210
211
|
self.splitDocs.setCollapsible(self.idxViewer, False)
|
211
212
|
self.splitView.setCollapsible(self.idxViewDoc, False)
|
212
|
-
self.splitView.setCollapsible(self.
|
213
|
+
self.splitView.setCollapsible(self.idxViewDocPanel, False)
|
213
214
|
|
214
215
|
self.splitMain.setStretchFactor(self.idxTree, 0)
|
215
216
|
self.splitMain.setStretchFactor(self.idxMain, 1)
|
@@ -242,6 +243,12 @@ class GuiMain(QMainWindow):
|
|
242
243
|
SHARED.projectStatusChanged.connect(self.mainStatus.updateProjectStatus)
|
243
244
|
SHARED.projectStatusMessage.connect(self.mainStatus.setStatusMessage)
|
244
245
|
SHARED.spellLanguageChanged.connect(self.mainStatus.setLanguage)
|
246
|
+
SHARED.indexChangedTags.connect(self.docViewerPanel.updateChangedTags)
|
247
|
+
SHARED.indexScannedText.connect(self.docViewerPanel.projectItemChanged)
|
248
|
+
SHARED.indexScannedText.connect(self.projView.updateItemValues)
|
249
|
+
SHARED.indexScannedText.connect(self.itemDetails.updateViewBox)
|
250
|
+
SHARED.indexCleared.connect(self.docViewerPanel.indexWasCleared)
|
251
|
+
SHARED.indexAvailable.connect(self.docViewerPanel.indexHasAppeared)
|
245
252
|
|
246
253
|
self.mainMenu.requestDocAction.connect(self._passDocumentAction)
|
247
254
|
self.mainMenu.requestDocInsert.connect(self._passDocumentInsert)
|
@@ -257,6 +264,7 @@ class GuiMain(QMainWindow):
|
|
257
264
|
self.projView.treeItemChanged.connect(self.docEditor.updateDocInfo)
|
258
265
|
self.projView.treeItemChanged.connect(self.docViewer.updateDocInfo)
|
259
266
|
self.projView.treeItemChanged.connect(self.itemDetails.updateViewBox)
|
267
|
+
self.projView.treeItemChanged.connect(self.docViewerPanel.projectItemChanged)
|
260
268
|
self.projView.rootFolderChanged.connect(self.outlineView.updateRootItem)
|
261
269
|
self.projView.rootFolderChanged.connect(self.novelView.updateRootItem)
|
262
270
|
self.projView.rootFolderChanged.connect(self.projView.updateRootItem)
|
@@ -275,8 +283,16 @@ class GuiMain(QMainWindow):
|
|
275
283
|
self.docEditor.spellCheckStateChanged.connect(self.mainMenu.setSpellCheckState)
|
276
284
|
self.docEditor.closeDocumentRequest.connect(self.closeDocEditor)
|
277
285
|
self.docEditor.toggleFocusModeRequest.connect(self.toggleFocusMode)
|
286
|
+
self.docEditor.requestProjectItemSelected.connect(self.projView.setSelectedHandle)
|
287
|
+
self.docEditor.requestProjectItemRenamed.connect(self.projView.renameTreeItem)
|
278
288
|
|
289
|
+
self.docViewer.documentLoaded.connect(self.docViewerPanel.updateHandle)
|
279
290
|
self.docViewer.loadDocumentTagRequest.connect(self._followTag)
|
291
|
+
self.docViewer.togglePanelVisibility.connect(self._toggleViewerPanelVisibility)
|
292
|
+
self.docViewer.requestProjectItemSelected.connect(self.projView.setSelectedHandle)
|
293
|
+
|
294
|
+
self.docViewerPanel.loadDocumentTagRequest.connect(self._followTag)
|
295
|
+
self.docViewerPanel.openDocumentRequest.connect(self._openDocument)
|
280
296
|
|
281
297
|
self.outlineView.loadDocumentTagRequest.connect(self._followTag)
|
282
298
|
self.outlineView.openDocumentRequest.connect(self._openDocument)
|
@@ -321,19 +337,9 @@ class GuiMain(QMainWindow):
|
|
321
337
|
self.asProjTimer.start()
|
322
338
|
self.asDocTimer.start()
|
323
339
|
self.mainStatus.clearStatus()
|
324
|
-
|
325
|
-
# Handle Windows Mode
|
326
340
|
self.showNormal()
|
327
341
|
|
328
342
|
logger.debug("Ready: GUI")
|
329
|
-
|
330
|
-
if __hexversion__[-2] == "a" and logger.getEffectiveLevel() > logging.DEBUG:
|
331
|
-
SHARED.warn(self.tr(
|
332
|
-
"You are running an untested development version of novelWriter. "
|
333
|
-
"Please be careful when working on a live project "
|
334
|
-
"and make sure you take regular backups."
|
335
|
-
))
|
336
|
-
|
337
343
|
logger.info("novelWriter is ready ...")
|
338
344
|
self.mainStatus.setStatusMessage(self.tr("novelWriter is ready ..."))
|
339
345
|
|
@@ -437,6 +443,7 @@ class GuiMain(QMainWindow):
|
|
437
443
|
self.docViewer.clearNavHistory()
|
438
444
|
self.closeDocViewer(byUser=False)
|
439
445
|
|
446
|
+
self.docViewerPanel.closeProjectTasks()
|
440
447
|
self.outlineView.closeProjectTasks()
|
441
448
|
self.novelView.closeProjectTasks()
|
442
449
|
self.projView.clearProjectView()
|
@@ -510,6 +517,7 @@ class GuiMain(QMainWindow):
|
|
510
517
|
self.projView.openProjectTasks()
|
511
518
|
self.novelView.openProjectTasks()
|
512
519
|
self.outlineView.openProjectTasks()
|
520
|
+
self.docViewerPanel.openProjectTasks()
|
513
521
|
self._updateStatusWordCount()
|
514
522
|
|
515
523
|
# Restore previously open documents, if any
|
@@ -598,7 +606,7 @@ class GuiMain(QMainWindow):
|
|
598
606
|
if self.docEditor.loadText(tHandle, tLine):
|
599
607
|
SHARED.project.data.setLastHandle(tHandle, "editor")
|
600
608
|
self.projView.setSelectedHandle(tHandle, doScroll=doScroll)
|
601
|
-
self.novelView.setActiveHandle(tHandle)
|
609
|
+
self.novelView.setActiveHandle(tHandle, doScroll=doScroll)
|
602
610
|
if changeFocus:
|
603
611
|
self.docEditor.setFocus()
|
604
612
|
else:
|
@@ -675,13 +683,19 @@ class GuiMain(QMainWindow):
|
|
675
683
|
logger.debug("Viewing document with handle '%s'", tHandle)
|
676
684
|
if self.docViewer.loadText(tHandle):
|
677
685
|
if not self.splitView.isVisible():
|
686
|
+
cursorVisible = self.docEditor.cursorIsVisible()
|
678
687
|
bPos = self.splitMain.sizes()
|
679
688
|
self.splitView.setVisible(True)
|
680
689
|
vPos = [0, 0]
|
681
690
|
vPos[0] = int(bPos[1]/2)
|
682
691
|
vPos[1] = bPos[1] - vPos[0]
|
683
692
|
self.splitDocs.setSizes(vPos)
|
684
|
-
self.
|
693
|
+
self.docViewerPanel.setVisible(CONFIG.showViewerPanel)
|
694
|
+
|
695
|
+
# Since editor width changes, we need to make sure we
|
696
|
+
# restore cursor visibility in the editor. See #1302
|
697
|
+
if cursorVisible:
|
698
|
+
self.docEditor.ensureCursorVisibleNoCentre()
|
685
699
|
|
686
700
|
if sTitle:
|
687
701
|
self.docViewer.navigateTo(f"#{sTitle}")
|
@@ -782,11 +796,9 @@ class GuiMain(QMainWindow):
|
|
782
796
|
if not SHARED.hasProject:
|
783
797
|
logger.error("No project open")
|
784
798
|
return False
|
785
|
-
|
786
799
|
if tHandle is None and (self.docEditor.anyFocus() or self.isFocusMode):
|
787
800
|
tHandle = self.docEditor.docHandle
|
788
801
|
self.projView.renameTreeItem(tHandle)
|
789
|
-
|
790
802
|
return True
|
791
803
|
|
792
804
|
def rebuildTrees(self) -> None:
|
@@ -853,198 +865,113 @@ class GuiMain(QMainWindow):
|
|
853
865
|
|
854
866
|
return None
|
855
867
|
|
868
|
+
@pyqtSlot()
|
856
869
|
def showPreferencesDialog(self) -> None:
|
857
870
|
"""Open the preferences dialog."""
|
858
|
-
|
859
|
-
|
860
|
-
|
861
|
-
if dlgConf.result() == QDialog.Accepted:
|
862
|
-
logger.debug("Applying new preferences")
|
863
|
-
self.initMain()
|
864
|
-
self.saveDocument()
|
865
|
-
|
866
|
-
if dlgConf.needsRestart:
|
867
|
-
SHARED.info(self.tr(
|
868
|
-
"Some changes will not be applied until novelWriter has been restarted."
|
869
|
-
))
|
870
|
-
|
871
|
-
if dlgConf.refreshTree:
|
872
|
-
self.projView.populateTree()
|
873
|
-
|
874
|
-
if dlgConf.updateTheme:
|
875
|
-
# We are doing this manually instead of connecting to
|
876
|
-
# qApp.paletteChanged since the processing order matters
|
877
|
-
SHARED.theme.loadTheme()
|
878
|
-
self.docEditor.updateTheme()
|
879
|
-
self.docViewer.updateTheme()
|
880
|
-
self.sideBar.updateTheme()
|
881
|
-
self.projView.updateTheme()
|
882
|
-
self.novelView.updateTheme()
|
883
|
-
self.outlineView.updateTheme()
|
884
|
-
self.itemDetails.updateTheme()
|
885
|
-
self.mainStatus.updateTheme()
|
886
|
-
|
887
|
-
if dlgConf.updateSyntax:
|
888
|
-
SHARED.theme.loadSyntax()
|
889
|
-
self.docEditor.updateSyntaxColours()
|
890
|
-
|
891
|
-
self.docEditor.initEditor()
|
892
|
-
self.docViewer.initViewer()
|
893
|
-
self.projView.initSettings()
|
894
|
-
self.novelView.initSettings()
|
895
|
-
self.outlineView.initSettings()
|
896
|
-
|
897
|
-
self._updateStatusWordCount()
|
898
|
-
|
871
|
+
dialog = GuiPreferences(self)
|
872
|
+
dialog.newPreferencesReady.connect(self._processConfigChanges)
|
873
|
+
dialog.exec_()
|
899
874
|
return
|
900
875
|
|
876
|
+
@pyqtSlot()
|
901
877
|
@pyqtSlot(int)
|
902
|
-
def showProjectSettingsDialog(self, focusTab: int = GuiProjectSettings.TAB_MAIN) ->
|
878
|
+
def showProjectSettingsDialog(self, focusTab: int = GuiProjectSettings.TAB_MAIN) -> None:
|
903
879
|
"""Open the project settings dialog."""
|
904
|
-
if
|
905
|
-
|
906
|
-
|
907
|
-
|
908
|
-
|
909
|
-
dlgProj.exec_()
|
910
|
-
|
911
|
-
if dlgProj.result() == QDialog.Accepted:
|
912
|
-
logger.debug("Applying new project settings")
|
913
|
-
SHARED.updateSpellCheckLanguage()
|
914
|
-
self.itemDetails.refreshDetails()
|
915
|
-
self._updateWindowTitle(SHARED.project.data.name)
|
916
|
-
|
917
|
-
return True
|
880
|
+
if SHARED.hasProject:
|
881
|
+
dialog = GuiProjectSettings(self, focusTab=focusTab)
|
882
|
+
dialog.newProjectSettingsReady.connect(self._processProjectSettingsChanges)
|
883
|
+
dialog.exec_()
|
884
|
+
return
|
918
885
|
|
919
|
-
|
886
|
+
@pyqtSlot()
|
887
|
+
def showProjectDetailsDialog(self) -> None:
|
920
888
|
"""Open the project details dialog."""
|
921
|
-
if
|
922
|
-
|
923
|
-
|
924
|
-
|
925
|
-
|
926
|
-
|
927
|
-
|
928
|
-
|
929
|
-
|
930
|
-
dlgDetails.setModal(True)
|
931
|
-
dlgDetails.show()
|
932
|
-
dlgDetails.raise_()
|
933
|
-
dlgDetails.updateValues()
|
934
|
-
|
935
|
-
return True
|
889
|
+
if SHARED.hasProject:
|
890
|
+
dialog = GuiProjectDetails(self)
|
891
|
+
dialog.setModal(True)
|
892
|
+
dialog.show()
|
893
|
+
dialog.raise_()
|
894
|
+
qApp.processEvents()
|
895
|
+
dialog.updateValues()
|
896
|
+
return
|
936
897
|
|
937
898
|
@pyqtSlot()
|
938
|
-
def showBuildManuscriptDialog(self) ->
|
899
|
+
def showBuildManuscriptDialog(self) -> None:
|
939
900
|
"""Open the build manuscript dialog."""
|
940
|
-
if
|
941
|
-
|
942
|
-
|
943
|
-
|
944
|
-
|
945
|
-
|
946
|
-
|
947
|
-
|
948
|
-
|
949
|
-
dlgBuild.setModal(False)
|
950
|
-
dlgBuild.show()
|
951
|
-
dlgBuild.raise_()
|
952
|
-
qApp.processEvents()
|
953
|
-
|
954
|
-
dlgBuild.loadContent()
|
955
|
-
|
956
|
-
return True
|
957
|
-
|
958
|
-
def showLoremIpsumDialog(self) -> bool:
|
959
|
-
"""Open the insert lorem ipsum text dialog."""
|
960
|
-
if not SHARED.hasProject:
|
961
|
-
logger.error("No project open")
|
962
|
-
return False
|
963
|
-
|
964
|
-
dlgLipsum = getGuiItem("GuiLipsum")
|
965
|
-
if dlgLipsum is None:
|
966
|
-
dlgLipsum = GuiLipsum(self)
|
967
|
-
assert isinstance(dlgLipsum, GuiLipsum)
|
968
|
-
|
969
|
-
dlgLipsum.setModal(False)
|
970
|
-
dlgLipsum.show()
|
971
|
-
dlgLipsum.raise_()
|
972
|
-
qApp.processEvents()
|
973
|
-
|
974
|
-
return True
|
901
|
+
if SHARED.hasProject:
|
902
|
+
if (dialog := SHARED.findTopLevelWidget(GuiManuscript)) is None:
|
903
|
+
dialog = GuiManuscript(self)
|
904
|
+
dialog.setModal(False)
|
905
|
+
dialog.show()
|
906
|
+
dialog.raise_()
|
907
|
+
qApp.processEvents()
|
908
|
+
dialog.loadContent()
|
909
|
+
return
|
975
910
|
|
976
|
-
|
911
|
+
@pyqtSlot()
|
912
|
+
def showProjectWordListDialog(self) -> None:
|
977
913
|
"""Open the project word list dialog."""
|
978
|
-
if
|
979
|
-
|
980
|
-
|
981
|
-
|
982
|
-
|
983
|
-
dlgWords.exec_()
|
984
|
-
|
985
|
-
if dlgWords.result() == QDialog.Accepted:
|
986
|
-
logger.debug("Reloading word list")
|
987
|
-
SHARED.updateSpellCheckLanguage(reload=True)
|
988
|
-
self.docEditor.spellCheckDocument()
|
989
|
-
|
990
|
-
return True
|
914
|
+
if SHARED.hasProject:
|
915
|
+
dialog = GuiWordList(self)
|
916
|
+
dialog.newWordListReady.connect(self._processWordListChanges)
|
917
|
+
dialog.exec_()
|
918
|
+
return
|
991
919
|
|
992
|
-
|
920
|
+
@pyqtSlot()
|
921
|
+
def showWritingStatsDialog(self) -> None:
|
993
922
|
"""Open the session stats dialog."""
|
994
|
-
if
|
995
|
-
|
996
|
-
|
997
|
-
|
998
|
-
|
999
|
-
|
1000
|
-
|
1001
|
-
|
1002
|
-
|
1003
|
-
dlgStats.setModal(False)
|
1004
|
-
dlgStats.show()
|
1005
|
-
dlgStats.raise_()
|
1006
|
-
qApp.processEvents()
|
1007
|
-
dlgStats.populateGUI()
|
1008
|
-
|
1009
|
-
return True
|
1010
|
-
|
1011
|
-
def showAboutNWDialog(self, showNotes: bool = False) -> bool:
|
1012
|
-
"""Show the about dialog for novelWriter."""
|
1013
|
-
dlgAbout = getGuiItem("GuiAbout")
|
1014
|
-
if dlgAbout is None:
|
1015
|
-
dlgAbout = GuiAbout(self)
|
1016
|
-
assert isinstance(dlgAbout, GuiAbout)
|
923
|
+
if SHARED.hasProject:
|
924
|
+
if (dialog := SHARED.findTopLevelWidget(GuiWritingStats)) is None:
|
925
|
+
dialog = GuiWritingStats(self)
|
926
|
+
dialog.setModal(False)
|
927
|
+
dialog.show()
|
928
|
+
dialog.raise_()
|
929
|
+
qApp.processEvents()
|
930
|
+
dialog.populateGUI()
|
931
|
+
return
|
1017
932
|
|
1018
|
-
|
1019
|
-
|
1020
|
-
|
933
|
+
@pyqtSlot()
|
934
|
+
def showAboutNWDialog(self, showNotes: bool = False) -> None:
|
935
|
+
"""Show the novelWriter about dialog."""
|
936
|
+
dialog = GuiAbout(self)
|
937
|
+
dialog.setModal(True)
|
938
|
+
dialog.show()
|
939
|
+
dialog.raise_()
|
1021
940
|
qApp.processEvents()
|
1022
|
-
|
1023
|
-
|
941
|
+
dialog.populateGUI()
|
1024
942
|
if showNotes:
|
1025
|
-
|
1026
|
-
|
1027
|
-
return True
|
943
|
+
dialog.showReleaseNotes()
|
944
|
+
return
|
1028
945
|
|
946
|
+
@pyqtSlot()
|
1029
947
|
def showAboutQtDialog(self) -> None:
|
1030
|
-
"""Show the about dialog
|
948
|
+
"""Show the Qt about dialog."""
|
1031
949
|
msgBox = QMessageBox(self)
|
1032
950
|
msgBox.aboutQt(self, "About Qt")
|
1033
951
|
return
|
1034
952
|
|
953
|
+
@pyqtSlot()
|
1035
954
|
def showUpdatesDialog(self) -> None:
|
1036
955
|
"""Show the check for updates dialog."""
|
1037
|
-
|
1038
|
-
|
1039
|
-
|
1040
|
-
|
1041
|
-
|
1042
|
-
dlgUpdate.setModal(True)
|
1043
|
-
dlgUpdate.show()
|
1044
|
-
dlgUpdate.raise_()
|
956
|
+
dialog = GuiUpdates(self)
|
957
|
+
dialog.setModal(True)
|
958
|
+
dialog.show()
|
959
|
+
dialog.raise_()
|
1045
960
|
qApp.processEvents()
|
1046
|
-
|
961
|
+
dialog.checkLatest()
|
962
|
+
return
|
1047
963
|
|
964
|
+
@pyqtSlot()
|
965
|
+
def showDictionariesDialog(self) -> None:
|
966
|
+
"""Show the download dictionaries dialog."""
|
967
|
+
dialog = GuiDictionaries(self)
|
968
|
+
dialog.setModal(True)
|
969
|
+
dialog.show()
|
970
|
+
dialog.raise_()
|
971
|
+
qApp.processEvents()
|
972
|
+
if not dialog.initDialog():
|
973
|
+
dialog.close()
|
974
|
+
SHARED.error(self.tr("Could not initialise the dialog."))
|
1048
975
|
return
|
1049
976
|
|
1050
977
|
def reportConfErr(self) -> bool:
|
@@ -1076,10 +1003,10 @@ class GuiMain(QMainWindow):
|
|
1076
1003
|
if not self.isFocusMode:
|
1077
1004
|
CONFIG.setMainPanePos(self.splitMain.sizes())
|
1078
1005
|
CONFIG.setOutlinePanePos(self.outlineView.splitSizes())
|
1079
|
-
if self.
|
1006
|
+
if self.docViewerPanel.isVisible():
|
1080
1007
|
CONFIG.setViewPanePos(self.splitView.sizes())
|
1081
1008
|
|
1082
|
-
CONFIG.
|
1009
|
+
CONFIG.showViewerPanel = self.docViewerPanel.isVisible()
|
1083
1010
|
if self.windowState() & Qt.WindowFullScreen != Qt.WindowFullScreen:
|
1084
1011
|
# Ignore window size if in full screen mode
|
1085
1012
|
CONFIG.setMainWinSize(self.width(), self.height())
|
@@ -1101,11 +1028,18 @@ class GuiMain(QMainWindow):
|
|
1101
1028
|
# Only reset the last handle if the user called this
|
1102
1029
|
SHARED.project.data.setLastHandle(None, "viewer")
|
1103
1030
|
|
1031
|
+
cursorVisible = self.docEditor.cursorIsVisible()
|
1032
|
+
|
1104
1033
|
# Hide the panel
|
1105
1034
|
bPos = self.splitMain.sizes()
|
1106
1035
|
self.splitView.setVisible(False)
|
1107
1036
|
self.splitDocs.setSizes([bPos[1], 0])
|
1108
1037
|
|
1038
|
+
# Since editor width changes, we need to make sure we restore
|
1039
|
+
# cursor visibility in the editor. See #1302
|
1040
|
+
if cursorVisible:
|
1041
|
+
self.docEditor.ensureCursorVisibleNoCentre()
|
1042
|
+
|
1109
1043
|
return not self.splitView.isVisible()
|
1110
1044
|
|
1111
1045
|
def toggleFullScreenMode(self) -> None:
|
@@ -1121,10 +1055,7 @@ class GuiMain(QMainWindow):
|
|
1121
1055
|
"""Capture the closing event of the GUI and call the close
|
1122
1056
|
function to handle all the close process steps.
|
1123
1057
|
"""
|
1124
|
-
if self.closeMain()
|
1125
|
-
event.accept()
|
1126
|
-
else:
|
1127
|
-
event.ignore()
|
1058
|
+
event.accept() if self.closeMain() else event.ignore()
|
1128
1059
|
return
|
1129
1060
|
|
1130
1061
|
##
|
@@ -1154,6 +1085,7 @@ class GuiMain(QMainWindow):
|
|
1154
1085
|
else:
|
1155
1086
|
logger.debug("Deactivating Focus Mode")
|
1156
1087
|
|
1088
|
+
cursorVisible = self.docEditor.cursorIsVisible()
|
1157
1089
|
isVisible = not self.isFocusMode
|
1158
1090
|
self.treePane.setVisible(isVisible)
|
1159
1091
|
self.mainStatus.setVisible(isVisible)
|
@@ -1169,6 +1101,9 @@ class GuiMain(QMainWindow):
|
|
1169
1101
|
elif self.docViewer.docHandle is not None:
|
1170
1102
|
self.splitView.setVisible(True)
|
1171
1103
|
|
1104
|
+
if cursorVisible:
|
1105
|
+
self.docEditor.ensureCursorVisibleNoCentre()
|
1106
|
+
|
1172
1107
|
return
|
1173
1108
|
|
1174
1109
|
@pyqtSlot(nwWidget)
|
@@ -1202,6 +1137,65 @@ class GuiMain(QMainWindow):
|
|
1202
1137
|
# Private Slots
|
1203
1138
|
##
|
1204
1139
|
|
1140
|
+
@pyqtSlot(bool, bool, bool, bool)
|
1141
|
+
def _processConfigChanges(self, restart: bool, tree: bool, theme: bool, syntax: bool) -> None:
|
1142
|
+
"""Refresh GUI based on flags from the Preferences dialog."""
|
1143
|
+
logger.debug("Applying new preferences")
|
1144
|
+
self.initMain()
|
1145
|
+
self.saveDocument()
|
1146
|
+
|
1147
|
+
if restart:
|
1148
|
+
SHARED.info(self.tr(
|
1149
|
+
"Some changes will not be applied until novelWriter has been restarted."
|
1150
|
+
))
|
1151
|
+
|
1152
|
+
if tree:
|
1153
|
+
self.projView.populateTree()
|
1154
|
+
|
1155
|
+
if theme:
|
1156
|
+
# We are doing this manually instead of connecting to
|
1157
|
+
# qApp.paletteChanged since the processing order matters
|
1158
|
+
SHARED.theme.loadTheme()
|
1159
|
+
self.docEditor.updateTheme()
|
1160
|
+
self.docViewer.updateTheme()
|
1161
|
+
self.docViewerPanel.updateTheme()
|
1162
|
+
self.sideBar.updateTheme()
|
1163
|
+
self.projView.updateTheme()
|
1164
|
+
self.novelView.updateTheme()
|
1165
|
+
self.outlineView.updateTheme()
|
1166
|
+
self.itemDetails.updateTheme()
|
1167
|
+
self.mainStatus.updateTheme()
|
1168
|
+
|
1169
|
+
if syntax:
|
1170
|
+
SHARED.theme.loadSyntax()
|
1171
|
+
self.docEditor.updateSyntaxColours()
|
1172
|
+
|
1173
|
+
self.docEditor.initEditor()
|
1174
|
+
self.docViewer.initViewer()
|
1175
|
+
self.projView.initSettings()
|
1176
|
+
self.novelView.initSettings()
|
1177
|
+
self.outlineView.initSettings()
|
1178
|
+
self._updateStatusWordCount()
|
1179
|
+
|
1180
|
+
return
|
1181
|
+
|
1182
|
+
@pyqtSlot()
|
1183
|
+
def _processProjectSettingsChanges(self) -> None:
|
1184
|
+
"""Refresh data dependent on project settings."""
|
1185
|
+
logger.debug("Applying new project settings")
|
1186
|
+
SHARED.updateSpellCheckLanguage()
|
1187
|
+
self.itemDetails.refreshDetails()
|
1188
|
+
self._updateWindowTitle(SHARED.project.data.name)
|
1189
|
+
return
|
1190
|
+
|
1191
|
+
@pyqtSlot()
|
1192
|
+
def _processWordListChanges(self) -> None:
|
1193
|
+
"""Reload project word list."""
|
1194
|
+
logger.debug("Reloading word list")
|
1195
|
+
SHARED.updateSpellCheckLanguage(reload=True)
|
1196
|
+
self.docEditor.spellCheckDocument()
|
1197
|
+
return
|
1198
|
+
|
1205
1199
|
@pyqtSlot(str, nwDocMode)
|
1206
1200
|
def _followTag(self, tag: str, mode: nwDocMode) -> None:
|
1207
1201
|
"""Follow a tag after user interaction with a link."""
|
@@ -1267,6 +1261,13 @@ class GuiMain(QMainWindow):
|
|
1267
1261
|
self.docEditor.insertText(content)
|
1268
1262
|
return
|
1269
1263
|
|
1264
|
+
@pyqtSlot()
|
1265
|
+
def _toggleViewerPanelVisibility(self):
|
1266
|
+
"""Toggle the visibility of the document viewer panel."""
|
1267
|
+
CONFIG.showViewerPanel = not CONFIG.showViewerPanel
|
1268
|
+
self.docViewerPanel.setVisible(CONFIG.showViewerPanel)
|
1269
|
+
return
|
1270
|
+
|
1270
1271
|
@pyqtSlot()
|
1271
1272
|
def _timeTick(self) -> None:
|
1272
1273
|
"""Process time tick of the main timer."""
|
@@ -1278,6 +1279,8 @@ class GuiMain(QMainWindow):
|
|
1278
1279
|
self.mainStatus.setUserIdle(editIdle or userIdle)
|
1279
1280
|
SHARED.updateIdleTime(currTime, editIdle or userIdle)
|
1280
1281
|
self.mainStatus.updateTime(idleTime=SHARED.projectIdleTime)
|
1282
|
+
if CONFIG.memInfo and int(currTime) % 5 == 0: # pragma: no cover
|
1283
|
+
self.mainStatus.memInfo()
|
1281
1284
|
return
|
1282
1285
|
|
1283
1286
|
@pyqtSlot()
|
@@ -1408,6 +1411,7 @@ class GuiMain(QMainWindow):
|
|
1408
1411
|
self.addAction(self.mainMenu.aInsTimes)
|
1409
1412
|
self.addAction(self.mainMenu.aInsDivide)
|
1410
1413
|
self.addAction(self.mainMenu.aInsSynopsis)
|
1414
|
+
self.addAction(self.mainMenu.aInsShort)
|
1411
1415
|
|
1412
1416
|
for mAction, _ in self.mainMenu.mInsKWItems.values():
|
1413
1417
|
self.addAction(mAction)
|
@@ -1420,8 +1424,8 @@ class GuiMain(QMainWindow):
|
|
1420
1424
|
self.addAction(self.mainMenu.aReplaceNext)
|
1421
1425
|
|
1422
1426
|
# Format
|
1423
|
-
self.addAction(self.mainMenu.
|
1424
|
-
self.addAction(self.mainMenu.
|
1427
|
+
self.addAction(self.mainMenu.aFmtItalic)
|
1428
|
+
self.addAction(self.mainMenu.aFmtBold)
|
1425
1429
|
self.addAction(self.mainMenu.aFmtStrike)
|
1426
1430
|
self.addAction(self.mainMenu.aFmtDQuote)
|
1427
1431
|
self.addAction(self.mainMenu.aFmtSQuote)
|