novelWriter 2.5.3__py3-none-any.whl → 2.6b2__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.5.3.dist-info → novelWriter-2.6b2.dist-info}/METADATA +1 -1
- {novelWriter-2.5.3.dist-info → novelWriter-2.6b2.dist-info}/RECORD +80 -60
- novelwriter/__init__.py +49 -10
- novelwriter/assets/i18n/project_en_GB.json +1 -0
- novelwriter/assets/icons/typicons_dark/icons.conf +8 -0
- novelwriter/assets/icons/typicons_dark/mixed_copy.svg +4 -0
- novelwriter/assets/icons/typicons_dark/mixed_margin-bottom.svg +6 -0
- novelwriter/assets/icons/typicons_dark/mixed_margin-left.svg +6 -0
- novelwriter/assets/icons/typicons_dark/mixed_margin-right.svg +6 -0
- novelwriter/assets/icons/typicons_dark/mixed_margin-top.svg +6 -0
- novelwriter/assets/icons/typicons_dark/mixed_size-height.svg +6 -0
- novelwriter/assets/icons/typicons_dark/mixed_size-width.svg +6 -0
- novelwriter/assets/icons/typicons_dark/nw_toolbar.svg +5 -0
- novelwriter/assets/icons/typicons_light/icons.conf +8 -0
- novelwriter/assets/icons/typicons_light/mixed_copy.svg +4 -0
- novelwriter/assets/icons/typicons_light/mixed_margin-bottom.svg +6 -0
- novelwriter/assets/icons/typicons_light/mixed_margin-left.svg +6 -0
- novelwriter/assets/icons/typicons_light/mixed_margin-right.svg +6 -0
- novelwriter/assets/icons/typicons_light/mixed_margin-top.svg +6 -0
- novelwriter/assets/icons/typicons_light/mixed_size-height.svg +6 -0
- novelwriter/assets/icons/typicons_light/mixed_size-width.svg +6 -0
- novelwriter/assets/icons/typicons_light/nw_toolbar.svg +5 -0
- novelwriter/assets/manual.pdf +0 -0
- novelwriter/assets/sample.zip +0 -0
- novelwriter/common.py +100 -2
- novelwriter/config.py +25 -15
- novelwriter/constants.py +168 -60
- novelwriter/core/buildsettings.py +66 -39
- novelwriter/core/coretools.py +145 -147
- novelwriter/core/docbuild.py +132 -170
- novelwriter/core/index.py +38 -37
- novelwriter/core/item.py +41 -8
- novelwriter/core/itemmodel.py +518 -0
- novelwriter/core/options.py +4 -1
- novelwriter/core/project.py +67 -89
- novelwriter/core/spellcheck.py +9 -14
- novelwriter/core/status.py +7 -5
- novelwriter/core/tree.py +268 -287
- novelwriter/dialogs/docmerge.py +7 -17
- novelwriter/dialogs/preferences.py +46 -33
- novelwriter/dialogs/projectsettings.py +5 -5
- novelwriter/enum.py +36 -23
- novelwriter/extensions/configlayout.py +27 -12
- novelwriter/extensions/modified.py +13 -1
- novelwriter/extensions/pagedsidebar.py +5 -5
- novelwriter/formats/shared.py +155 -0
- novelwriter/formats/todocx.py +1191 -0
- novelwriter/formats/tohtml.py +451 -0
- novelwriter/{core → formats}/tokenizer.py +487 -491
- novelwriter/formats/tomarkdown.py +217 -0
- novelwriter/{core → formats}/toodt.py +311 -432
- novelwriter/formats/toqdoc.py +484 -0
- novelwriter/formats/toraw.py +91 -0
- novelwriter/gui/doceditor.py +342 -284
- novelwriter/gui/dochighlight.py +96 -84
- novelwriter/gui/docviewer.py +88 -31
- novelwriter/gui/docviewerpanel.py +17 -25
- novelwriter/gui/editordocument.py +17 -2
- novelwriter/gui/itemdetails.py +25 -28
- novelwriter/gui/mainmenu.py +129 -63
- novelwriter/gui/noveltree.py +45 -47
- novelwriter/gui/outline.py +196 -249
- novelwriter/gui/projtree.py +594 -1241
- novelwriter/gui/search.py +9 -10
- novelwriter/gui/sidebar.py +7 -6
- novelwriter/gui/theme.py +10 -5
- novelwriter/guimain.py +100 -196
- novelwriter/shared.py +66 -27
- novelwriter/text/counting.py +2 -0
- novelwriter/text/patterns.py +168 -60
- novelwriter/tools/manusbuild.py +14 -12
- novelwriter/tools/manuscript.py +120 -78
- novelwriter/tools/manussettings.py +424 -291
- novelwriter/tools/welcome.py +4 -4
- novelwriter/tools/writingstats.py +3 -3
- novelwriter/types.py +23 -7
- novelwriter/core/tohtml.py +0 -530
- novelwriter/core/tomarkdown.py +0 -252
- novelwriter/core/toqdoc.py +0 -419
- {novelWriter-2.5.3.dist-info → novelWriter-2.6b2.dist-info}/LICENSE.md +0 -0
- {novelWriter-2.5.3.dist-info → novelWriter-2.6b2.dist-info}/WHEEL +0 -0
- {novelWriter-2.5.3.dist-info → novelWriter-2.6b2.dist-info}/entry_points.txt +0 -0
- {novelWriter-2.5.3.dist-info → novelWriter-2.6b2.dist-info}/top_level.txt +0 -0
novelwriter/gui/search.py
CHANGED
@@ -30,15 +30,18 @@ from time import time
|
|
30
30
|
from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot
|
31
31
|
from PyQt5.QtGui import QCursor, QKeyEvent
|
32
32
|
from PyQt5.QtWidgets import (
|
33
|
-
QApplication, QFrame, QHBoxLayout,
|
34
|
-
|
33
|
+
QApplication, QFrame, QHBoxLayout, QLabel, QLineEdit, QToolBar,
|
34
|
+
QTreeWidget, QTreeWidgetItem, QVBoxLayout, QWidget
|
35
35
|
)
|
36
36
|
|
37
37
|
from novelwriter import CONFIG, SHARED
|
38
38
|
from novelwriter.common import checkInt, cssCol
|
39
39
|
from novelwriter.core.coretools import DocSearch
|
40
40
|
from novelwriter.core.item import NWItem
|
41
|
-
from novelwriter.types import
|
41
|
+
from novelwriter.types import (
|
42
|
+
QtAlignMiddle, QtAlignRight, QtHeaderStretch, QtHeaderToContents,
|
43
|
+
QtUserRole
|
44
|
+
)
|
42
45
|
|
43
46
|
logger = logging.getLogger(__name__)
|
44
47
|
|
@@ -120,8 +123,8 @@ class GuiProjectSearch(QWidget):
|
|
120
123
|
|
121
124
|
treeHeader = self.searchResult.header()
|
122
125
|
treeHeader.setStretchLastSection(False)
|
123
|
-
treeHeader.setSectionResizeMode(self.C_NAME,
|
124
|
-
treeHeader.setSectionResizeMode(self.C_COUNT,
|
126
|
+
treeHeader.setSectionResizeMode(self.C_NAME, QtHeaderStretch)
|
127
|
+
treeHeader.setSectionResizeMode(self.C_COUNT, QtHeaderToContents)
|
125
128
|
|
126
129
|
# Assemble
|
127
130
|
self.headerBox = QHBoxLayout()
|
@@ -331,15 +334,11 @@ class GuiProjectSearch(QWidget):
|
|
331
334
|
"""Populate the result tree."""
|
332
335
|
if results and nwItem:
|
333
336
|
tHandle = nwItem.itemHandle
|
334
|
-
docIcon = SHARED.theme.getItemIcon(
|
335
|
-
nwItem.itemType, nwItem.itemClass,
|
336
|
-
nwItem.itemLayout, nwItem.mainHeading
|
337
|
-
)
|
338
337
|
ext = "+" if capped else ""
|
339
338
|
|
340
339
|
tItem = QTreeWidgetItem()
|
341
340
|
tItem.setText(self.C_NAME, nwItem.itemName)
|
342
|
-
tItem.setIcon(self.C_NAME,
|
341
|
+
tItem.setIcon(self.C_NAME, nwItem.getMainIcon())
|
343
342
|
tItem.setData(self.C_NAME, self.D_HANDLE, tHandle)
|
344
343
|
tItem.setText(self.C_COUNT, f"({len(results):n}{ext})")
|
345
344
|
tItem.setTextAlignment(self.C_COUNT, QtAlignRight)
|
novelwriter/gui/sidebar.py
CHANGED
@@ -32,6 +32,7 @@ from PyQt5.QtGui import QPalette
|
|
32
32
|
from PyQt5.QtWidgets import QMenu, QVBoxLayout, QWidget
|
33
33
|
|
34
34
|
from novelwriter import CONFIG, SHARED
|
35
|
+
from novelwriter.common import qtLambda
|
35
36
|
from novelwriter.enum import nwView
|
36
37
|
from novelwriter.extensions.eventfilters import StatusTipFilter
|
37
38
|
from novelwriter.extensions.modified import NIconToolButton
|
@@ -54,7 +55,7 @@ class GuiSideBar(QWidget):
|
|
54
55
|
|
55
56
|
self.mainGui = mainGui
|
56
57
|
|
57
|
-
iPx = int(1.
|
58
|
+
iPx = int(1.25*SHARED.theme.baseButtonHeight)
|
58
59
|
iSz = QSize(iPx, iPx)
|
59
60
|
|
60
61
|
self.setContentsMargins(0, 0, 0, 0)
|
@@ -63,19 +64,19 @@ class GuiSideBar(QWidget):
|
|
63
64
|
# Buttons
|
64
65
|
self.tbProject = NIconToolButton(self, iSz)
|
65
66
|
self.tbProject.setToolTip("{0} [Ctrl+T]".format(self.tr("Project Tree View")))
|
66
|
-
self.tbProject.clicked.connect(
|
67
|
+
self.tbProject.clicked.connect(qtLambda(self.requestViewChange.emit, nwView.PROJECT))
|
67
68
|
|
68
69
|
self.tbNovel = NIconToolButton(self, iSz)
|
69
70
|
self.tbNovel.setToolTip("{0} [Ctrl+T]".format(self.tr("Novel Tree View")))
|
70
|
-
self.tbNovel.clicked.connect(
|
71
|
+
self.tbNovel.clicked.connect(qtLambda(self.requestViewChange.emit, nwView.NOVEL))
|
71
72
|
|
72
73
|
self.tbSearch = NIconToolButton(self, iSz)
|
73
74
|
self.tbSearch.setToolTip("{0} [Ctrl+Shift+F]".format(self.tr("Project Search")))
|
74
|
-
self.tbSearch.clicked.connect(
|
75
|
+
self.tbSearch.clicked.connect(qtLambda(self.requestViewChange.emit, nwView.SEARCH))
|
75
76
|
|
76
77
|
self.tbOutline = NIconToolButton(self, iSz)
|
77
78
|
self.tbOutline.setToolTip("{0} [Ctrl+Shift+T]".format(self.tr("Novel Outline View")))
|
78
|
-
self.tbOutline.clicked.connect(
|
79
|
+
self.tbOutline.clicked.connect(qtLambda(self.requestViewChange.emit, nwView.OUTLINE))
|
79
80
|
|
80
81
|
self.tbBuild = NIconToolButton(self, iSz)
|
81
82
|
self.tbBuild.setToolTip("{0} [F5]".format(self.tr("Build Manuscript")))
|
@@ -113,7 +114,7 @@ class GuiSideBar(QWidget):
|
|
113
114
|
self.outerBox.addWidget(self.tbStats)
|
114
115
|
self.outerBox.addWidget(self.tbSettings)
|
115
116
|
self.outerBox.setContentsMargins(0, 0, 0, 0)
|
116
|
-
self.outerBox.setSpacing(CONFIG.pxInt(
|
117
|
+
self.outerBox.setSpacing(CONFIG.pxInt(6))
|
117
118
|
|
118
119
|
self.setLayout(self.outerBox)
|
119
120
|
self.updateTheme()
|
novelwriter/gui/theme.py
CHANGED
@@ -151,6 +151,9 @@ class GuiTheme:
|
|
151
151
|
self.guiFont = QApplication.font()
|
152
152
|
self.guiFontB = QApplication.font()
|
153
153
|
self.guiFontB.setBold(True)
|
154
|
+
self.guiFontBU = QApplication.font()
|
155
|
+
self.guiFontBU.setBold(True)
|
156
|
+
self.guiFontBU.setUnderline(True)
|
154
157
|
self.guiFontSmall = QApplication.font()
|
155
158
|
self.guiFontSmall.setPointSizeF(0.9*self.guiFont.pointSizeF())
|
156
159
|
|
@@ -500,13 +503,15 @@ class GuiIcons:
|
|
500
503
|
|
501
504
|
# Format Icons
|
502
505
|
"fmt_bold", "fmt_bold-md", "fmt_italic", "fmt_italic-md", "fmt_mark", "fmt_strike",
|
503
|
-
"fmt_strike-md", "fmt_subscript", "fmt_superscript", "fmt_underline",
|
506
|
+
"fmt_strike-md", "fmt_subscript", "fmt_superscript", "fmt_underline", "margin_bottom",
|
507
|
+
"margin_left", "margin_right", "margin_top", "size_height", "size_width",
|
504
508
|
|
505
509
|
# General Button Icons
|
506
|
-
"add", "add_document", "backward", "bookmark", "browse", "checked", "close", "
|
507
|
-
"document", "down", "edit", "export", "font", "forward", "import", "list",
|
508
|
-
"menu", "minimise", "more", "noncheckable", "open", "panel", "quote",
|
509
|
-
"
|
510
|
+
"add", "add_document", "backward", "bookmark", "browse", "checked", "close", "copy",
|
511
|
+
"cross", "document", "down", "edit", "export", "font", "forward", "import", "list",
|
512
|
+
"maximise", "menu", "minimise", "more", "noncheckable", "open", "panel", "quote",
|
513
|
+
"refresh", "remove", "revert", "search_replace", "search", "settings", "star", "toolbar",
|
514
|
+
"unchecked", "up", "view",
|
510
515
|
|
511
516
|
# Switches
|
512
517
|
"sticky-on", "sticky-off",
|
novelwriter/guimain.py
CHANGED
@@ -62,6 +62,7 @@ from novelwriter.tools.manuscript import GuiManuscript
|
|
62
62
|
from novelwriter.tools.noveldetails import GuiNovelDetails
|
63
63
|
from novelwriter.tools.welcome import GuiWelcome
|
64
64
|
from novelwriter.tools.writingstats import GuiWritingStats
|
65
|
+
from novelwriter.types import QtModShift
|
65
66
|
|
66
67
|
logger = logging.getLogger(__name__)
|
67
68
|
|
@@ -212,15 +213,19 @@ class GuiMain(QMainWindow):
|
|
212
213
|
SHARED.indexChangedTags.connect(self.docEditor.updateChangedTags)
|
213
214
|
SHARED.indexChangedTags.connect(self.docViewerPanel.updateChangedTags)
|
214
215
|
SHARED.indexCleared.connect(self.docViewerPanel.indexWasCleared)
|
215
|
-
SHARED.indexScannedText.connect(self.docViewerPanel.projectItemChanged)
|
216
|
-
SHARED.indexScannedText.connect(self.itemDetails.updateViewBox)
|
217
|
-
SHARED.indexScannedText.connect(self.projView.updateItemValues)
|
218
216
|
SHARED.mainClockTick.connect(self._timeTick)
|
217
|
+
SHARED.projectItemChanged.connect(self.docEditor.onProjectItemChanged)
|
218
|
+
SHARED.projectItemChanged.connect(self.docViewer.onProjectItemChanged)
|
219
|
+
SHARED.projectItemChanged.connect(self.docViewerPanel.onProjectItemChanged)
|
220
|
+
SHARED.projectItemChanged.connect(self.itemDetails.onProjectItemChanged)
|
221
|
+
SHARED.projectItemChanged.connect(self.projView.onProjectItemChanged)
|
219
222
|
SHARED.projectStatusChanged.connect(self.mainStatus.updateProjectStatus)
|
220
223
|
SHARED.projectStatusMessage.connect(self.mainStatus.setStatusMessage)
|
224
|
+
SHARED.rootFolderChanged.connect(self.novelView.updateRootItem)
|
225
|
+
SHARED.rootFolderChanged.connect(self.outlineView.updateRootItem)
|
226
|
+
SHARED.rootFolderChanged.connect(self.projView.updateRootItem)
|
221
227
|
SHARED.spellLanguageChanged.connect(self.mainStatus.setLanguage)
|
222
228
|
SHARED.statusLabelsChanged.connect(self.docViewerPanel.updateStatusLabels)
|
223
|
-
SHARED.statusLabelsChanged.connect(self.projView.refreshUserLabels)
|
224
229
|
|
225
230
|
self.mainMenu.requestDocAction.connect(self._passDocumentAction)
|
226
231
|
self.mainMenu.requestDocInsert.connect(self._passDocumentInsert)
|
@@ -233,15 +238,7 @@ class GuiMain(QMainWindow):
|
|
233
238
|
|
234
239
|
self.projView.openDocumentRequest.connect(self._openDocument)
|
235
240
|
self.projView.projectSettingsRequest.connect(self.showProjectSettingsDialog)
|
236
|
-
self.projView.rootFolderChanged.connect(self.novelView.updateRootItem)
|
237
|
-
self.projView.rootFolderChanged.connect(self.outlineView.updateRootItem)
|
238
|
-
self.projView.rootFolderChanged.connect(self.projView.updateRootItem)
|
239
241
|
self.projView.selectedItemChanged.connect(self.itemDetails.updateViewBox)
|
240
|
-
self.projView.treeItemChanged.connect(self.docEditor.updateDocInfo)
|
241
|
-
self.projView.treeItemChanged.connect(self.docViewer.updateDocInfo)
|
242
|
-
self.projView.treeItemChanged.connect(self.docViewerPanel.projectItemChanged)
|
243
|
-
self.projView.treeItemChanged.connect(self.itemDetails.updateViewBox)
|
244
|
-
self.projView.wordCountsChanged.connect(self._updateStatusWordCount)
|
245
242
|
|
246
243
|
self.novelView.openDocumentRequest.connect(self._openDocument)
|
247
244
|
self.novelView.selectedItemChanged.connect(self.itemDetails.updateViewBox)
|
@@ -249,25 +246,27 @@ class GuiMain(QMainWindow):
|
|
249
246
|
self.projSearch.openDocumentSelectRequest.connect(self._openDocumentSelection)
|
250
247
|
self.projSearch.selectedItemChanged.connect(self.itemDetails.updateViewBox)
|
251
248
|
|
252
|
-
self.docEditor.
|
253
|
-
self.docEditor.docCountsChanged.connect(self.itemDetails.updateCounts)
|
254
|
-
self.docEditor.docCountsChanged.connect(self.projView.updateCounts)
|
249
|
+
self.docEditor.closeEditorRequest.connect(self.closeDocEditor)
|
255
250
|
self.docEditor.docTextChanged.connect(self.projSearch.textChanged)
|
256
251
|
self.docEditor.editedStatusChanged.connect(self.mainStatus.updateDocumentStatus)
|
252
|
+
self.docEditor.itemHandleChanged.connect(self.novelView.setActiveHandle)
|
253
|
+
self.docEditor.itemHandleChanged.connect(self.projView.setActiveHandle)
|
257
254
|
self.docEditor.loadDocumentTagRequest.connect(self._followTag)
|
258
255
|
self.docEditor.novelItemMetaChanged.connect(self.novelView.updateNovelItemMeta)
|
259
256
|
self.docEditor.novelStructureChanged.connect(self.novelView.refreshTree)
|
260
|
-
self.docEditor.
|
257
|
+
self.docEditor.openDocumentRequest.connect(self._openDocument)
|
258
|
+
self.docEditor.requestNewNoteCreation.connect(SHARED.createNewNote)
|
261
259
|
self.docEditor.requestNextDocument.connect(self.openNextDocument)
|
262
260
|
self.docEditor.requestProjectItemRenamed.connect(self.projView.renameTreeItem)
|
263
261
|
self.docEditor.requestProjectItemSelected.connect(self.projView.setSelectedHandle)
|
264
262
|
self.docEditor.spellCheckStateChanged.connect(self.mainMenu.setSpellCheckState)
|
265
|
-
self.docEditor.statusMessage.connect(self.mainStatus.setStatusMessage)
|
266
263
|
self.docEditor.toggleFocusModeRequest.connect(self.toggleFocusMode)
|
264
|
+
self.docEditor.updateStatusMessage.connect(self.mainStatus.setStatusMessage)
|
267
265
|
|
268
266
|
self.docViewer.closeDocumentRequest.connect(self.closeDocViewer)
|
269
267
|
self.docViewer.documentLoaded.connect(self.docViewerPanel.updateHandle)
|
270
268
|
self.docViewer.loadDocumentTagRequest.connect(self._followTag)
|
269
|
+
self.docViewer.openDocumentRequest.connect(self._openDocument)
|
271
270
|
self.docViewer.reloadDocumentRequest.connect(self._reloadViewer)
|
272
271
|
self.docViewer.requestProjectItemSelected.connect(self.projView.setSelectedHandle)
|
273
272
|
self.docViewer.togglePanelVisibility.connect(self._toggleViewerPanelVisibility)
|
@@ -289,21 +288,30 @@ class GuiMain(QMainWindow):
|
|
289
288
|
self.asDocTimer = QTimer(self)
|
290
289
|
self.asDocTimer.timeout.connect(self._autoSaveDocument)
|
291
290
|
|
292
|
-
# Shortcuts
|
293
|
-
self._connectMenuActions()
|
294
|
-
|
291
|
+
# Shortcuts
|
295
292
|
self.keyReturn = QShortcut(self)
|
296
|
-
self.keyReturn.setKey(
|
293
|
+
self.keyReturn.setKey("Return")
|
297
294
|
self.keyReturn.activated.connect(self._keyPressReturn)
|
298
295
|
|
296
|
+
self.keyShiftReturn = QShortcut(self)
|
297
|
+
self.keyShiftReturn.setKey("Shift+Return")
|
298
|
+
self.keyShiftReturn.activated.connect(self._keyPressReturn)
|
299
|
+
|
299
300
|
self.keyEnter = QShortcut(self)
|
300
|
-
self.keyEnter.setKey(
|
301
|
+
self.keyEnter.setKey("Enter")
|
301
302
|
self.keyEnter.activated.connect(self._keyPressReturn)
|
302
303
|
|
304
|
+
self.keyShiftEnter = QShortcut(self)
|
305
|
+
self.keyShiftEnter.setKey("Shift+Enter")
|
306
|
+
self.keyShiftEnter.activated.connect(self._keyPressReturn)
|
307
|
+
|
303
308
|
self.keyEscape = QShortcut(self)
|
304
|
-
self.keyEscape.setKey(
|
309
|
+
self.keyEscape.setKey("Esc")
|
305
310
|
self.keyEscape.activated.connect(self._keyPressEscape)
|
306
311
|
|
312
|
+
# Internal Variables
|
313
|
+
self._lastTotalCount = 0
|
314
|
+
|
307
315
|
# Initialise Main GUI
|
308
316
|
self.initMain()
|
309
317
|
self.asProjTimer.start()
|
@@ -481,8 +489,7 @@ class GuiMain(QMainWindow):
|
|
481
489
|
QApplication.processEvents()
|
482
490
|
self.openDocument(lastEdited, doScroll=True)
|
483
491
|
|
484
|
-
lastViewed
|
485
|
-
if lastViewed is not None:
|
492
|
+
if lastViewed := SHARED.project.data.getLastHandle("viewer"):
|
486
493
|
QApplication.processEvents()
|
487
494
|
self.viewDocument(lastViewed)
|
488
495
|
|
@@ -502,17 +509,15 @@ class GuiMain(QMainWindow):
|
|
502
509
|
|
503
510
|
def saveProject(self, autoSave: bool = False) -> bool:
|
504
511
|
"""Save the current project."""
|
505
|
-
if
|
506
|
-
|
507
|
-
|
508
|
-
self.projView.saveProjectTasks()
|
509
|
-
return SHARED.saveProject(autoSave=autoSave)
|
512
|
+
if SHARED.hasProject:
|
513
|
+
return SHARED.saveProject(autoSave=autoSave)
|
514
|
+
return False
|
510
515
|
|
511
516
|
##
|
512
517
|
# Document Actions
|
513
518
|
##
|
514
519
|
|
515
|
-
def closeDocument(self
|
520
|
+
def closeDocument(self) -> None:
|
516
521
|
"""Close the document and clear the editor and title field."""
|
517
522
|
if SHARED.hasProject:
|
518
523
|
# Disable focus mode if it is active
|
@@ -520,8 +525,6 @@ class GuiMain(QMainWindow):
|
|
520
525
|
SHARED.setFocusMode(False)
|
521
526
|
self.saveDocument()
|
522
527
|
self.docEditor.clearEditor()
|
523
|
-
if not beforeOpen:
|
524
|
-
self.novelView.setActiveHandle(None)
|
525
528
|
return
|
526
529
|
|
527
530
|
def openDocument(
|
@@ -533,12 +536,8 @@ class GuiMain(QMainWindow):
|
|
533
536
|
doScroll: bool = False
|
534
537
|
) -> bool:
|
535
538
|
"""Open a specific document, optionally at a given line."""
|
536
|
-
if not SHARED.hasProject:
|
537
|
-
logger.error("
|
538
|
-
return False
|
539
|
-
|
540
|
-
if not tHandle or not SHARED.project.tree.checkType(tHandle, nwItemType.FILE):
|
541
|
-
logger.debug("Requested item '%s' is not a document", tHandle)
|
539
|
+
if not (SHARED.hasProject and tHandle):
|
540
|
+
logger.error("Nothing to open open")
|
542
541
|
return False
|
543
542
|
|
544
543
|
if sTitle and tLine is None:
|
@@ -548,19 +547,15 @@ class GuiMain(QMainWindow):
|
|
548
547
|
self._changeView(nwView.EDITOR)
|
549
548
|
if tHandle == self.docEditor.docHandle:
|
550
549
|
self.docEditor.setCursorLine(tLine)
|
551
|
-
if changeFocus:
|
552
|
-
self.docEditor.setFocus()
|
553
|
-
return True
|
554
|
-
|
555
|
-
self.closeDocument(beforeOpen=True)
|
556
|
-
if self.docEditor.loadText(tHandle, tLine):
|
557
|
-
SHARED.project.data.setLastHandle(tHandle, "editor")
|
558
|
-
self.projView.setSelectedHandle(tHandle, doScroll=doScroll)
|
559
|
-
self.novelView.setActiveHandle(tHandle, doScroll=doScroll)
|
560
|
-
if changeFocus:
|
561
|
-
self.docEditor.setFocus()
|
562
550
|
else:
|
563
|
-
|
551
|
+
self.closeDocument()
|
552
|
+
if self.docEditor.loadText(tHandle, tLine):
|
553
|
+
self.projView.setSelectedHandle(tHandle, doScroll=doScroll)
|
554
|
+
else:
|
555
|
+
return False
|
556
|
+
|
557
|
+
if changeFocus:
|
558
|
+
self.docEditor.setFocus()
|
564
559
|
|
565
560
|
return True
|
566
561
|
|
@@ -728,8 +723,11 @@ class GuiMain(QMainWindow):
|
|
728
723
|
logger.warning("No item selected")
|
729
724
|
return
|
730
725
|
|
731
|
-
if tHandle:
|
732
|
-
|
726
|
+
if tHandle and SHARED.project.tree.checkType(tHandle, nwItemType.FILE):
|
727
|
+
if QApplication.keyboardModifiers() == QtModShift:
|
728
|
+
self.viewDocument(tHandle)
|
729
|
+
else:
|
730
|
+
self.openDocument(tHandle, sTitle=sTitle, changeFocus=False, doScroll=False)
|
733
731
|
|
734
732
|
return
|
735
733
|
|
@@ -740,9 +738,8 @@ class GuiMain(QMainWindow):
|
|
740
738
|
QApplication.setOverrideCursor(QCursor(Qt.CursorShape.WaitCursor))
|
741
739
|
tStart = time()
|
742
740
|
|
743
|
-
|
744
|
-
SHARED.project.
|
745
|
-
self.projView.populateTree()
|
741
|
+
SHARED.project.index.rebuild()
|
742
|
+
SHARED.project.tree.refreshAllItems()
|
746
743
|
self.novelView.refreshTree()
|
747
744
|
|
748
745
|
tEnd = time()
|
@@ -855,13 +852,11 @@ class GuiMain(QMainWindow):
|
|
855
852
|
|
856
853
|
def closeMain(self) -> bool:
|
857
854
|
"""Save everything, and close novelWriter."""
|
858
|
-
if SHARED.hasProject
|
859
|
-
|
860
|
-
|
861
|
-
|
862
|
-
|
863
|
-
if not msgYes:
|
864
|
-
return False
|
855
|
+
if SHARED.hasProject and not SHARED.question("%s<br>%s" % (
|
856
|
+
self.tr("Do you want to exit novelWriter?"),
|
857
|
+
self.tr("Changes are saved automatically.")
|
858
|
+
)):
|
859
|
+
return False
|
865
860
|
|
866
861
|
logger.info("Exiting novelWriter")
|
867
862
|
|
@@ -906,11 +901,6 @@ class GuiMain(QMainWindow):
|
|
906
901
|
|
907
902
|
return not self.splitView.isVisible()
|
908
903
|
|
909
|
-
def toggleFullScreenMode(self) -> None:
|
910
|
-
"""Toggle full screen mode"""
|
911
|
-
self.setWindowState(self.windowState() ^ Qt.WindowState.WindowFullScreen)
|
912
|
-
return
|
913
|
-
|
914
904
|
##
|
915
905
|
# Events
|
916
906
|
##
|
@@ -926,6 +916,12 @@ class GuiMain(QMainWindow):
|
|
926
916
|
# Public Slots
|
927
917
|
##
|
928
918
|
|
919
|
+
@pyqtSlot()
|
920
|
+
def toggleFullScreenMode(self) -> None:
|
921
|
+
"""Toggle full screen mode"""
|
922
|
+
self.setWindowState(self.windowState() ^ Qt.WindowState.WindowFullScreen)
|
923
|
+
return
|
924
|
+
|
929
925
|
@pyqtSlot()
|
930
926
|
def closeDocEditor(self) -> None:
|
931
927
|
"""Close the document editor. This does not hide the editor."""
|
@@ -1055,13 +1051,8 @@ class GuiMain(QMainWindow):
|
|
1055
1051
|
self.initMain()
|
1056
1052
|
self.saveDocument()
|
1057
1053
|
|
1058
|
-
if restart:
|
1059
|
-
SHARED.info(self.tr(
|
1060
|
-
"Some changes will not be applied until novelWriter has been restarted."
|
1061
|
-
))
|
1062
|
-
|
1063
1054
|
if tree:
|
1064
|
-
|
1055
|
+
SHARED.project.tree.refreshAllItems()
|
1065
1056
|
|
1066
1057
|
if theme:
|
1067
1058
|
# We are doing this manually instead of connecting to
|
@@ -1087,8 +1078,16 @@ class GuiMain(QMainWindow):
|
|
1087
1078
|
self.projView.initSettings()
|
1088
1079
|
self.novelView.initSettings()
|
1089
1080
|
self.outlineView.initSettings()
|
1081
|
+
|
1082
|
+
# Force update of word count
|
1083
|
+
self._lastTotalCount = 0
|
1090
1084
|
self._updateStatusWordCount()
|
1091
1085
|
|
1086
|
+
if restart:
|
1087
|
+
SHARED.info(self.tr(
|
1088
|
+
"Some changes will not be applied until novelWriter has been restarted."
|
1089
|
+
))
|
1090
|
+
|
1092
1091
|
return
|
1093
1092
|
|
1094
1093
|
@pyqtSlot()
|
@@ -1111,8 +1110,16 @@ class GuiMain(QMainWindow):
|
|
1111
1110
|
@pyqtSlot(str, nwDocMode)
|
1112
1111
|
def _followTag(self, tag: str, mode: nwDocMode) -> None:
|
1113
1112
|
"""Follow a tag after user interaction with a link."""
|
1114
|
-
tHandle, sTitle =
|
1115
|
-
if tHandle is
|
1113
|
+
tHandle, sTitle = SHARED.project.index.getTagSource(tag)
|
1114
|
+
if tHandle is None:
|
1115
|
+
SHARED.error(self.tr(
|
1116
|
+
"Could not find the reference for tag '{0}'. It either doesn't "
|
1117
|
+
"exist, or the index is out of date. The index can be updated "
|
1118
|
+
"from the Tools menu, or by pressing {1}."
|
1119
|
+
).format(
|
1120
|
+
tag, "F9"
|
1121
|
+
))
|
1122
|
+
else:
|
1116
1123
|
if mode == nwDocMode.EDIT:
|
1117
1124
|
self.openDocument(tHandle, sTitle=sTitle)
|
1118
1125
|
elif mode == nwDocMode.VIEW:
|
@@ -1216,8 +1223,10 @@ class GuiMain(QMainWindow):
|
|
1216
1223
|
self.mainStatus.setUserIdle(editIdle or userIdle)
|
1217
1224
|
SHARED.updateIdleTime(currTime, editIdle or userIdle)
|
1218
1225
|
self.mainStatus.updateTime(idleTime=SHARED.projectIdleTime)
|
1219
|
-
if
|
1220
|
-
self.
|
1226
|
+
if int(currTime) % 5 == 0:
|
1227
|
+
self._updateStatusWordCount()
|
1228
|
+
if CONFIG.memInfo: # pragma: no cover
|
1229
|
+
self.mainStatus.memInfo()
|
1221
1230
|
return
|
1222
1231
|
|
1223
1232
|
@pyqtSlot()
|
@@ -1245,15 +1254,19 @@ class GuiMain(QMainWindow):
|
|
1245
1254
|
if not SHARED.hasProject:
|
1246
1255
|
self.mainStatus.setProjectStats(0, 0)
|
1247
1256
|
|
1248
|
-
SHARED.project.
|
1249
|
-
if
|
1250
|
-
|
1251
|
-
|
1252
|
-
|
1253
|
-
|
1254
|
-
|
1255
|
-
|
1256
|
-
|
1257
|
+
currentTotalCount = SHARED.project.currentTotalCount
|
1258
|
+
if self._lastTotalCount != currentTotalCount:
|
1259
|
+
self._lastTotalCount = currentTotalCount
|
1260
|
+
|
1261
|
+
SHARED.project.updateWordCounts()
|
1262
|
+
if CONFIG.incNotesWCount:
|
1263
|
+
iTotal = sum(SHARED.project.data.initCounts)
|
1264
|
+
cTotal = sum(SHARED.project.data.currCounts)
|
1265
|
+
self.mainStatus.setProjectStats(cTotal, cTotal - iTotal)
|
1266
|
+
else:
|
1267
|
+
iNovel, _ = SHARED.project.data.initCounts
|
1268
|
+
cNovel, _ = SHARED.project.data.currCounts
|
1269
|
+
self.mainStatus.setProjectStats(cNovel, cNovel - iNovel)
|
1257
1270
|
|
1258
1271
|
return
|
1259
1272
|
|
@@ -1299,116 +1312,7 @@ class GuiMain(QMainWindow):
|
|
1299
1312
|
# Internal Functions
|
1300
1313
|
##
|
1301
1314
|
|
1302
|
-
def _connectMenuActions(self) -> None:
|
1303
|
-
"""Connect to the main window all menu actions that need to be
|
1304
|
-
available also when the main menu is hidden.
|
1305
|
-
"""
|
1306
|
-
# Project
|
1307
|
-
self.addAction(self.mainMenu.aSaveProject)
|
1308
|
-
self.addAction(self.mainMenu.aEditItem)
|
1309
|
-
self.addAction(self.mainMenu.aExitNW)
|
1310
|
-
|
1311
|
-
# Document
|
1312
|
-
self.addAction(self.mainMenu.aSaveDoc)
|
1313
|
-
self.addAction(self.mainMenu.aCloseDoc)
|
1314
|
-
|
1315
|
-
# Edit
|
1316
|
-
self.addAction(self.mainMenu.aEditUndo)
|
1317
|
-
self.addAction(self.mainMenu.aEditRedo)
|
1318
|
-
self.addAction(self.mainMenu.aEditCut)
|
1319
|
-
self.addAction(self.mainMenu.aEditCopy)
|
1320
|
-
self.addAction(self.mainMenu.aEditPaste)
|
1321
|
-
self.addAction(self.mainMenu.aSelectAll)
|
1322
|
-
self.addAction(self.mainMenu.aSelectPar)
|
1323
|
-
|
1324
|
-
# View
|
1325
|
-
self.addAction(self.mainMenu.aFocusMode)
|
1326
|
-
self.addAction(self.mainMenu.aFullScreen)
|
1327
|
-
|
1328
|
-
# Insert
|
1329
|
-
self.addAction(self.mainMenu.aInsENDash)
|
1330
|
-
self.addAction(self.mainMenu.aInsEMDash)
|
1331
|
-
self.addAction(self.mainMenu.aInsHorBar)
|
1332
|
-
self.addAction(self.mainMenu.aInsFigDash)
|
1333
|
-
self.addAction(self.mainMenu.aInsQuoteLS)
|
1334
|
-
self.addAction(self.mainMenu.aInsQuoteRS)
|
1335
|
-
self.addAction(self.mainMenu.aInsQuoteLD)
|
1336
|
-
self.addAction(self.mainMenu.aInsQuoteRD)
|
1337
|
-
self.addAction(self.mainMenu.aInsMSApos)
|
1338
|
-
self.addAction(self.mainMenu.aInsEllipsis)
|
1339
|
-
self.addAction(self.mainMenu.aInsPrime)
|
1340
|
-
self.addAction(self.mainMenu.aInsDPrime)
|
1341
|
-
self.addAction(self.mainMenu.aInsNBSpace)
|
1342
|
-
self.addAction(self.mainMenu.aInsThinSpace)
|
1343
|
-
self.addAction(self.mainMenu.aInsThinNBSpace)
|
1344
|
-
self.addAction(self.mainMenu.aInsBullet)
|
1345
|
-
self.addAction(self.mainMenu.aInsHyBull)
|
1346
|
-
self.addAction(self.mainMenu.aInsFlower)
|
1347
|
-
self.addAction(self.mainMenu.aInsPerMille)
|
1348
|
-
self.addAction(self.mainMenu.aInsDegree)
|
1349
|
-
self.addAction(self.mainMenu.aInsMinus)
|
1350
|
-
self.addAction(self.mainMenu.aInsTimes)
|
1351
|
-
self.addAction(self.mainMenu.aInsDivide)
|
1352
|
-
self.addAction(self.mainMenu.aInsSynopsis)
|
1353
|
-
self.addAction(self.mainMenu.aInsShort)
|
1354
|
-
|
1355
|
-
for mAction, _ in self.mainMenu.mInsKWItems.values():
|
1356
|
-
self.addAction(mAction)
|
1357
|
-
|
1358
|
-
# Search
|
1359
|
-
self.addAction(self.mainMenu.aFind)
|
1360
|
-
self.addAction(self.mainMenu.aReplace)
|
1361
|
-
self.addAction(self.mainMenu.aFindNext)
|
1362
|
-
self.addAction(self.mainMenu.aFindPrev)
|
1363
|
-
self.addAction(self.mainMenu.aReplaceNext)
|
1364
|
-
|
1365
|
-
# Format
|
1366
|
-
self.addAction(self.mainMenu.aFmtItalic)
|
1367
|
-
self.addAction(self.mainMenu.aFmtBold)
|
1368
|
-
self.addAction(self.mainMenu.aFmtStrike)
|
1369
|
-
self.addAction(self.mainMenu.aFmtDQuote)
|
1370
|
-
self.addAction(self.mainMenu.aFmtSQuote)
|
1371
|
-
self.addAction(self.mainMenu.aFmtHead1)
|
1372
|
-
self.addAction(self.mainMenu.aFmtHead2)
|
1373
|
-
self.addAction(self.mainMenu.aFmtHead3)
|
1374
|
-
self.addAction(self.mainMenu.aFmtHead4)
|
1375
|
-
self.addAction(self.mainMenu.aFmtAlignLeft)
|
1376
|
-
self.addAction(self.mainMenu.aFmtAlignCentre)
|
1377
|
-
self.addAction(self.mainMenu.aFmtAlignRight)
|
1378
|
-
self.addAction(self.mainMenu.aFmtIndentLeft)
|
1379
|
-
self.addAction(self.mainMenu.aFmtIndentRight)
|
1380
|
-
self.addAction(self.mainMenu.aFmtComment)
|
1381
|
-
self.addAction(self.mainMenu.aFmtNoFormat)
|
1382
|
-
|
1383
|
-
# Tools
|
1384
|
-
self.addAction(self.mainMenu.aSpellCheck)
|
1385
|
-
self.addAction(self.mainMenu.aReRunSpell)
|
1386
|
-
self.addAction(self.mainMenu.aPreferences)
|
1387
|
-
|
1388
|
-
# Help
|
1389
|
-
self.addAction(self.mainMenu.aHelpDocs)
|
1390
|
-
if isinstance(CONFIG.pdfDocs, Path):
|
1391
|
-
self.addAction(self.mainMenu.aPdfDocs)
|
1392
|
-
|
1393
|
-
return
|
1394
|
-
|
1395
1315
|
def _updateWindowTitle(self, projName: str | None = None) -> None:
|
1396
1316
|
"""Set the window title and add the project's name."""
|
1397
1317
|
self.setWindowTitle(" - ".join(filter(None, [projName, CONFIG.appName])))
|
1398
1318
|
return
|
1399
|
-
|
1400
|
-
def _getTagSource(self, tag: str) -> tuple[str | None, str | None]:
|
1401
|
-
"""Handle the index lookup of a tag and display an alert if the
|
1402
|
-
tag cannot be found.
|
1403
|
-
"""
|
1404
|
-
tHandle, sTitle = SHARED.project.index.getTagSource(tag)
|
1405
|
-
if tHandle is None:
|
1406
|
-
SHARED.error(self.tr(
|
1407
|
-
"Could not find the reference for tag '{0}'. It either doesn't "
|
1408
|
-
"exist, or the index is out of date. The index can be updated "
|
1409
|
-
"from the Tools menu, or by pressing {1}."
|
1410
|
-
).format(
|
1411
|
-
tag, "F9"
|
1412
|
-
))
|
1413
|
-
return None, None
|
1414
|
-
return tHandle, sTitle
|