novelWriter 2.2rc1__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.2rc1.dist-info → novelWriter-2.2.1.dist-info}/METADATA +1 -1
- {novelWriter-2.2rc1.dist-info → novelWriter-2.2.1.dist-info}/RECORD +113 -111
- {novelWriter-2.2rc1.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_US.json +1 -0
- novelwriter/assets/i18n/project_es_419.json +11 -0
- novelwriter/assets/i18n/project_fr_FR.json +11 -0
- novelwriter/assets/i18n/project_it_IT.json +11 -0
- novelwriter/assets/i18n/project_ja_JP.json +2 -1
- novelwriter/assets/i18n/project_nb_NO.json +1 -0
- novelwriter/assets/i18n/project_zh_CN.json +11 -0
- novelwriter/assets/icons/typicons_dark/icons.conf +3 -2
- 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_light/icons.conf +3 -2
- 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/manual.pdf +0 -0
- novelwriter/assets/sample.zip +0 -0
- novelwriter/assets/text/release_notes.htm +50 -7
- novelwriter/common.py +16 -29
- novelwriter/config.py +3 -3
- novelwriter/constants.py +1 -1
- novelwriter/core/buildsettings.py +1 -1
- novelwriter/core/coretools.py +2 -1
- novelwriter/core/docbuild.py +1 -1
- novelwriter/core/document.py +1 -1
- novelwriter/core/index.py +2 -2
- novelwriter/core/item.py +2 -2
- novelwriter/core/options.py +3 -3
- novelwriter/core/project.py +3 -3
- novelwriter/core/projectdata.py +2 -2
- 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 +2 -2
- novelwriter/core/tokenizer.py +1 -1
- novelwriter/core/tomd.py +2 -2
- novelwriter/core/toodt.py +1 -1
- 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 +44 -57
- 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 +4 -14
- novelwriter/dialogs/wordlist.py +34 -21
- novelwriter/enum.py +5 -4
- 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 +72 -64
- novelwriter/gui/dochighlight.py +3 -2
- novelwriter/gui/docviewer.py +22 -47
- novelwriter/gui/docviewerpanel.py +68 -23
- novelwriter/gui/editordocument.py +3 -3
- novelwriter/gui/itemdetails.py +2 -2
- novelwriter/gui/mainmenu.py +35 -30
- novelwriter/gui/noveltree.py +44 -53
- novelwriter/gui/outline.py +2 -1
- novelwriter/gui/projtree.py +5 -6
- novelwriter/gui/sidebar.py +6 -4
- novelwriter/gui/statusbar.py +47 -4
- novelwriter/gui/theme.py +5 -6
- novelwriter/guimain.py +139 -189
- novelwriter/shared.py +53 -29
- novelwriter/tools/dictionaries.py +2 -2
- novelwriter/tools/lipsum.py +34 -28
- novelwriter/tools/manusbuild.py +3 -4
- novelwriter/tools/manuscript.py +19 -26
- novelwriter/tools/manussettings.py +2 -4
- novelwriter/tools/projwizard.py +3 -3
- novelwriter/tools/writingstats.py +17 -4
- novelwriter/assets/icons/typicons_dark/nw_tb-markdown.svg +0 -8
- novelwriter/assets/icons/typicons_dark/nw_tb-shortcode.svg +0 -8
- novelwriter/assets/icons/typicons_light/nw_tb-markdown.svg +0 -8
- novelwriter/assets/icons/typicons_light/nw_tb-shortcode.svg +0 -8
- {novelWriter-2.2rc1.dist-info → novelWriter-2.2.1.dist-info}/LICENSE.md +0 -0
- {novelWriter-2.2rc1.dist-info → novelWriter-2.2.1.dist-info}/entry_points.txt +0 -0
- {novelWriter-2.2rc1.dist-info → novelWriter-2.2.1.dist-info}/top_level.txt +0 -0
novelwriter/gui/doceditor.py
CHANGED
@@ -14,7 +14,7 @@ Created: 2023-11-06 [2.2b1] MetaCompleter
|
|
14
14
|
Created: 2023-11-07 [2.2b1] GuiDocToolBar
|
15
15
|
|
16
16
|
This file is a part of novelWriter
|
17
|
-
Copyright 2018–
|
17
|
+
Copyright 2018–2024, Veronica Berglyd Olsen
|
18
18
|
|
19
19
|
This program is free software: you can redistribute it and/or modify
|
20
20
|
it under the terms of the GNU General Public License as published by
|
@@ -58,10 +58,11 @@ from novelwriter.common import minmax, transferCase
|
|
58
58
|
from novelwriter.constants import nwKeyWords, nwLabels, nwShortcode, nwUnicode, trConst
|
59
59
|
from novelwriter.core.item import NWItem
|
60
60
|
from novelwriter.core.index import countWords
|
61
|
+
from novelwriter.tools.lipsum import GuiLipsum
|
61
62
|
from novelwriter.core.document import NWDocument
|
62
63
|
from novelwriter.gui.dochighlight import GuiDocHighlighter
|
63
64
|
from novelwriter.gui.editordocument import GuiTextDocument
|
64
|
-
from novelwriter.extensions.
|
65
|
+
from novelwriter.extensions.eventfilters import WheelEventFilter
|
65
66
|
|
66
67
|
if TYPE_CHECKING: # pragma: no cover
|
67
68
|
from novelwriter.guimain import GuiMain
|
@@ -717,11 +718,11 @@ class GuiDocEditor(QPlainTextEdit):
|
|
717
718
|
self.copy()
|
718
719
|
elif action == nwDocAction.PASTE:
|
719
720
|
self.paste()
|
720
|
-
elif action == nwDocAction.
|
721
|
+
elif action == nwDocAction.MD_ITALIC:
|
721
722
|
self._toggleFormat(1, "_")
|
722
|
-
elif action == nwDocAction.
|
723
|
+
elif action == nwDocAction.MD_BOLD:
|
723
724
|
self._toggleFormat(2, "*")
|
724
|
-
elif action == nwDocAction.
|
725
|
+
elif action == nwDocAction.MD_STRIKE:
|
725
726
|
self._toggleFormat(2, "~")
|
726
727
|
elif action == nwDocAction.S_QUOTE:
|
727
728
|
self._wrapSelection(self._typSQuoteO, self._typSQuoteC)
|
@@ -831,11 +832,11 @@ class GuiDocEditor(QPlainTextEdit):
|
|
831
832
|
elif insert == nwDocInsert.QUOTE_RD:
|
832
833
|
text = self._typDQuoteC
|
833
834
|
elif insert == nwDocInsert.SYNOPSIS:
|
834
|
-
text = "%
|
835
|
+
text = "%Synopsis: "
|
835
836
|
newBlock = True
|
836
837
|
goAfter = True
|
837
838
|
elif insert == nwDocInsert.SHORT:
|
838
|
-
text = "%
|
839
|
+
text = "%Short: "
|
839
840
|
newBlock = True
|
840
841
|
goAfter = True
|
841
842
|
elif insert == nwDocInsert.NEW_PAGE:
|
@@ -850,18 +851,23 @@ class GuiDocEditor(QPlainTextEdit):
|
|
850
851
|
text = "[vspace:2]"
|
851
852
|
newBlock = True
|
852
853
|
goAfter = False
|
854
|
+
elif insert == nwDocInsert.LIPSUM:
|
855
|
+
text = GuiLipsum.getLipsum(self)
|
856
|
+
newBlock = True
|
857
|
+
goAfter = False
|
853
858
|
else:
|
854
859
|
return False
|
855
860
|
else:
|
856
861
|
return False
|
857
862
|
|
858
|
-
if
|
859
|
-
|
860
|
-
|
861
|
-
|
862
|
-
|
863
|
-
|
864
|
-
|
863
|
+
if text:
|
864
|
+
if newBlock:
|
865
|
+
self.insertNewBlock(text, defaultAfter=goAfter)
|
866
|
+
else:
|
867
|
+
cursor = self.textCursor()
|
868
|
+
cursor.beginEditBlock()
|
869
|
+
cursor.insertText(text)
|
870
|
+
cursor.endEditBlock()
|
865
871
|
|
866
872
|
return True
|
867
873
|
|
@@ -1144,6 +1150,7 @@ class GuiDocEditor(QPlainTextEdit):
|
|
1144
1150
|
|
1145
1151
|
# Execute the context menu
|
1146
1152
|
ctxMenu.exec_(self.viewport().mapToGlobal(pos))
|
1153
|
+
ctxMenu.deleteLater()
|
1147
1154
|
|
1148
1155
|
return
|
1149
1156
|
|
@@ -2005,20 +2012,25 @@ class GuiDocEditor(QPlainTextEdit):
|
|
2005
2012
|
cPos = cursor.position()
|
2006
2013
|
bPos = cursor.block().position()
|
2007
2014
|
bLen = cursor.block().length()
|
2015
|
+
apos = nwUnicode.U_APOS + nwUnicode.U_RSQUO
|
2008
2016
|
|
2009
|
-
# Scan
|
2017
|
+
# Scan backward
|
2010
2018
|
sPos = cPos
|
2011
2019
|
for i in range(cPos - bPos):
|
2012
2020
|
sPos = cPos - i - 1
|
2013
|
-
|
2021
|
+
cOne = self._qDocument.characterAt(sPos)
|
2022
|
+
cTwo = self._qDocument.characterAt(sPos - 1)
|
2023
|
+
if not (cOne.isalnum() or cOne in apos and cTwo.isalnum()):
|
2014
2024
|
sPos += 1
|
2015
2025
|
break
|
2016
2026
|
|
2017
|
-
# Scan
|
2027
|
+
# Scan forward
|
2018
2028
|
ePos = cPos
|
2019
2029
|
for i in range(bPos + bLen - cPos):
|
2020
2030
|
ePos = cPos + i
|
2021
|
-
|
2031
|
+
cOne = self._qDocument.characterAt(ePos)
|
2032
|
+
cTwo = self._qDocument.characterAt(ePos + 1)
|
2033
|
+
if not (cOne.isalnum() or cOne in apos and cTwo.isalnum()):
|
2022
2034
|
break
|
2023
2035
|
|
2024
2036
|
if ePos - sPos <= 0:
|
@@ -2225,39 +2237,65 @@ class GuiDocToolBar(QWidget):
|
|
2225
2237
|
# General Buttons
|
2226
2238
|
# ===============
|
2227
2239
|
|
2228
|
-
self.
|
2229
|
-
self.
|
2230
|
-
self.
|
2231
|
-
self.
|
2232
|
-
|
2233
|
-
|
2240
|
+
self.tbBoldMD = QToolButton(self)
|
2241
|
+
self.tbBoldMD.setIconSize(iconSize)
|
2242
|
+
self.tbBoldMD.setToolTip(self.tr("Markdown Bold"))
|
2243
|
+
self.tbBoldMD.clicked.connect(
|
2244
|
+
lambda: self.requestDocAction.emit(nwDocAction.MD_BOLD)
|
2245
|
+
)
|
2246
|
+
|
2247
|
+
self.tbItalicMD = QToolButton(self)
|
2248
|
+
self.tbItalicMD.setIconSize(iconSize)
|
2249
|
+
self.tbItalicMD.setToolTip(self.tr("Markdown Italic"))
|
2250
|
+
self.tbItalicMD.clicked.connect(
|
2251
|
+
lambda: self.requestDocAction.emit(nwDocAction.MD_ITALIC)
|
2252
|
+
)
|
2253
|
+
|
2254
|
+
self.tbStrikeMD = QToolButton(self)
|
2255
|
+
self.tbStrikeMD.setIconSize(iconSize)
|
2256
|
+
self.tbStrikeMD.setToolTip(self.tr("Markdown Strikethrough"))
|
2257
|
+
self.tbStrikeMD.clicked.connect(
|
2258
|
+
lambda: self.requestDocAction.emit(nwDocAction.MD_STRIKE)
|
2259
|
+
)
|
2234
2260
|
|
2235
2261
|
self.tbBold = QToolButton(self)
|
2236
2262
|
self.tbBold.setIconSize(iconSize)
|
2237
|
-
self.tbBold.
|
2263
|
+
self.tbBold.setToolTip(self.tr("Shortcode Bold"))
|
2264
|
+
self.tbBold.clicked.connect(
|
2265
|
+
lambda: self.requestDocAction.emit(nwDocAction.SC_BOLD)
|
2266
|
+
)
|
2238
2267
|
|
2239
2268
|
self.tbItalic = QToolButton(self)
|
2240
2269
|
self.tbItalic.setIconSize(iconSize)
|
2241
|
-
self.tbItalic.
|
2270
|
+
self.tbItalic.setToolTip(self.tr("Shortcode Italic"))
|
2271
|
+
self.tbItalic.clicked.connect(
|
2272
|
+
lambda: self.requestDocAction.emit(nwDocAction.SC_ITALIC)
|
2273
|
+
)
|
2242
2274
|
|
2243
2275
|
self.tbStrike = QToolButton(self)
|
2244
2276
|
self.tbStrike.setIconSize(iconSize)
|
2245
|
-
self.tbStrike.
|
2277
|
+
self.tbStrike.setToolTip(self.tr("Shortcode Strikethrough"))
|
2278
|
+
self.tbStrike.clicked.connect(
|
2279
|
+
lambda: self.requestDocAction.emit(nwDocAction.SC_STRIKE)
|
2280
|
+
)
|
2246
2281
|
|
2247
2282
|
self.tbUnderline = QToolButton(self)
|
2248
2283
|
self.tbUnderline.setIconSize(iconSize)
|
2284
|
+
self.tbUnderline.setToolTip(self.tr("Shortcode Underline"))
|
2249
2285
|
self.tbUnderline.clicked.connect(
|
2250
2286
|
lambda: self.requestDocAction.emit(nwDocAction.SC_ULINE)
|
2251
2287
|
)
|
2252
2288
|
|
2253
2289
|
self.tbSuperscript = QToolButton(self)
|
2254
2290
|
self.tbSuperscript.setIconSize(iconSize)
|
2291
|
+
self.tbSuperscript.setToolTip(self.tr("Shortcode Superscript"))
|
2255
2292
|
self.tbSuperscript.clicked.connect(
|
2256
2293
|
lambda: self.requestDocAction.emit(nwDocAction.SC_SUP)
|
2257
2294
|
)
|
2258
2295
|
|
2259
2296
|
self.tbSubscript = QToolButton(self)
|
2260
2297
|
self.tbSubscript.setIconSize(iconSize)
|
2298
|
+
self.tbSubscript.setToolTip(self.tr("Shortcode Subscript"))
|
2261
2299
|
self.tbSubscript.clicked.connect(
|
2262
2300
|
lambda: self.requestDocAction.emit(nwDocAction.SC_SUB)
|
2263
2301
|
)
|
@@ -2266,7 +2304,10 @@ class GuiDocToolBar(QWidget):
|
|
2266
2304
|
# ========
|
2267
2305
|
|
2268
2306
|
self.outerBox = QVBoxLayout()
|
2269
|
-
self.outerBox.addWidget(self.
|
2307
|
+
self.outerBox.addWidget(self.tbBoldMD)
|
2308
|
+
self.outerBox.addWidget(self.tbItalicMD)
|
2309
|
+
self.outerBox.addWidget(self.tbStrikeMD)
|
2310
|
+
self.outerBox.addSpacing(cM)
|
2270
2311
|
self.outerBox.addWidget(self.tbBold)
|
2271
2312
|
self.outerBox.addWidget(self.tbItalic)
|
2272
2313
|
self.outerBox.addWidget(self.tbStrike)
|
@@ -2294,8 +2335,9 @@ class GuiDocToolBar(QWidget):
|
|
2294
2335
|
palette.setColor(QPalette.ColorRole.Text, QColor(*SHARED.theme.colText))
|
2295
2336
|
self.setPalette(palette)
|
2296
2337
|
|
2297
|
-
|
2298
|
-
self.
|
2338
|
+
self.tbBoldMD.setIcon(SHARED.theme.getIcon("fmt_bold-md"))
|
2339
|
+
self.tbItalicMD.setIcon(SHARED.theme.getIcon("fmt_italic-md"))
|
2340
|
+
self.tbStrikeMD.setIcon(SHARED.theme.getIcon("fmt_strike-md"))
|
2299
2341
|
self.tbBold.setIcon(SHARED.theme.getIcon("fmt_bold"))
|
2300
2342
|
self.tbItalic.setIcon(SHARED.theme.getIcon("fmt_italic"))
|
2301
2343
|
self.tbStrike.setIcon(SHARED.theme.getIcon("fmt_strike"))
|
@@ -2305,40 +2347,6 @@ class GuiDocToolBar(QWidget):
|
|
2305
2347
|
|
2306
2348
|
return
|
2307
2349
|
|
2308
|
-
##
|
2309
|
-
# Private Slots
|
2310
|
-
##
|
2311
|
-
|
2312
|
-
@pyqtSlot(bool)
|
2313
|
-
def _toggleFormatMode(self, checked: bool) -> None:
|
2314
|
-
"""Toggle the formatting mode."""
|
2315
|
-
CONFIG.useShortcodes = checked
|
2316
|
-
return
|
2317
|
-
|
2318
|
-
@pyqtSlot()
|
2319
|
-
def _formatBold(self):
|
2320
|
-
"""Call the bold format action."""
|
2321
|
-
self.requestDocAction.emit(
|
2322
|
-
nwDocAction.SC_BOLD if self.tbMode.isChecked() else nwDocAction.STRONG
|
2323
|
-
)
|
2324
|
-
return
|
2325
|
-
|
2326
|
-
@pyqtSlot()
|
2327
|
-
def _formatItalic(self):
|
2328
|
-
"""Call the italic format action."""
|
2329
|
-
self.requestDocAction.emit(
|
2330
|
-
nwDocAction.SC_ITALIC if self.tbMode.isChecked() else nwDocAction.EMPH
|
2331
|
-
)
|
2332
|
-
return
|
2333
|
-
|
2334
|
-
@pyqtSlot()
|
2335
|
-
def _formatStrike(self):
|
2336
|
-
"""Call the strikethrough format action."""
|
2337
|
-
self.requestDocAction.emit(
|
2338
|
-
nwDocAction.SC_STRIKE if self.tbMode.isChecked() else nwDocAction.STRIKE
|
2339
|
-
)
|
2340
|
-
return
|
2341
|
-
|
2342
2350
|
# END Class GuiDocToolBar
|
2343
2351
|
|
2344
2352
|
|
novelwriter/gui/dochighlight.py
CHANGED
@@ -3,10 +3,11 @@ novelWriter – GUI Syntax Highlighter
|
|
3
3
|
====================================
|
4
4
|
|
5
5
|
File History:
|
6
|
-
Created: 2019-04-06 [0.0.1]
|
6
|
+
Created: 2019-04-06 [0.0.1] GuiDocHighlighter
|
7
|
+
Created: 2023-09-10 [2.2b1] TextBlockData
|
7
8
|
|
8
9
|
This file is a part of novelWriter
|
9
|
-
Copyright 2018–
|
10
|
+
Copyright 2018–2024, Veronica Berglyd Olsen
|
10
11
|
|
11
12
|
This program is free software: you can redistribute it and/or modify
|
12
13
|
it under the terms of the GNU General Public License as published by
|
novelwriter/gui/docviewer.py
CHANGED
@@ -9,7 +9,7 @@ Created: 2020-06-09 [0.8] GuiDocViewFooter
|
|
9
9
|
Created: 2020-09-08 [1.0b1] GuiDocViewHistory
|
10
10
|
|
11
11
|
This file is a part of novelWriter
|
12
|
-
Copyright 2018–
|
12
|
+
Copyright 2018–2024, Veronica Berglyd Olsen
|
13
13
|
|
14
14
|
This program is free software: you can redistribute it and/or modify
|
15
15
|
it under the terms of the GNU General Public License as published by
|
@@ -46,7 +46,7 @@ from novelwriter.enum import nwItemType, nwDocAction, nwDocMode
|
|
46
46
|
from novelwriter.error import logException
|
47
47
|
from novelwriter.constants import nwUnicode
|
48
48
|
from novelwriter.core.tohtml import ToHtml
|
49
|
-
from novelwriter.extensions.
|
49
|
+
from novelwriter.extensions.eventfilters import WheelEventFilter
|
50
50
|
|
51
51
|
if TYPE_CHECKING: # pragma: no cover
|
52
52
|
from novelwriter.guimain import GuiMain
|
@@ -378,33 +378,34 @@ class GuiDocViewer(QTextBrowser):
|
|
378
378
|
userCursor = self.textCursor()
|
379
379
|
userSelection = userCursor.hasSelection()
|
380
380
|
|
381
|
-
|
381
|
+
ctxMenu = QMenu(self)
|
382
382
|
|
383
383
|
if userSelection:
|
384
|
-
mnuCopy = QAction(self.tr("Copy"),
|
384
|
+
mnuCopy = QAction(self.tr("Copy"), ctxMenu)
|
385
385
|
mnuCopy.triggered.connect(lambda: self.docAction(nwDocAction.COPY))
|
386
|
-
|
386
|
+
ctxMenu.addAction(mnuCopy)
|
387
387
|
|
388
|
-
|
388
|
+
ctxMenu.addSeparator()
|
389
389
|
|
390
|
-
mnuSelAll = QAction(self.tr("Select All"),
|
390
|
+
mnuSelAll = QAction(self.tr("Select All"), ctxMenu)
|
391
391
|
mnuSelAll.triggered.connect(lambda: self.docAction(nwDocAction.SEL_ALL))
|
392
|
-
|
392
|
+
ctxMenu.addAction(mnuSelAll)
|
393
393
|
|
394
|
-
mnuSelWord = QAction(self.tr("Select Word"),
|
394
|
+
mnuSelWord = QAction(self.tr("Select Word"), ctxMenu)
|
395
395
|
mnuSelWord.triggered.connect(
|
396
396
|
lambda: self._makePosSelection(QTextCursor.SelectionType.WordUnderCursor, point)
|
397
397
|
)
|
398
|
-
|
398
|
+
ctxMenu.addAction(mnuSelWord)
|
399
399
|
|
400
|
-
mnuSelPara = QAction(self.tr("Select Paragraph"),
|
400
|
+
mnuSelPara = QAction(self.tr("Select Paragraph"), ctxMenu)
|
401
401
|
mnuSelPara.triggered.connect(
|
402
402
|
lambda: self._makePosSelection(QTextCursor.SelectionType.BlockUnderCursor, point)
|
403
403
|
)
|
404
|
-
|
404
|
+
ctxMenu.addAction(mnuSelPara)
|
405
405
|
|
406
406
|
# Open the context menu
|
407
|
-
|
407
|
+
ctxMenu.exec_(self.viewport().mapToGlobal(point))
|
408
|
+
ctxMenu.deleteLater()
|
408
409
|
|
409
410
|
return
|
410
411
|
|
@@ -861,8 +862,7 @@ class GuiDocViewFooter(QWidget):
|
|
861
862
|
self._docHandle = None
|
862
863
|
|
863
864
|
fPx = int(0.9*SHARED.theme.fontPixelSize)
|
864
|
-
|
865
|
-
hSp = CONFIG.pxInt(8)
|
865
|
+
hSp = CONFIG.pxInt(4)
|
866
866
|
|
867
867
|
# Main Widget Settings
|
868
868
|
self.setContentsMargins(0, 0, 0, 0)
|
@@ -872,64 +872,41 @@ class GuiDocViewFooter(QWidget):
|
|
872
872
|
self.showHide = QToolButton(self)
|
873
873
|
self.showHide.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonIconOnly)
|
874
874
|
self.showHide.setIconSize(QSize(fPx, fPx))
|
875
|
-
self.showHide.setFixedSize(QSize(fPx, fPx))
|
876
875
|
self.showHide.clicked.connect(lambda: self.docViewer.togglePanelVisibility.emit())
|
877
876
|
self.showHide.setToolTip(self.tr("Show/Hide Viewer Panel"))
|
878
877
|
|
879
878
|
# Show Comments
|
880
879
|
self.showComments = QToolButton(self)
|
880
|
+
self.showComments.setText(self.tr("Comments"))
|
881
881
|
self.showComments.setCheckable(True)
|
882
882
|
self.showComments.setChecked(CONFIG.viewComments)
|
883
|
-
self.showComments.setToolButtonStyle(Qt.ToolButtonStyle.
|
883
|
+
self.showComments.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonTextBesideIcon)
|
884
884
|
self.showComments.setIconSize(QSize(fPx, fPx))
|
885
|
-
self.showComments.setFixedSize(QSize(fPx, fPx))
|
886
885
|
self.showComments.toggled.connect(self._doToggleComments)
|
887
886
|
self.showComments.setToolTip(self.tr("Show Comments"))
|
888
887
|
|
889
888
|
# Show Synopsis
|
890
889
|
self.showSynopsis = QToolButton(self)
|
890
|
+
self.showSynopsis.setText(self.tr("Synopsis"))
|
891
891
|
self.showSynopsis.setCheckable(True)
|
892
892
|
self.showSynopsis.setChecked(CONFIG.viewSynopsis)
|
893
|
-
self.showSynopsis.setToolButtonStyle(Qt.ToolButtonStyle.
|
893
|
+
self.showSynopsis.setToolButtonStyle(Qt.ToolButtonStyle.ToolButtonTextBesideIcon)
|
894
894
|
self.showSynopsis.setIconSize(QSize(fPx, fPx))
|
895
|
-
self.showSynopsis.setFixedSize(QSize(fPx, fPx))
|
896
895
|
self.showSynopsis.toggled.connect(self._doToggleSynopsis)
|
897
896
|
self.showSynopsis.setToolTip(self.tr("Show Synopsis Comments"))
|
898
897
|
|
899
|
-
# Labels
|
900
|
-
self.lblComments = QLabel(self.tr("Comments"))
|
901
|
-
self.lblComments.setBuddy(self.showComments)
|
902
|
-
self.lblComments.setIndent(0)
|
903
|
-
self.lblComments.setMargin(0)
|
904
|
-
self.lblComments.setContentsMargins(0, 0, 0, 0)
|
905
|
-
self.lblComments.setAutoFillBackground(True)
|
906
|
-
self.lblComments.setFixedHeight(fPx)
|
907
|
-
self.lblComments.setAlignment(Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignTop)
|
908
|
-
|
909
|
-
self.lblSynopsis = QLabel(self.tr("Synopsis"))
|
910
|
-
self.lblSynopsis.setBuddy(self.showSynopsis)
|
911
|
-
self.lblSynopsis.setIndent(0)
|
912
|
-
self.lblSynopsis.setMargin(0)
|
913
|
-
self.lblSynopsis.setContentsMargins(0, 0, 0, 0)
|
914
|
-
self.lblSynopsis.setAutoFillBackground(True)
|
915
|
-
self.lblSynopsis.setFixedHeight(fPx)
|
916
|
-
self.lblSynopsis.setAlignment(Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignTop)
|
917
|
-
|
918
898
|
lblFont = self.font()
|
919
899
|
lblFont.setPointSizeF(0.9*SHARED.theme.fontPointSize)
|
920
|
-
self.
|
921
|
-
self.
|
900
|
+
self.showComments.setFont(lblFont)
|
901
|
+
self.showSynopsis.setFont(lblFont)
|
922
902
|
|
923
903
|
# Assemble Layout
|
924
904
|
self.outerBox = QHBoxLayout()
|
925
|
-
self.outerBox.setSpacing(bSp)
|
926
905
|
self.outerBox.addWidget(self.showHide, 0)
|
927
906
|
self.outerBox.addStretch(1)
|
928
907
|
self.outerBox.addWidget(self.showComments, 0)
|
929
|
-
self.outerBox.addWidget(self.lblComments, 0)
|
930
|
-
self.outerBox.addSpacing(hSp)
|
931
908
|
self.outerBox.addWidget(self.showSynopsis, 0)
|
932
|
-
self.outerBox.
|
909
|
+
self.outerBox.setSpacing(hSp)
|
933
910
|
self.setLayout(self.outerBox)
|
934
911
|
|
935
912
|
# Fix Margins and Size
|
@@ -983,8 +960,6 @@ class GuiDocViewFooter(QWidget):
|
|
983
960
|
palette.setColor(QPalette.ColorRole.WindowText, QColor(*SHARED.theme.colText))
|
984
961
|
palette.setColor(QPalette.ColorRole.Text, QColor(*SHARED.theme.colText))
|
985
962
|
self.setPalette(palette)
|
986
|
-
self.lblComments.setPalette(palette)
|
987
|
-
self.lblSynopsis.setPalette(palette)
|
988
963
|
return
|
989
964
|
|
990
965
|
##
|
@@ -6,7 +6,7 @@ File History:
|
|
6
6
|
Created: 2023-11-14 [2.2rc1] GuiDocViewerPanel
|
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
|
@@ -57,7 +57,7 @@ class GuiDocViewerPanel(QWidget):
|
|
57
57
|
self.tabBackRefs = _ViewPanelBackRefs(self)
|
58
58
|
|
59
59
|
self.mainTabs = QTabWidget(self)
|
60
|
-
self.mainTabs.addTab(self.tabBackRefs, self.tr("
|
60
|
+
self.mainTabs.addTab(self.tabBackRefs, self.tr("References"))
|
61
61
|
|
62
62
|
self.kwTabs: dict[str, _ViewPanelKeyWords] = {}
|
63
63
|
self.idTabs: dict[str, int] = {}
|
@@ -73,7 +73,7 @@ class GuiDocViewerPanel(QWidget):
|
|
73
73
|
self.outerBox.setContentsMargins(0, 0, 0, 0)
|
74
74
|
|
75
75
|
self.setLayout(self.outerBox)
|
76
|
-
self.updateTheme()
|
76
|
+
self.updateTheme(updateTabs=False)
|
77
77
|
|
78
78
|
logger.debug("Ready: GuiDocViewerPanel")
|
79
79
|
|
@@ -83,7 +83,7 @@ class GuiDocViewerPanel(QWidget):
|
|
83
83
|
# Methods
|
84
84
|
##
|
85
85
|
|
86
|
-
def updateTheme(self) -> None:
|
86
|
+
def updateTheme(self, updateTabs: bool = True) -> None:
|
87
87
|
"""Update theme elements."""
|
88
88
|
vPx = CONFIG.pxInt(4)
|
89
89
|
lPx = CONFIG.pxInt(2)
|
@@ -102,6 +102,11 @@ class GuiDocViewerPanel(QWidget):
|
|
102
102
|
self.mainTabs.setStyleSheet(styleSheet)
|
103
103
|
self.updateHandle(self._lastHandle)
|
104
104
|
|
105
|
+
if updateTabs:
|
106
|
+
self.tabBackRefs.updateTheme()
|
107
|
+
for tab in self.kwTabs.values():
|
108
|
+
tab.updateTheme()
|
109
|
+
|
105
110
|
return
|
106
111
|
|
107
112
|
def openProjectTasks(self) -> None:
|
@@ -118,6 +123,7 @@ class GuiDocViewerPanel(QWidget):
|
|
118
123
|
widths = {}
|
119
124
|
for key, tab in self.kwTabs.items():
|
120
125
|
widths[key] = tab.getColumnWidths()
|
126
|
+
logger.debug("Saving State: GuiDocViewerPanel")
|
121
127
|
SHARED.project.options.setValue("GuiDocViewerPanel", "colWidths", widths)
|
122
128
|
return
|
123
129
|
|
@@ -218,12 +224,14 @@ class _ViewPanelBackRefs(QTreeWidget):
|
|
218
224
|
# Set Header Sizes
|
219
225
|
treeHeader = self.header()
|
220
226
|
treeHeader.setStretchLastSection(True)
|
227
|
+
treeHeader.setMinimumSectionSize(iPx + cMg) # See Issue #1627
|
221
228
|
treeHeader.setSectionResizeMode(self.C_DOC, QHeaderView.ResizeMode.ResizeToContents)
|
222
229
|
treeHeader.setSectionResizeMode(self.C_EDIT, QHeaderView.ResizeMode.Fixed)
|
223
230
|
treeHeader.setSectionResizeMode(self.C_VIEW, QHeaderView.ResizeMode.Fixed)
|
224
231
|
treeHeader.setSectionResizeMode(self.C_TITLE, QHeaderView.ResizeMode.ResizeToContents)
|
225
232
|
treeHeader.resizeSection(self.C_EDIT, iPx + cMg)
|
226
233
|
treeHeader.resizeSection(self.C_VIEW, iPx + cMg)
|
234
|
+
treeHeader.setSectionsMovable(False)
|
227
235
|
|
228
236
|
# Cache Icons Locally
|
229
237
|
self._editIcon = SHARED.theme.getIcon("edit")
|
@@ -235,6 +243,16 @@ class _ViewPanelBackRefs(QTreeWidget):
|
|
235
243
|
|
236
244
|
return
|
237
245
|
|
246
|
+
def updateTheme(self) -> None:
|
247
|
+
"""Update theme elements."""
|
248
|
+
self._editIcon = SHARED.theme.getIcon("edit")
|
249
|
+
self._viewIcon = SHARED.theme.getIcon("view")
|
250
|
+
for i in range(self.topLevelItemCount()):
|
251
|
+
if item := self.topLevelItem(i):
|
252
|
+
item.setIcon(self.C_EDIT, self._editIcon)
|
253
|
+
item.setIcon(self.C_VIEW, self._viewIcon)
|
254
|
+
return
|
255
|
+
|
238
256
|
def clearContent(self) -> None:
|
239
257
|
"""Clear the widget."""
|
240
258
|
self.clear()
|
@@ -276,7 +294,7 @@ class _ViewPanelBackRefs(QTreeWidget):
|
|
276
294
|
def _treeItemDoubleClicked(self, index: QModelIndex) -> None:
|
277
295
|
"""Emit follow tag signal on user double click."""
|
278
296
|
tHandle = index.siblingAtColumn(self.C_DATA).data(self.D_HANDLE)
|
279
|
-
if index.column()
|
297
|
+
if index.column() not in (self.C_EDIT, self.C_VIEW):
|
280
298
|
self._parent.openDocumentRequest.emit(tHandle, nwDocMode.VIEW, "", True)
|
281
299
|
return
|
282
300
|
|
@@ -299,10 +317,12 @@ class _ViewPanelBackRefs(QTreeWidget):
|
|
299
317
|
|
300
318
|
trItem.setIcon(self.C_DOC, docIcon)
|
301
319
|
trItem.setText(self.C_DOC, nwItem.itemName)
|
320
|
+
trItem.setToolTip(self.C_DOC, nwItem.itemName)
|
302
321
|
trItem.setIcon(self.C_EDIT, self._editIcon)
|
303
322
|
trItem.setIcon(self.C_VIEW, self._viewIcon)
|
304
|
-
trItem.setText(self.C_TITLE, hItem.title)
|
305
323
|
trItem.setData(self.C_TITLE, Qt.ItemDataRole.DecorationRole, hDec)
|
324
|
+
trItem.setText(self.C_TITLE, hItem.title)
|
325
|
+
trItem.setToolTip(self.C_TITLE, hItem.title)
|
306
326
|
trItem.setData(self.C_DATA, self.D_HANDLE, tHandle)
|
307
327
|
|
308
328
|
if tKey not in self._treeMap:
|
@@ -316,13 +336,14 @@ class _ViewPanelBackRefs(QTreeWidget):
|
|
316
336
|
|
317
337
|
class _ViewPanelKeyWords(QTreeWidget):
|
318
338
|
|
319
|
-
C_DATA
|
320
|
-
C_NAME
|
321
|
-
C_EDIT
|
322
|
-
C_VIEW
|
323
|
-
|
324
|
-
|
325
|
-
|
339
|
+
C_DATA = 0
|
340
|
+
C_NAME = 0
|
341
|
+
C_EDIT = 1
|
342
|
+
C_VIEW = 2
|
343
|
+
C_IMPORT = 3
|
344
|
+
C_DOC = 4
|
345
|
+
C_TITLE = 5
|
346
|
+
C_SHORT = 6
|
326
347
|
|
327
348
|
D_TAG = Qt.ItemDataRole.UserRole
|
328
349
|
|
@@ -330,13 +351,14 @@ class _ViewPanelKeyWords(QTreeWidget):
|
|
330
351
|
super().__init__(parent=parent)
|
331
352
|
|
332
353
|
self._parent = parent
|
354
|
+
self._class = itemClass
|
333
355
|
self._treeMap: dict[str, QTreeWidgetItem] = {}
|
334
356
|
|
335
357
|
iPx = SHARED.theme.baseIconSize
|
336
358
|
cMg = CONFIG.pxInt(6)
|
337
359
|
|
338
360
|
self.setHeaderLabels([
|
339
|
-
self.tr("Tag"), "", "", self.tr("Document"),
|
361
|
+
self.tr("Tag"), "", "", self.tr("Importance"), self.tr("Document"),
|
340
362
|
self.tr("Heading"), self.tr("Short Description")
|
341
363
|
])
|
342
364
|
self.setIndentation(0)
|
@@ -351,7 +373,7 @@ class _ViewPanelKeyWords(QTreeWidget):
|
|
351
373
|
# Set Header Sizes
|
352
374
|
treeHeader = self.header()
|
353
375
|
treeHeader.setStretchLastSection(True)
|
354
|
-
treeHeader.
|
376
|
+
treeHeader.setMinimumSectionSize(iPx + cMg) # See Issue #1627
|
355
377
|
treeHeader.setSectionResizeMode(self.C_EDIT, QHeaderView.ResizeMode.Fixed)
|
356
378
|
treeHeader.setSectionResizeMode(self.C_VIEW, QHeaderView.ResizeMode.Fixed)
|
357
379
|
treeHeader.resizeSection(self.C_EDIT, iPx + cMg)
|
@@ -369,6 +391,17 @@ class _ViewPanelKeyWords(QTreeWidget):
|
|
369
391
|
|
370
392
|
return
|
371
393
|
|
394
|
+
def updateTheme(self) -> None:
|
395
|
+
"""Update theme elements."""
|
396
|
+
self._classIcon = SHARED.theme.getIcon(nwLabels.CLASS_ICON[self._class])
|
397
|
+
self._editIcon = SHARED.theme.getIcon("edit")
|
398
|
+
self._viewIcon = SHARED.theme.getIcon("view")
|
399
|
+
for i in range(self.topLevelItemCount()):
|
400
|
+
if item := self.topLevelItem(i):
|
401
|
+
item.setIcon(self.C_EDIT, self._editIcon)
|
402
|
+
item.setIcon(self.C_VIEW, self._viewIcon)
|
403
|
+
return
|
404
|
+
|
372
405
|
def countEntries(self) -> int:
|
373
406
|
"""Return the number of items in the list."""
|
374
407
|
return self.topLevelItemCount()
|
@@ -386,22 +419,30 @@ class _ViewPanelKeyWords(QTreeWidget):
|
|
386
419
|
nwItem.itemType, nwItem.itemClass,
|
387
420
|
nwItem.itemLayout, nwItem.mainHeading
|
388
421
|
)
|
422
|
+
impLabel, impIcon = nwItem.getImportStatus(incIcon=True)
|
389
423
|
iLevel = nwHeaders.H_LEVEL.get(hItem.level, 0) if nwItem.isDocumentLayout() else 5
|
390
424
|
hDec = SHARED.theme.getHeaderDecorationNarrow(iLevel)
|
391
425
|
|
392
|
-
# This can not use a get call to the dictionary as that
|
393
|
-
#
|
426
|
+
# This can not use a get call to the dictionary as that would create an
|
427
|
+
# instance of the QTreeWidgetItem, which has some weird side effects
|
394
428
|
trItem = self._treeMap[tag] if tag in self._treeMap else QTreeWidgetItem()
|
395
429
|
|
396
|
-
trItem.setText(self.C_NAME, name)
|
397
430
|
trItem.setIcon(self.C_NAME, self._classIcon)
|
431
|
+
trItem.setText(self.C_NAME, name)
|
432
|
+
trItem.setToolTip(self.C_NAME, name)
|
398
433
|
trItem.setIcon(self.C_EDIT, self._editIcon)
|
399
434
|
trItem.setIcon(self.C_VIEW, self._viewIcon)
|
435
|
+
trItem.setIcon(self.C_IMPORT, impIcon)
|
436
|
+
trItem.setText(self.C_IMPORT, impLabel)
|
437
|
+
trItem.setToolTip(self.C_IMPORT, impLabel)
|
400
438
|
trItem.setIcon(self.C_DOC, docIcon)
|
401
439
|
trItem.setText(self.C_DOC, nwItem.itemName)
|
402
|
-
trItem.
|
440
|
+
trItem.setToolTip(self.C_DOC, nwItem.itemName)
|
403
441
|
trItem.setData(self.C_TITLE, Qt.ItemDataRole.DecorationRole, hDec)
|
442
|
+
trItem.setText(self.C_TITLE, hItem.title)
|
443
|
+
trItem.setToolTip(self.C_TITLE, hItem.title)
|
404
444
|
trItem.setText(self.C_SHORT, hItem.synopsis)
|
445
|
+
trItem.setToolTip(self.C_SHORT, hItem.synopsis)
|
405
446
|
trItem.setData(self.C_DATA, self.D_TAG, tag)
|
406
447
|
|
407
448
|
if tag not in self._treeMap:
|
@@ -420,14 +461,18 @@ class _ViewPanelKeyWords(QTreeWidget):
|
|
420
461
|
|
421
462
|
def setColumnWidths(self, widths: list[int]) -> None:
|
422
463
|
"""Set the column widths."""
|
423
|
-
if isinstance(widths, list) and len(widths) >=
|
424
|
-
self.setColumnWidth(self.
|
425
|
-
self.setColumnWidth(self.
|
464
|
+
if isinstance(widths, list) and len(widths) >= 4:
|
465
|
+
self.setColumnWidth(self.C_NAME, CONFIG.pxInt(checkInt(widths[0], 100)))
|
466
|
+
self.setColumnWidth(self.C_IMPORT, CONFIG.pxInt(checkInt(widths[1], 100)))
|
467
|
+
self.setColumnWidth(self.C_DOC, CONFIG.pxInt(checkInt(widths[2], 100)))
|
468
|
+
self.setColumnWidth(self.C_TITLE, CONFIG.pxInt(checkInt(widths[3], 100)))
|
426
469
|
return
|
427
470
|
|
428
471
|
def getColumnWidths(self) -> list[int]:
|
429
472
|
"""Get the widths of the user-adjustable columns."""
|
430
473
|
return [
|
474
|
+
CONFIG.rpxInt(self.columnWidth(self.C_NAME)),
|
475
|
+
CONFIG.rpxInt(self.columnWidth(self.C_IMPORT)),
|
431
476
|
CONFIG.rpxInt(self.columnWidth(self.C_DOC)),
|
432
477
|
CONFIG.rpxInt(self.columnWidth(self.C_TITLE)),
|
433
478
|
]
|
@@ -450,7 +495,7 @@ class _ViewPanelKeyWords(QTreeWidget):
|
|
450
495
|
def _treeItemDoubleClicked(self, index: QModelIndex) -> None:
|
451
496
|
"""Emit follow tag signal on user double click."""
|
452
497
|
tag = index.siblingAtColumn(self.C_DATA).data(self.D_TAG)
|
453
|
-
if index.column()
|
498
|
+
if index.column() not in (self.C_EDIT, self.C_VIEW):
|
454
499
|
self._parent.loadDocumentTagRequest.emit(tag, nwDocMode.VIEW)
|
455
500
|
return
|
456
501
|
|