novelWriter 2.4.2__py3-none-any.whl → 2.5b1__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.4.2.dist-info → novelWriter-2.5b1.dist-info}/METADATA +4 -5
- {novelWriter-2.4.2.dist-info → novelWriter-2.5b1.dist-info}/RECORD +109 -101
- novelwriter/__init__.py +33 -39
- novelwriter/assets/i18n/project_en_GB.json +1 -0
- novelwriter/assets/icons/typicons_dark/icons.conf +2 -0
- novelwriter/assets/icons/typicons_dark/nw_font.svg +4 -0
- novelwriter/assets/icons/typicons_dark/nw_quote.svg +4 -0
- novelwriter/assets/icons/typicons_light/icons.conf +2 -0
- novelwriter/assets/icons/typicons_light/nw_font.svg +4 -0
- novelwriter/assets/icons/typicons_light/nw_quote.svg +4 -0
- novelwriter/assets/manual.pdf +0 -0
- novelwriter/assets/sample.zip +0 -0
- novelwriter/assets/syntax/cyberpunk_night.conf +5 -3
- novelwriter/assets/syntax/default_dark.conf +32 -18
- novelwriter/assets/syntax/default_light.conf +24 -10
- novelwriter/assets/syntax/dracula.conf +44 -0
- novelwriter/assets/syntax/grey_dark.conf +5 -4
- novelwriter/assets/syntax/grey_light.conf +5 -4
- novelwriter/assets/syntax/light_owl.conf +7 -6
- novelwriter/assets/syntax/night_owl.conf +7 -6
- novelwriter/assets/syntax/snazzy.conf +42 -0
- novelwriter/assets/syntax/solarized_dark.conf +4 -3
- novelwriter/assets/syntax/solarized_light.conf +4 -3
- novelwriter/assets/syntax/tango.conf +27 -11
- novelwriter/assets/syntax/tomorrow.conf +6 -5
- novelwriter/assets/syntax/tomorrow_night.conf +7 -6
- novelwriter/assets/syntax/tomorrow_night_blue.conf +6 -5
- novelwriter/assets/syntax/tomorrow_night_bright.conf +6 -5
- novelwriter/assets/syntax/tomorrow_night_eighties.conf +6 -5
- novelwriter/assets/text/credits_en.htm +4 -1
- novelwriter/assets/themes/cyberpunk_night.conf +2 -0
- novelwriter/assets/themes/default_dark.conf +1 -0
- novelwriter/assets/themes/default_light.conf +1 -0
- novelwriter/assets/themes/dracula.conf +47 -0
- novelwriter/assets/themes/solarized_dark.conf +1 -0
- novelwriter/assets/themes/solarized_light.conf +1 -0
- novelwriter/common.py +31 -9
- novelwriter/config.py +118 -84
- novelwriter/constants.py +40 -26
- novelwriter/core/buildsettings.py +63 -66
- novelwriter/core/coretools.py +2 -22
- novelwriter/core/docbuild.py +51 -40
- novelwriter/core/document.py +3 -5
- novelwriter/core/index.py +115 -45
- novelwriter/core/item.py +8 -19
- novelwriter/core/options.py +2 -4
- novelwriter/core/project.py +23 -57
- novelwriter/core/projectdata.py +1 -3
- novelwriter/core/projectxml.py +12 -15
- novelwriter/core/sessions.py +3 -5
- novelwriter/core/spellcheck.py +4 -9
- novelwriter/core/status.py +211 -164
- novelwriter/core/storage.py +0 -8
- novelwriter/core/tohtml.py +94 -100
- novelwriter/core/tokenizer.py +199 -112
- novelwriter/core/{tomd.py → tomarkdown.py} +97 -78
- novelwriter/core/toodt.py +212 -148
- novelwriter/core/toqdoc.py +403 -0
- novelwriter/core/tree.py +5 -7
- novelwriter/dialogs/about.py +3 -5
- novelwriter/dialogs/docmerge.py +1 -3
- novelwriter/dialogs/docsplit.py +1 -3
- novelwriter/dialogs/editlabel.py +0 -2
- novelwriter/dialogs/preferences.py +111 -88
- novelwriter/dialogs/projectsettings.py +216 -180
- novelwriter/dialogs/quotes.py +3 -4
- novelwriter/dialogs/wordlist.py +3 -9
- novelwriter/enum.py +31 -25
- novelwriter/error.py +8 -15
- novelwriter/extensions/circularprogress.py +5 -6
- novelwriter/extensions/configlayout.py +18 -18
- novelwriter/extensions/eventfilters.py +1 -5
- novelwriter/extensions/modified.py +50 -13
- novelwriter/extensions/novelselector.py +1 -3
- novelwriter/extensions/pagedsidebar.py +9 -12
- novelwriter/extensions/simpleprogress.py +1 -3
- novelwriter/extensions/statusled.py +1 -3
- novelwriter/extensions/switch.py +4 -6
- novelwriter/extensions/switchbox.py +7 -6
- novelwriter/extensions/versioninfo.py +3 -9
- novelwriter/gui/doceditor.py +132 -133
- novelwriter/gui/dochighlight.py +237 -183
- novelwriter/gui/docviewer.py +61 -97
- novelwriter/gui/docviewerpanel.py +3 -10
- novelwriter/gui/editordocument.py +1 -3
- novelwriter/gui/itemdetails.py +7 -11
- novelwriter/gui/mainmenu.py +11 -7
- novelwriter/gui/noveltree.py +11 -24
- novelwriter/gui/outline.py +11 -23
- novelwriter/gui/projtree.py +26 -43
- novelwriter/gui/search.py +1 -3
- novelwriter/gui/sidebar.py +2 -6
- novelwriter/gui/statusbar.py +6 -10
- novelwriter/gui/theme.py +26 -51
- novelwriter/guimain.py +50 -71
- novelwriter/shared.py +30 -15
- novelwriter/tools/dictionaries.py +12 -15
- novelwriter/tools/lipsum.py +2 -4
- novelwriter/tools/manusbuild.py +1 -3
- novelwriter/tools/manuscript.py +71 -144
- novelwriter/tools/manussettings.py +67 -73
- novelwriter/tools/noveldetails.py +6 -11
- novelwriter/tools/welcome.py +2 -16
- novelwriter/tools/writingstats.py +6 -9
- novelwriter/types.py +45 -3
- {novelWriter-2.4.2.dist-info → novelWriter-2.5b1.dist-info}/LICENSE.md +0 -0
- {novelWriter-2.4.2.dist-info → novelWriter-2.5b1.dist-info}/WHEEL +0 -0
- {novelWriter-2.4.2.dist-info → novelWriter-2.5b1.dist-info}/entry_points.txt +0 -0
- {novelWriter-2.4.2.dist-info → novelWriter-2.5b1.dist-info}/top_level.txt +0 -0
novelwriter/gui/docviewer.py
CHANGED
@@ -31,27 +31,21 @@ import logging
|
|
31
31
|
from enum import Enum
|
32
32
|
|
33
33
|
from PyQt5.QtCore import QPoint, Qt, QUrl, pyqtSignal, pyqtSlot
|
34
|
-
from PyQt5.QtGui import
|
35
|
-
QCursor, QFont, QMouseEvent, QPalette, QResizeEvent, QTextCursor,
|
36
|
-
QTextOption
|
37
|
-
)
|
34
|
+
from PyQt5.QtGui import QCursor, QMouseEvent, QPalette, QResizeEvent, QTextCursor
|
38
35
|
from PyQt5.QtWidgets import (
|
39
36
|
QAction, QApplication, QFrame, QHBoxLayout, QLabel, QMenu, QTextBrowser,
|
40
37
|
QToolButton, QWidget
|
41
38
|
)
|
42
39
|
|
43
40
|
from novelwriter import CONFIG, SHARED
|
44
|
-
from novelwriter.common import cssCol
|
45
41
|
from novelwriter.constants import nwHeaders, nwUnicode
|
46
|
-
from novelwriter.core.
|
42
|
+
from novelwriter.core.toqdoc import TextDocumentTheme, ToQTextDocument
|
47
43
|
from novelwriter.enum import nwDocAction, nwDocMode, nwItemType
|
48
44
|
from novelwriter.error import logException
|
49
45
|
from novelwriter.extensions.eventfilters import WheelEventFilter
|
50
46
|
from novelwriter.extensions.modified import NIconToolButton
|
51
47
|
from novelwriter.gui.theme import STYLES_MIN_TOOLBUTTON
|
52
|
-
from novelwriter.types import
|
53
|
-
QtAlignCenterTop, QtAlignJustify, QtKeepAnchor, QtMouseLeft, QtMoveAnchor
|
54
|
-
)
|
48
|
+
from novelwriter.types import QtAlignCenterTop, QtKeepAnchor, QtMouseLeft, QtMoveAnchor
|
55
49
|
|
56
50
|
logger = logging.getLogger(__name__)
|
57
51
|
|
@@ -72,6 +66,7 @@ class GuiDocViewer(QTextBrowser):
|
|
72
66
|
|
73
67
|
# Internal Variables
|
74
68
|
self._docHandle = None
|
69
|
+
self._docTheme = TextDocumentTheme()
|
75
70
|
|
76
71
|
# Settings
|
77
72
|
self.setMinimumWidth(CONFIG.pxInt(300))
|
@@ -140,13 +135,10 @@ class GuiDocViewer(QTextBrowser):
|
|
140
135
|
|
141
136
|
def initViewer(self) -> None:
|
142
137
|
"""Set editor settings from main config."""
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
font.setFamily(CONFIG.textFont)
|
148
|
-
font.setPointSize(CONFIG.textSize)
|
149
|
-
self.document().setDefaultFont(font)
|
138
|
+
# Set the font. See issues #1862 and #1875.
|
139
|
+
self.setFont(CONFIG.textFont)
|
140
|
+
self.docHeader.updateFont()
|
141
|
+
self.docFooter.updateFont()
|
150
142
|
|
151
143
|
# Set the widget colours to match syntax theme
|
152
144
|
mainPalette = self.palette()
|
@@ -159,16 +151,23 @@ class GuiDocViewer(QTextBrowser):
|
|
159
151
|
docPalette.setColor(QPalette.ColorRole.Base, SHARED.theme.colBack)
|
160
152
|
docPalette.setColor(QPalette.ColorRole.Text, SHARED.theme.colText)
|
161
153
|
self.viewport().setPalette(docPalette)
|
162
|
-
|
163
154
|
self.docHeader.matchColours()
|
164
155
|
self.docFooter.matchColours()
|
165
156
|
|
157
|
+
# Update theme colours
|
158
|
+
self._docTheme.text = SHARED.theme.colText
|
159
|
+
self._docTheme.highlight = SHARED.theme.colMark
|
160
|
+
self._docTheme.head = SHARED.theme.colHead
|
161
|
+
self._docTheme.comment = SHARED.theme.colHidden
|
162
|
+
self._docTheme.note = SHARED.theme.colNote
|
163
|
+
self._docTheme.code = SHARED.theme.colCode
|
164
|
+
self._docTheme.modifier = SHARED.theme.colMod
|
165
|
+
self._docTheme.keyword = SHARED.theme.colKey
|
166
|
+
self._docTheme.tag = SHARED.theme.colTag
|
167
|
+
self._docTheme.optional = SHARED.theme.colOpt
|
168
|
+
|
166
169
|
# Set default text margins
|
167
170
|
self.document().setDocumentMargin(0)
|
168
|
-
options = QTextOption()
|
169
|
-
if CONFIG.doJustify:
|
170
|
-
options.setAlignment(QtAlignJustify)
|
171
|
-
self.document().setDefaultTextOption(options)
|
172
171
|
|
173
172
|
# Scroll bars
|
174
173
|
if CONFIG.hideVScroll:
|
@@ -200,21 +199,22 @@ class GuiDocViewer(QTextBrowser):
|
|
200
199
|
QApplication.setOverrideCursor(QCursor(Qt.CursorShape.WaitCursor))
|
201
200
|
|
202
201
|
sPos = self.verticalScrollBar().value()
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
202
|
+
qDoc = ToQTextDocument(SHARED.project)
|
203
|
+
qDoc.setJustify(CONFIG.doJustify)
|
204
|
+
qDoc.initDocument(CONFIG.textFont, self._docTheme)
|
205
|
+
qDoc.setKeywords(True)
|
206
|
+
qDoc.setComments(CONFIG.viewComments)
|
207
|
+
qDoc.setSynopsis(CONFIG.viewSynopsis)
|
209
208
|
|
210
209
|
# Be extra careful here to prevent crashes when first opening a
|
211
210
|
# project as a crash here leaves no way of recovering.
|
212
211
|
# See issue #298
|
213
212
|
try:
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
213
|
+
qDoc.setText(tHandle)
|
214
|
+
qDoc.doPreProcessing()
|
215
|
+
qDoc.tokenizeText()
|
216
|
+
qDoc.doConvert()
|
217
|
+
qDoc.appendFootnotes()
|
218
218
|
except Exception:
|
219
219
|
logger.error("Failed to generate preview for document with handle '%s'", tHandle)
|
220
220
|
logException()
|
@@ -230,11 +230,7 @@ class GuiDocViewer(QTextBrowser):
|
|
230
230
|
self.docHistory.append(tHandle)
|
231
231
|
|
232
232
|
self.setDocumentTitle(tHandle)
|
233
|
-
|
234
|
-
# Replace tabs before setting the HTML, and then put them back in
|
235
|
-
self.setHtml(aDoc.result.replace("\t", "!!tab!!"))
|
236
|
-
while self.find("!!tab!!"):
|
237
|
-
self.textCursor().insertText("\t")
|
233
|
+
self.setDocument(qDoc.document)
|
238
234
|
|
239
235
|
if self._docHandle == tHandle:
|
240
236
|
# This is a refresh, so we set the scrollbar back to where it was
|
@@ -372,12 +368,10 @@ class GuiDocViewer(QTextBrowser):
|
|
372
368
|
@pyqtSlot("QUrl")
|
373
369
|
def _linkClicked(self, url: QUrl) -> None:
|
374
370
|
"""Process a clicked link in the document."""
|
375
|
-
link
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
if len(bits) == 2:
|
380
|
-
self.loadDocumentTagRequest.emit(bits[1], nwDocMode.VIEW)
|
371
|
+
if link := url.url():
|
372
|
+
logger.debug("Clicked link: '%s'", link)
|
373
|
+
if (bits := link.partition("_")) and bits[2]:
|
374
|
+
self.loadDocumentTagRequest.emit(bits[2], nwDocMode.VIEW)
|
381
375
|
return
|
382
376
|
|
383
377
|
@pyqtSlot("QPoint")
|
@@ -467,34 +461,6 @@ class GuiDocViewer(QTextBrowser):
|
|
467
461
|
self._makeSelection(selType)
|
468
462
|
return
|
469
463
|
|
470
|
-
def _makeStyleSheet(self) -> None:
|
471
|
-
"""Generate an appropriate style sheet for the document viewer,
|
472
|
-
based on the current syntax highlighter theme.
|
473
|
-
"""
|
474
|
-
colText = cssCol(SHARED.theme.colText)
|
475
|
-
colHead = cssCol(SHARED.theme.colHead)
|
476
|
-
colVals = cssCol(SHARED.theme.colVal)
|
477
|
-
colMark = cssCol(SHARED.theme.colMark)
|
478
|
-
colKeys = cssCol(SHARED.theme.colKey)
|
479
|
-
colOpts = cssCol(SHARED.theme.colOpt)
|
480
|
-
colHide = cssCol(SHARED.theme.colHidden)
|
481
|
-
colMods = cssCol(SHARED.theme.colMod)
|
482
|
-
self.document().setDefaultStyleSheet(
|
483
|
-
f"body {{color: {colText};}}\n"
|
484
|
-
f"h1, h2, h3, h4 {{color: {colHead};}}\n"
|
485
|
-
f"a {{color: {colVals};}}\n"
|
486
|
-
f"mark {{background-color: {colMark};}}\n"
|
487
|
-
f".tags {{color: {colKeys};}}\n"
|
488
|
-
f".optional {{color: {colOpts};}}\n"
|
489
|
-
f".comment {{color: {colHide};}}\n"
|
490
|
-
f".synopsis {{color: {colMods};}}\n"
|
491
|
-
".title {text-align: center;}\n"
|
492
|
-
)
|
493
|
-
|
494
|
-
return
|
495
|
-
|
496
|
-
# END Class GuiDocViewer
|
497
|
-
|
498
464
|
|
499
465
|
class GuiDocViewHistory:
|
500
466
|
|
@@ -608,15 +574,13 @@ class GuiDocViewHistory:
|
|
608
574
|
)
|
609
575
|
return
|
610
576
|
|
611
|
-
# END Class GuiDocViewHistory
|
612
|
-
|
613
|
-
|
614
|
-
# =============================================================================================== #
|
615
|
-
# The Embedded Document Header
|
616
|
-
# Only used by DocViewer, and is at a fixed position in the QTextBrowser's viewport
|
617
|
-
# =============================================================================================== #
|
618
577
|
|
619
578
|
class GuiDocViewHeader(QWidget):
|
579
|
+
"""The Embedded Document Header
|
580
|
+
|
581
|
+
Only used by DocViewer, and is at a fixed position in the
|
582
|
+
QTextBrowser's viewport.
|
583
|
+
"""
|
620
584
|
|
621
585
|
def __init__(self, docViewer: GuiDocViewer) -> None:
|
622
586
|
super().__init__(parent=docViewer)
|
@@ -646,10 +610,6 @@ class GuiDocViewHeader(QWidget):
|
|
646
610
|
self.itemTitle.setAlignment(QtAlignCenterTop)
|
647
611
|
self.itemTitle.setFixedHeight(iPx)
|
648
612
|
|
649
|
-
lblFont = self.itemTitle.font()
|
650
|
-
lblFont.setPointSizeF(0.9*SHARED.theme.fontPointSize)
|
651
|
-
self.itemTitle.setFont(lblFont)
|
652
|
-
|
653
613
|
# Other Widgets
|
654
614
|
self.outlineMenu = QMenu(self)
|
655
615
|
|
@@ -700,7 +660,7 @@ class GuiDocViewHeader(QWidget):
|
|
700
660
|
self.outerBox.setContentsMargins(mPx, mPx, mPx, mPx)
|
701
661
|
self.setMinimumHeight(iPx + 2*mPx)
|
702
662
|
|
703
|
-
|
663
|
+
self.updateFont()
|
704
664
|
self.updateTheme()
|
705
665
|
|
706
666
|
logger.debug("Ready: GuiDocViewHeader")
|
@@ -745,6 +705,12 @@ class GuiDocViewHeader(QWidget):
|
|
745
705
|
self._docOutline = data
|
746
706
|
return
|
747
707
|
|
708
|
+
def updateFont(self) -> None:
|
709
|
+
"""Update the font settings."""
|
710
|
+
self.setFont(SHARED.theme.guiFont)
|
711
|
+
self.itemTitle.setFont(SHARED.theme.guiFontSmall)
|
712
|
+
return
|
713
|
+
|
748
714
|
def updateTheme(self) -> None:
|
749
715
|
"""Update theme elements."""
|
750
716
|
self.outlineButton.setThemeIcon("list")
|
@@ -832,15 +798,13 @@ class GuiDocViewHeader(QWidget):
|
|
832
798
|
self.docViewer.requestProjectItemSelected.emit(self._docHandle, True)
|
833
799
|
return
|
834
800
|
|
835
|
-
# END Class GuiDocViewHeader
|
836
|
-
|
837
|
-
|
838
|
-
# =============================================================================================== #
|
839
|
-
# The Embedded Document Footer
|
840
|
-
# Only used by DocViewer, and is at a fixed position in the QTextBrowser's viewport
|
841
|
-
# =============================================================================================== #
|
842
801
|
|
843
802
|
class GuiDocViewFooter(QWidget):
|
803
|
+
"""The Embedded Document Footer
|
804
|
+
|
805
|
+
Only used by DocViewer, and is at a fixed position in the
|
806
|
+
QTextBrowser's viewport.
|
807
|
+
"""
|
844
808
|
|
845
809
|
def __init__(self, docViewer: GuiDocViewer) -> None:
|
846
810
|
super().__init__(parent=docViewer)
|
@@ -886,11 +850,6 @@ class GuiDocViewFooter(QWidget):
|
|
886
850
|
self.showSynopsis.toggled.connect(self._doToggleSynopsis)
|
887
851
|
self.showSynopsis.setToolTip(self.tr("Show Synopsis Comments"))
|
888
852
|
|
889
|
-
lblFont = self.font()
|
890
|
-
lblFont.setPointSizeF(0.9*SHARED.theme.fontPointSize)
|
891
|
-
self.showComments.setFont(lblFont)
|
892
|
-
self.showSynopsis.setFont(lblFont)
|
893
|
-
|
894
853
|
# Assemble Layout
|
895
854
|
self.outerBox = QHBoxLayout()
|
896
855
|
self.outerBox.addWidget(self.showHide, 0)
|
@@ -906,7 +865,7 @@ class GuiDocViewFooter(QWidget):
|
|
906
865
|
self.outerBox.setContentsMargins(mPx, mPx, mPx, mPx)
|
907
866
|
self.setMinimumHeight(iPx + 2*mPx)
|
908
867
|
|
909
|
-
|
868
|
+
self.updateFont()
|
910
869
|
self.updateTheme()
|
911
870
|
|
912
871
|
logger.debug("Ready: GuiDocViewFooter")
|
@@ -917,6 +876,13 @@ class GuiDocViewFooter(QWidget):
|
|
917
876
|
# Methods
|
918
877
|
##
|
919
878
|
|
879
|
+
def updateFont(self) -> None:
|
880
|
+
"""Update the font settings."""
|
881
|
+
self.setFont(SHARED.theme.guiFont)
|
882
|
+
self.showComments.setFont(SHARED.theme.guiFontSmall)
|
883
|
+
self.showSynopsis.setFont(SHARED.theme.guiFontSmall)
|
884
|
+
return
|
885
|
+
|
920
886
|
def updateTheme(self) -> None:
|
921
887
|
"""Update theme elements."""
|
922
888
|
# Icons
|
@@ -964,5 +930,3 @@ class GuiDocViewFooter(QWidget):
|
|
964
930
|
CONFIG.viewSynopsis = state
|
965
931
|
self.docViewer.reloadText()
|
966
932
|
return
|
967
|
-
|
968
|
-
# END Class GuiDocViewFooter
|
@@ -209,9 +209,8 @@ class GuiDocViewerPanel(QWidget):
|
|
209
209
|
|
210
210
|
def _updateTabVisibility(self) -> None:
|
211
211
|
"""Hide class tabs with no content."""
|
212
|
-
|
213
|
-
|
214
|
-
self.mainTabs.setTabVisible(self.idTabs[tClass], cTab.countEntries() > 0)
|
212
|
+
for tClass, cTab in self.kwTabs.items():
|
213
|
+
self.mainTabs.setTabVisible(self.idTabs[tClass], cTab.countEntries() > 0)
|
215
214
|
return
|
216
215
|
|
217
216
|
def _loadAllTags(self) -> None:
|
@@ -222,8 +221,6 @@ class GuiDocViewerPanel(QWidget):
|
|
222
221
|
self.kwTabs[tClass].addUpdateEntry(key, name, iItem, hItem)
|
223
222
|
return
|
224
223
|
|
225
|
-
# END Class GuiDocViewerPanel
|
226
|
-
|
227
224
|
|
228
225
|
class _ViewPanelBackRefs(QTreeWidget):
|
229
226
|
|
@@ -361,8 +358,6 @@ class _ViewPanelBackRefs(QTreeWidget):
|
|
361
358
|
|
362
359
|
return
|
363
360
|
|
364
|
-
# END Class _ViewPanelBackRefs
|
365
|
-
|
366
361
|
|
367
362
|
class _ViewPanelKeyWords(QTreeWidget):
|
368
363
|
|
@@ -450,7 +445,7 @@ class _ViewPanelKeyWords(QTreeWidget):
|
|
450
445
|
nwItem.itemType, nwItem.itemClass,
|
451
446
|
nwItem.itemLayout, nwItem.mainHeading
|
452
447
|
)
|
453
|
-
impLabel, impIcon = nwItem.getImportStatus(
|
448
|
+
impLabel, impIcon = nwItem.getImportStatus()
|
454
449
|
iLevel = nwHeaders.H_LEVEL.get(hItem.level, 0) if nwItem.isDocumentLayout() else 5
|
455
450
|
hDec = SHARED.theme.getHeaderDecorationNarrow(iLevel)
|
456
451
|
|
@@ -529,5 +524,3 @@ class _ViewPanelKeyWords(QTreeWidget):
|
|
529
524
|
if index.column() not in (self.C_EDIT, self.C_VIEW):
|
530
525
|
self._parent.loadDocumentTagRequest.emit(tag, nwDocMode.VIEW)
|
531
526
|
return
|
532
|
-
|
533
|
-
# END Class _ViewPanelKeyWords
|
@@ -28,8 +28,8 @@ import logging
|
|
28
28
|
from collections.abc import Iterable
|
29
29
|
from time import time
|
30
30
|
|
31
|
-
from PyQt5.QtGui import QTextBlock, QTextCursor, QTextDocument
|
32
31
|
from PyQt5.QtCore import QObject, pyqtSlot
|
32
|
+
from PyQt5.QtGui import QTextBlock, QTextCursor, QTextDocument
|
33
33
|
from PyQt5.QtWidgets import QApplication, QPlainTextDocumentLayout
|
34
34
|
|
35
35
|
from novelwriter import SHARED
|
@@ -133,5 +133,3 @@ class GuiTextDocument(QTextDocument):
|
|
133
133
|
"""Set the spell check state of the syntax highlighter."""
|
134
134
|
self._syntax.setSpellCheck(state)
|
135
135
|
return
|
136
|
-
|
137
|
-
# END Class GuiTextDocument
|
novelwriter/gui/itemdetails.py
CHANGED
@@ -26,12 +26,14 @@ from __future__ import annotations
|
|
26
26
|
import logging
|
27
27
|
|
28
28
|
from PyQt5.QtCore import pyqtSlot
|
29
|
-
from PyQt5.QtWidgets import
|
29
|
+
from PyQt5.QtWidgets import QGridLayout, QLabel, QWidget
|
30
30
|
|
31
31
|
from novelwriter import CONFIG, SHARED
|
32
|
-
from novelwriter.
|
32
|
+
from novelwriter.common import elide
|
33
|
+
from novelwriter.constants import nwLabels, trConst
|
33
34
|
from novelwriter.types import (
|
34
|
-
QtAlignLeft, QtAlignLeftBase, QtAlignRight, QtAlignRightBase,
|
35
|
+
QtAlignLeft, QtAlignLeftBase, QtAlignRight, QtAlignRightBase,
|
36
|
+
QtAlignRightMiddle
|
35
37
|
)
|
36
38
|
|
37
39
|
logger = logging.getLogger(__name__)
|
@@ -236,10 +238,6 @@ class GuiItemDetails(QWidget):
|
|
236
238
|
# Label
|
237
239
|
# =====
|
238
240
|
|
239
|
-
label = nwItem.itemName
|
240
|
-
if len(label) > 100:
|
241
|
-
label = label[:96].rstrip()+" ..."
|
242
|
-
|
243
241
|
if nwItem.isFileType():
|
244
242
|
if nwItem.isActive:
|
245
243
|
self.labelIcon.setPixmap(SHARED.theme.getPixmap("checked", (iPx, iPx)))
|
@@ -248,12 +246,12 @@ class GuiItemDetails(QWidget):
|
|
248
246
|
else:
|
249
247
|
self.labelIcon.setPixmap(SHARED.theme.getPixmap("noncheckable", (iPx, iPx)))
|
250
248
|
|
251
|
-
self.labelData.setText(
|
249
|
+
self.labelData.setText(elide(nwItem.itemName, 100))
|
252
250
|
|
253
251
|
# Status
|
254
252
|
# ======
|
255
253
|
|
256
|
-
status, icon = nwItem.getImportStatus(
|
254
|
+
status, icon = nwItem.getImportStatus()
|
257
255
|
self.statusIcon.setPixmap(icon.pixmap(iPx, iPx))
|
258
256
|
self.statusData.setText(status)
|
259
257
|
|
@@ -297,5 +295,3 @@ class GuiItemDetails(QWidget):
|
|
297
295
|
self.wCountData.setText(f"{wC:n}")
|
298
296
|
self.pCountData.setText(f"{pC:n}")
|
299
297
|
return
|
300
|
-
|
301
|
-
# END Class GuiItemDetails
|
novelwriter/gui/mainmenu.py
CHANGED
@@ -25,16 +25,16 @@ from __future__ import annotations
|
|
25
25
|
|
26
26
|
import logging
|
27
27
|
|
28
|
-
from typing import TYPE_CHECKING
|
29
28
|
from pathlib import Path
|
29
|
+
from typing import TYPE_CHECKING
|
30
30
|
|
31
|
-
from PyQt5.QtGui import QDesktopServices
|
32
31
|
from PyQt5.QtCore import QUrl, pyqtSignal, pyqtSlot
|
33
|
-
from PyQt5.
|
32
|
+
from PyQt5.QtGui import QDesktopServices
|
33
|
+
from PyQt5.QtWidgets import QAction, QMenuBar
|
34
34
|
|
35
35
|
from novelwriter import CONFIG, SHARED
|
36
36
|
from novelwriter.common import openExternalPath
|
37
|
-
from novelwriter.constants import nwConst,
|
37
|
+
from novelwriter.constants import nwConst, nwKeyWords, nwLabels, nwUnicode, trConst
|
38
38
|
from novelwriter.enum import nwDocAction, nwDocInsert, nwView, nwWidget
|
39
39
|
from novelwriter.extensions.eventfilters import StatusTipFilter
|
40
40
|
|
@@ -202,7 +202,7 @@ class GuiMainMenu(QMenuBar):
|
|
202
202
|
# Document > Save
|
203
203
|
self.aSaveDoc = self.docuMenu.addAction(self.tr("Save Document"))
|
204
204
|
self.aSaveDoc.setShortcut("Ctrl+S")
|
205
|
-
self.aSaveDoc.triggered.connect(self.mainGui.
|
205
|
+
self.aSaveDoc.triggered.connect(self.mainGui.forceSaveDocument)
|
206
206
|
|
207
207
|
# Document > Close
|
208
208
|
self.aCloseDoc = self.docuMenu.addAction(self.tr("Close Document"))
|
@@ -597,6 +597,12 @@ class GuiMainMenu(QMenuBar):
|
|
597
597
|
lambda: self.requestDocInsert.emit(nwDocInsert.LIPSUM)
|
598
598
|
)
|
599
599
|
|
600
|
+
# Insert > Footnote
|
601
|
+
self.aFootnote = self.insMenu.addAction(self.tr("Footnote"))
|
602
|
+
self.aFootnote.triggered.connect(
|
603
|
+
lambda: self.requestDocInsert.emit(nwDocInsert.FOOTNOTE)
|
604
|
+
)
|
605
|
+
|
600
606
|
return
|
601
607
|
|
602
608
|
def _buildFormatMenu(self) -> None:
|
@@ -985,5 +991,3 @@ class GuiMainMenu(QMenuBar):
|
|
985
991
|
self.aWebsite.triggered.connect(lambda: self._openWebsite(nwConst.URL_WEB))
|
986
992
|
|
987
993
|
return
|
988
|
-
|
989
|
-
# END Class GuiMainMenu
|
novelwriter/gui/noveltree.py
CHANGED
@@ -29,14 +29,13 @@ import logging
|
|
29
29
|
|
30
30
|
from enum import Enum
|
31
31
|
from time import time
|
32
|
-
from typing import TYPE_CHECKING
|
33
32
|
|
34
|
-
from PyQt5.QtCore import QModelIndex, QPoint, Qt,
|
33
|
+
from PyQt5.QtCore import QModelIndex, QPoint, Qt, pyqtSignal, pyqtSlot
|
35
34
|
from PyQt5.QtGui import QFocusEvent, QFont, QMouseEvent, QPalette, QResizeEvent
|
36
35
|
from PyQt5.QtWidgets import (
|
37
36
|
QAbstractItemView, QActionGroup, QFrame, QHBoxLayout, QHeaderView,
|
38
|
-
QInputDialog, QMenu,
|
39
|
-
|
37
|
+
QInputDialog, QMenu, QToolTip, QTreeWidget, QTreeWidgetItem, QVBoxLayout,
|
38
|
+
QWidget
|
40
39
|
)
|
41
40
|
|
42
41
|
from novelwriter import CONFIG, SHARED
|
@@ -47,10 +46,10 @@ from novelwriter.enum import nwDocMode, nwItemClass, nwOutline
|
|
47
46
|
from novelwriter.extensions.modified import NIconToolButton
|
48
47
|
from novelwriter.extensions.novelselector import NovelSelector
|
49
48
|
from novelwriter.gui.theme import STYLES_MIN_TOOLBUTTON
|
50
|
-
from novelwriter.types import
|
51
|
-
|
52
|
-
|
53
|
-
|
49
|
+
from novelwriter.types import (
|
50
|
+
QtAlignRight, QtDecoration, QtMouseLeft, QtMouseMiddle, QtSizeExpanding,
|
51
|
+
QtUserRole
|
52
|
+
)
|
54
53
|
|
55
54
|
logger = logging.getLogger(__name__)
|
56
55
|
|
@@ -62,8 +61,6 @@ class NovelTreeColumn(Enum):
|
|
62
61
|
FOCUS = 2
|
63
62
|
PLOT = 3
|
64
63
|
|
65
|
-
# END Enum NovelTreeColumn
|
66
|
-
|
67
64
|
|
68
65
|
class GuiNovelView(QWidget):
|
69
66
|
|
@@ -71,10 +68,8 @@ class GuiNovelView(QWidget):
|
|
71
68
|
selectedItemChanged = pyqtSignal(str)
|
72
69
|
openDocumentRequest = pyqtSignal(str, Enum, str, bool)
|
73
70
|
|
74
|
-
def __init__(self,
|
75
|
-
super().__init__(parent=
|
76
|
-
|
77
|
-
self.mainGui = mainGui
|
71
|
+
def __init__(self, parent: QWidget) -> None:
|
72
|
+
super().__init__(parent=parent)
|
78
73
|
|
79
74
|
# Build GUI
|
80
75
|
self.novelTree = GuiNovelTree(self)
|
@@ -188,8 +183,6 @@ class GuiNovelView(QWidget):
|
|
188
183
|
self.novelTree.refreshHandle(tHandle)
|
189
184
|
return
|
190
185
|
|
191
|
-
# END Class GuiNovelView
|
192
|
-
|
193
186
|
|
194
187
|
class GuiNovelToolBar(QWidget):
|
195
188
|
|
@@ -199,7 +192,6 @@ class GuiNovelToolBar(QWidget):
|
|
199
192
|
logger.debug("Create: GuiNovelToolBar")
|
200
193
|
|
201
194
|
self.novelView = novelView
|
202
|
-
self.mainGui = novelView.mainGui
|
203
195
|
|
204
196
|
iSz = SHARED.theme.baseIconSize
|
205
197
|
mPx = CONFIG.pxInt(2)
|
@@ -215,7 +207,7 @@ class GuiNovelToolBar(QWidget):
|
|
215
207
|
self.novelValue.setFont(selFont)
|
216
208
|
self.novelValue.setListFormat(self.tr("Outline of {0}"))
|
217
209
|
self.novelValue.setMinimumWidth(CONFIG.pxInt(150))
|
218
|
-
self.novelValue.setSizePolicy(
|
210
|
+
self.novelValue.setSizePolicy(QtSizeExpanding, QtSizeExpanding)
|
219
211
|
self.novelValue.novelSelectionChanged.connect(self.setCurrentRoot)
|
220
212
|
|
221
213
|
self.tbNovel = NIconToolButton(self, iSz)
|
@@ -353,8 +345,6 @@ class GuiNovelToolBar(QWidget):
|
|
353
345
|
self.aLastCol[colType] = aLast
|
354
346
|
return
|
355
347
|
|
356
|
-
# END Class GuiNovelToolBar
|
357
|
-
|
358
348
|
|
359
349
|
class GuiNovelTree(QTreeWidget):
|
360
350
|
|
@@ -375,7 +365,6 @@ class GuiNovelTree(QTreeWidget):
|
|
375
365
|
logger.debug("Create: GuiNovelTree")
|
376
366
|
|
377
367
|
self.novelView = novelView
|
378
|
-
self.mainGui = novelView.mainGui
|
379
368
|
|
380
369
|
# Internal Variables
|
381
370
|
self._treeMap = {}
|
@@ -490,7 +479,7 @@ class GuiNovelTree(QTreeWidget):
|
|
490
479
|
if rootHandle is None:
|
491
480
|
rootHandle = SHARED.project.tree.findRoot(nwItemClass.NOVEL)
|
492
481
|
|
493
|
-
treeChanged =
|
482
|
+
treeChanged = SHARED.mainGui.projView.changedSince(self._lastBuild)
|
494
483
|
indexChanged = SHARED.project.index.rootChangedSince(rootHandle, self._lastBuild)
|
495
484
|
if not (treeChanged or indexChanged or overRide):
|
496
485
|
logger.debug("No changes have been made to the novel index")
|
@@ -783,5 +772,3 @@ class GuiNovelTree(QTreeWidget):
|
|
783
772
|
if tags:
|
784
773
|
lines.append(f"<b>{trConst(nwLabels.KEY_NAME[key])}</b>: {tags}")
|
785
774
|
return lines
|
786
|
-
|
787
|
-
# END Class GuiNovelTree
|
novelwriter/gui/outline.py
CHANGED
@@ -30,30 +30,28 @@ from __future__ import annotations
|
|
30
30
|
import csv
|
31
31
|
import logging
|
32
32
|
|
33
|
-
from time import time
|
34
33
|
from enum import Enum
|
34
|
+
from time import time
|
35
35
|
|
36
|
-
from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot
|
36
|
+
from PyQt5.QtCore import QT_TRANSLATE_NOOP, Qt, pyqtSignal, pyqtSlot
|
37
37
|
from PyQt5.QtWidgets import (
|
38
38
|
QAbstractItemView, QAction, QFileDialog, QFrame, QGridLayout, QGroupBox,
|
39
|
-
QHBoxLayout, QLabel, QMenu, QScrollArea,
|
40
|
-
|
39
|
+
QHBoxLayout, QLabel, QMenu, QScrollArea, QSplitter, QToolBar, QToolButton,
|
40
|
+
QTreeWidget, QTreeWidgetItem, QVBoxLayout, QWidget
|
41
41
|
)
|
42
42
|
|
43
43
|
from novelwriter import CONFIG, SHARED
|
44
|
-
from novelwriter.enum import (
|
45
|
-
nwDocMode, nwItemClass, nwItemLayout, nwItemType, nwOutline
|
46
|
-
)
|
47
|
-
from novelwriter.error import logException
|
48
44
|
from novelwriter.common import checkInt, formatFileFilter, makeFileNameSafe
|
49
|
-
from novelwriter.constants import nwHeaders,
|
45
|
+
from novelwriter.constants import nwHeaders, nwKeyWords, nwLabels, trConst
|
46
|
+
from novelwriter.enum import nwDocMode, nwItemClass, nwItemLayout, nwItemType, nwOutline
|
47
|
+
from novelwriter.error import logException
|
50
48
|
from novelwriter.extensions.configlayout import NColourLabel
|
51
49
|
from novelwriter.extensions.novelselector import NovelSelector
|
52
50
|
from novelwriter.types import (
|
53
|
-
QtAlignLeftTop, QtAlignRight, QtAlignRightTop, QtDecoration,
|
51
|
+
QtAlignLeftTop, QtAlignRight, QtAlignRightTop, QtDecoration,
|
52
|
+
QtSizeExpanding, QtUserRole
|
54
53
|
)
|
55
54
|
|
56
|
-
|
57
55
|
logger = logging.getLogger(__name__)
|
58
56
|
|
59
57
|
|
@@ -196,8 +194,6 @@ class GuiOutlineView(QWidget):
|
|
196
194
|
self.outlineTree.refreshTree(rootHandle=(tHandle or None), overRide=True)
|
197
195
|
return
|
198
196
|
|
199
|
-
# END Class GuiOutlineView
|
200
|
-
|
201
197
|
|
202
198
|
class GuiOutlineToolBar(QToolBar):
|
203
199
|
|
@@ -215,7 +211,7 @@ class GuiOutlineToolBar(QToolBar):
|
|
215
211
|
self.setContentsMargins(0, 0, 0, 0)
|
216
212
|
|
217
213
|
stretch = QWidget(self)
|
218
|
-
stretch.setSizePolicy(
|
214
|
+
stretch.setSizePolicy(QtSizeExpanding, QtSizeExpanding)
|
219
215
|
|
220
216
|
# Novel Selector
|
221
217
|
self.novelLabel = NColourLabel(
|
@@ -311,8 +307,6 @@ class GuiOutlineToolBar(QToolBar):
|
|
311
307
|
self.outlineExportRequest.emit()
|
312
308
|
return
|
313
309
|
|
314
|
-
# END Class GuiOutlineToolBar
|
315
|
-
|
316
310
|
|
317
311
|
class GuiOutlineTree(QTreeWidget):
|
318
312
|
|
@@ -728,8 +722,6 @@ class GuiOutlineTree(QTreeWidget):
|
|
728
722
|
|
729
723
|
return
|
730
724
|
|
731
|
-
# END Class GuiOutlineTree
|
732
|
-
|
733
725
|
|
734
726
|
class GuiOutlineHeaderMenu(QMenu):
|
735
727
|
|
@@ -772,8 +764,6 @@ class GuiOutlineHeaderMenu(QMenu):
|
|
772
764
|
|
773
765
|
return
|
774
766
|
|
775
|
-
# END Class GuiOutlineHeaderMenu
|
776
|
-
|
777
767
|
|
778
768
|
class GuiOutlineDetails(QScrollArea):
|
779
769
|
|
@@ -1048,7 +1038,7 @@ class GuiOutlineDetails(QScrollArea):
|
|
1048
1038
|
self.titleLabel.setText(self.tr(self.LVL_MAP.get(novIdx.level, "H1")))
|
1049
1039
|
self.titleValue.setText(novIdx.title)
|
1050
1040
|
|
1051
|
-
itemStatus, _ = nwItem.getImportStatus(
|
1041
|
+
itemStatus, _ = nwItem.getImportStatus()
|
1052
1042
|
|
1053
1043
|
self.fileValue.setText(nwItem.itemName)
|
1054
1044
|
self.itemValue.setText(itemStatus)
|
@@ -1104,5 +1094,3 @@ class GuiOutlineDetails(QScrollArea):
|
|
1104
1094
|
return ", ".join(
|
1105
1095
|
[f"<a href='{tag}'>{tag}</a>" for tag in refs.get(key, [])]
|
1106
1096
|
)
|
1107
|
-
|
1108
|
-
# END Class GuiOutlineDetails
|