novelWriter 2.2rc1__py3-none-any.whl → 2.3__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.3.dist-info}/METADATA +1 -1
- {novelWriter-2.2rc1.dist-info → novelWriter-2.3.dist-info}/RECORD +149 -132
- {novelWriter-2.2rc1.dist-info → novelWriter-2.3.dist-info}/WHEEL +1 -1
- novelWriter-2.3.dist-info/entry_points.txt +2 -0
- novelwriter/__init__.py +11 -6
- novelwriter/assets/i18n/nw_de_DE.qm +0 -0
- novelwriter/assets/i18n/nw_en_US.qm +0 -0
- novelwriter/assets/i18n/nw_es_419.qm +0 -0
- novelwriter/assets/i18n/nw_fr_FR.qm +0 -0
- novelwriter/assets/i18n/nw_it_IT.qm +0 -0
- novelwriter/assets/i18n/nw_ja_JP.qm +0 -0
- novelwriter/assets/i18n/nw_nb_NO.qm +0 -0
- novelwriter/assets/i18n/nw_nl_NL.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_nl_NL.json +11 -0
- novelwriter/assets/i18n/project_pt_BR.json +11 -0
- novelwriter/assets/i18n/project_zh_CN.json +11 -0
- novelwriter/assets/icons/typicons_dark/icons.conf +11 -2
- novelwriter/assets/icons/typicons_dark/mixed_document-new.svg +6 -0
- novelwriter/assets/icons/typicons_dark/mixed_import.svg +5 -0
- novelwriter/assets/icons/typicons_dark/nw_tb-bold-md.svg +4 -0
- novelwriter/assets/icons/typicons_dark/nw_tb-bold.svg +3 -1
- novelwriter/assets/icons/typicons_dark/nw_tb-italic-md.svg +4 -0
- novelwriter/assets/icons/typicons_dark/nw_tb-italic.svg +3 -1
- novelwriter/assets/icons/typicons_dark/nw_tb-strike-md.svg +4 -0
- novelwriter/assets/icons/typicons_dark/nw_tb-strike.svg +3 -1
- novelwriter/assets/icons/typicons_dark/nw_tb-subscript.svg +4 -2
- novelwriter/assets/icons/typicons_dark/nw_tb-superscript.svg +4 -2
- novelwriter/assets/icons/typicons_dark/nw_tb-underline.svg +4 -2
- novelwriter/assets/icons/typicons_dark/typ_document-add.svg +4 -0
- novelwriter/assets/icons/typicons_dark/typ_document.svg +4 -0
- novelwriter/assets/icons/typicons_dark/typ_th-dot-more.svg +4 -0
- novelwriter/assets/icons/typicons_dark/typ_th-list.svg +9 -0
- novelwriter/assets/icons/typicons_light/icons.conf +11 -2
- novelwriter/assets/icons/typicons_light/mixed_document-new.svg +6 -0
- novelwriter/assets/icons/typicons_light/mixed_import.svg +5 -0
- novelwriter/assets/icons/typicons_light/nw_tb-bold-md.svg +4 -0
- novelwriter/assets/icons/typicons_light/nw_tb-bold.svg +3 -1
- novelwriter/assets/icons/typicons_light/nw_tb-italic-md.svg +4 -0
- novelwriter/assets/icons/typicons_light/nw_tb-italic.svg +3 -1
- novelwriter/assets/icons/typicons_light/nw_tb-strike-md.svg +4 -0
- novelwriter/assets/icons/typicons_light/nw_tb-strike.svg +3 -1
- novelwriter/assets/icons/typicons_light/nw_tb-subscript.svg +4 -2
- novelwriter/assets/icons/typicons_light/nw_tb-superscript.svg +4 -2
- novelwriter/assets/icons/typicons_light/nw_tb-underline.svg +4 -2
- novelwriter/assets/icons/typicons_light/typ_document-add.svg +4 -0
- novelwriter/assets/icons/typicons_light/typ_document.svg +4 -0
- novelwriter/assets/icons/typicons_light/typ_th-dot-more.svg +4 -0
- novelwriter/assets/icons/typicons_light/typ_th-list.svg +9 -0
- novelwriter/assets/images/novelwriter-text-dark.svg +4 -0
- novelwriter/assets/images/novelwriter-text-light.svg +4 -0
- novelwriter/assets/images/welcome-dark.jpg +0 -0
- novelwriter/assets/images/welcome-light.jpg +0 -0
- novelwriter/assets/manual.pdf +0 -0
- novelwriter/assets/sample.zip +0 -0
- novelwriter/assets/syntax/cyberpunk_night.conf +26 -0
- novelwriter/assets/syntax/default_dark.conf +1 -0
- novelwriter/assets/syntax/default_light.conf +1 -0
- novelwriter/assets/syntax/grey_dark.conf +1 -0
- novelwriter/assets/syntax/grey_light.conf +1 -0
- novelwriter/assets/syntax/light_owl.conf +1 -0
- novelwriter/assets/syntax/night_owl.conf +1 -0
- novelwriter/assets/syntax/solarized_dark.conf +1 -0
- novelwriter/assets/syntax/solarized_light.conf +1 -0
- novelwriter/assets/syntax/tango.conf +23 -0
- novelwriter/assets/syntax/tomorrow.conf +1 -0
- novelwriter/assets/syntax/tomorrow_night.conf +1 -0
- novelwriter/assets/syntax/tomorrow_night_blue.conf +1 -0
- novelwriter/assets/syntax/tomorrow_night_bright.conf +1 -0
- novelwriter/assets/syntax/tomorrow_night_eighties.conf +1 -0
- novelwriter/assets/text/credits_en.htm +4 -2
- novelwriter/assets/themes/cyberpunk_night.conf +29 -0
- novelwriter/assets/themes/default_dark.conf +2 -2
- novelwriter/assets/themes/default_light.conf +2 -2
- novelwriter/common.py +64 -66
- novelwriter/config.py +39 -44
- novelwriter/constants.py +39 -17
- novelwriter/core/buildsettings.py +8 -8
- novelwriter/core/coretools.py +198 -157
- novelwriter/core/docbuild.py +7 -4
- novelwriter/core/document.py +7 -7
- novelwriter/core/index.py +90 -57
- novelwriter/core/item.py +23 -5
- novelwriter/core/options.py +11 -10
- novelwriter/core/project.py +73 -47
- novelwriter/core/projectdata.py +3 -16
- novelwriter/core/projectxml.py +14 -42
- novelwriter/core/sessions.py +4 -3
- novelwriter/core/spellcheck.py +6 -4
- novelwriter/core/status.py +5 -4
- novelwriter/core/storage.py +183 -141
- novelwriter/core/tohtml.py +6 -4
- novelwriter/core/tokenizer.py +110 -83
- novelwriter/core/tomd.py +2 -2
- novelwriter/core/toodt.py +41 -31
- novelwriter/core/tree.py +5 -4
- novelwriter/dialogs/about.py +88 -179
- novelwriter/dialogs/docmerge.py +30 -20
- novelwriter/dialogs/docsplit.py +33 -22
- novelwriter/dialogs/editlabel.py +20 -8
- novelwriter/dialogs/preferences.py +562 -725
- novelwriter/dialogs/{projsettings.py → projectsettings.py} +301 -270
- novelwriter/dialogs/quotes.py +47 -36
- novelwriter/dialogs/wordlist.py +128 -59
- novelwriter/enum.py +25 -22
- novelwriter/error.py +2 -2
- novelwriter/extensions/circularprogress.py +12 -12
- novelwriter/extensions/configlayout.py +185 -146
- novelwriter/extensions/{wheeleventfilter.py → eventfilters.py} +15 -5
- novelwriter/extensions/modified.py +81 -0
- novelwriter/extensions/novelselector.py +27 -13
- novelwriter/extensions/pagedsidebar.py +15 -20
- novelwriter/extensions/simpleprogress.py +8 -9
- novelwriter/extensions/statusled.py +9 -9
- novelwriter/extensions/switch.py +32 -64
- novelwriter/extensions/switchbox.py +2 -7
- novelwriter/extensions/versioninfo.py +153 -0
- novelwriter/gui/doceditor.py +250 -214
- novelwriter/gui/dochighlight.py +66 -94
- novelwriter/gui/docviewer.py +71 -98
- novelwriter/gui/docviewerpanel.py +140 -47
- novelwriter/gui/editordocument.py +3 -3
- novelwriter/gui/itemdetails.py +9 -9
- novelwriter/gui/mainmenu.py +47 -47
- novelwriter/gui/noveltree.py +53 -61
- novelwriter/gui/outline.py +100 -76
- novelwriter/gui/projtree.py +246 -112
- novelwriter/gui/sidebar.py +9 -8
- novelwriter/gui/statusbar.py +49 -7
- novelwriter/gui/theme.py +74 -76
- novelwriter/guimain.py +175 -330
- novelwriter/shared.py +68 -30
- novelwriter/tools/dictionaries.py +7 -8
- novelwriter/tools/lipsum.py +34 -28
- novelwriter/tools/manusbuild.py +3 -4
- novelwriter/tools/manuscript.py +25 -32
- novelwriter/tools/manussettings.py +194 -225
- novelwriter/tools/noveldetails.py +525 -0
- novelwriter/tools/welcome.py +819 -0
- novelwriter/tools/writingstats.py +26 -13
- novelWriter-2.2rc1.dist-info/entry_points.txt +0 -5
- novelwriter/assets/icons/typicons_dark/nw_tb-markdown.svg +0 -8
- novelwriter/assets/icons/typicons_dark/nw_tb-shortcode.svg +0 -8
- novelwriter/assets/icons/typicons_light/nw_tb-markdown.svg +0 -8
- novelwriter/assets/icons/typicons_light/nw_tb-shortcode.svg +0 -8
- novelwriter/assets/images/wizard-back.jpg +0 -0
- novelwriter/assets/text/gplv3_en.htm +0 -641
- novelwriter/assets/text/release_notes.htm +0 -17
- novelwriter/dialogs/projdetails.py +0 -525
- novelwriter/dialogs/projload.py +0 -298
- novelwriter/dialogs/updates.py +0 -182
- novelwriter/extensions/pageddialog.py +0 -130
- novelwriter/tools/projwizard.py +0 -478
- {novelWriter-2.2rc1.dist-info → novelWriter-2.3.dist-info}/LICENSE.md +0 -0
- {novelWriter-2.2rc1.dist-info → novelWriter-2.3.dist-info}/top_level.txt +0 -0
novelwriter/gui/projtree.py
CHANGED
@@ -6,9 +6,10 @@ File History:
|
|
6
6
|
Created: 2018-09-29 [0.0.1] GuiProjectTree
|
7
7
|
Created: 2022-06-06 [2.0rc1] GuiProjectView
|
8
8
|
Created: 2022-06-06 [2.0rc1] GuiProjectToolBar
|
9
|
+
Created: 2023-11-22 [2.2rc1] _TreeContextMenu
|
9
10
|
|
10
11
|
This file is a part of novelWriter
|
11
|
-
Copyright 2018–
|
12
|
+
Copyright 2018–2024, Veronica Berglyd Olsen
|
12
13
|
|
13
14
|
This program is free software: you can redistribute it and/or modify
|
14
15
|
it under the terms of the GNU General Public License as published by
|
@@ -31,15 +32,18 @@ from enum import Enum
|
|
31
32
|
from time import time
|
32
33
|
from typing import TYPE_CHECKING
|
33
34
|
|
34
|
-
from PyQt5.QtGui import
|
35
|
+
from PyQt5.QtGui import (
|
36
|
+
QDragEnterEvent, QDragMoveEvent, QDropEvent, QIcon, QMouseEvent, QPalette
|
37
|
+
)
|
35
38
|
from PyQt5.QtCore import QPoint, QTimer, Qt, QSize, pyqtSignal, pyqtSlot
|
36
39
|
from PyQt5.QtWidgets import (
|
37
|
-
QAbstractItemView, QDialog, QFrame, QHBoxLayout, QHeaderView,
|
38
|
-
QMenu, QShortcut, QSizePolicy, QToolButton, QTreeWidget,
|
39
|
-
QVBoxLayout, QWidget
|
40
|
+
QAbstractItemView, QAction, QDialog, QFrame, QHBoxLayout, QHeaderView,
|
41
|
+
QLabel, QMenu, QShortcut, QSizePolicy, QToolButton, QTreeWidget,
|
42
|
+
QTreeWidgetItem, QVBoxLayout, QWidget
|
40
43
|
)
|
41
44
|
|
42
45
|
from novelwriter import CONFIG, SHARED
|
46
|
+
from novelwriter.enum import nwDocMode, nwItemType, nwItemClass, nwItemLayout
|
43
47
|
from novelwriter.common import minmax
|
44
48
|
from novelwriter.constants import nwHeaders, nwUnicode, trConst, nwLabels
|
45
49
|
from novelwriter.core.item import NWItem
|
@@ -47,10 +51,7 @@ from novelwriter.core.coretools import DocDuplicator, DocMerger, DocSplitter
|
|
47
51
|
from novelwriter.dialogs.docmerge import GuiDocMerge
|
48
52
|
from novelwriter.dialogs.docsplit import GuiDocSplit
|
49
53
|
from novelwriter.dialogs.editlabel import GuiEditLabel
|
50
|
-
from novelwriter.dialogs.
|
51
|
-
from novelwriter.enum import (
|
52
|
-
nwDocMode, nwItemType, nwItemClass, nwItemLayout, nwWidget
|
53
|
-
)
|
54
|
+
from novelwriter.dialogs.projectsettings import GuiProjectSettings
|
54
55
|
|
55
56
|
if TYPE_CHECKING: # pragma: no cover
|
56
57
|
from novelwriter.guimain import GuiMain
|
@@ -132,7 +133,9 @@ class GuiProjectView(QWidget):
|
|
132
133
|
self.keyContext.activated.connect(lambda: self.projTree.openContextOnSelected())
|
133
134
|
|
134
135
|
# Signals
|
135
|
-
self.selectedItemChanged.connect(self.projBar.
|
136
|
+
self.selectedItemChanged.connect(self.projBar.treeSelectionChanged)
|
137
|
+
self.projTree.itemRefreshed.connect(self.projBar.treeItemRefreshed)
|
138
|
+
self.projBar.newDocumentFromTemplate.connect(self.createFileFromTemplate)
|
136
139
|
|
137
140
|
# Function Mappings
|
138
141
|
self.emptyTrash = self.projTree.emptyTrash
|
@@ -158,7 +161,7 @@ class GuiProjectView(QWidget):
|
|
158
161
|
self.projTree.initSettings()
|
159
162
|
return
|
160
163
|
|
161
|
-
def
|
164
|
+
def closeProjectTasks(self) -> None:
|
162
165
|
"""Clear project-related GUI content."""
|
163
166
|
self.projBar.clearContent()
|
164
167
|
self.projBar.setEnabled(False)
|
@@ -167,7 +170,7 @@ class GuiProjectView(QWidget):
|
|
167
170
|
|
168
171
|
def openProjectTasks(self) -> None:
|
169
172
|
"""Run open project tasks."""
|
170
|
-
self.projBar.
|
173
|
+
self.projBar.buildQuickLinksMenu()
|
171
174
|
self.projBar.setEnabled(True)
|
172
175
|
return
|
173
176
|
|
@@ -213,10 +216,17 @@ class GuiProjectView(QWidget):
|
|
213
216
|
|
214
217
|
@pyqtSlot(str)
|
215
218
|
def updateItemValues(self, tHandle: str) -> None:
|
216
|
-
"""Update tree item"""
|
219
|
+
"""Update tree item."""
|
217
220
|
self.projTree.setTreeItemValues(tHandle)
|
218
221
|
return
|
219
222
|
|
223
|
+
@pyqtSlot(str)
|
224
|
+
def createFileFromTemplate(self, tHandle: str) -> None:
|
225
|
+
"""Create a new document from a template."""
|
226
|
+
logger.debug("Template selected: '%s'", tHandle)
|
227
|
+
self.projTree.newTreeItem(nwItemType.FILE, copyDoc=tHandle)
|
228
|
+
return
|
229
|
+
|
220
230
|
@pyqtSlot(str, int, int, int)
|
221
231
|
def updateCounts(self, tHandle: str, cCount: int, wCount: int, pCount: int) -> None:
|
222
232
|
"""Slot for updating the word count of a specific item."""
|
@@ -226,8 +236,8 @@ class GuiProjectView(QWidget):
|
|
226
236
|
|
227
237
|
@pyqtSlot(str)
|
228
238
|
def updateRootItem(self, tHandle: str) -> None:
|
229
|
-
"""
|
230
|
-
self.projBar.
|
239
|
+
"""Process root item changes."""
|
240
|
+
self.projBar.buildQuickLinksMenu()
|
231
241
|
return
|
232
242
|
|
233
243
|
# END Class GuiProjectView
|
@@ -235,6 +245,8 @@ class GuiProjectView(QWidget):
|
|
235
245
|
|
236
246
|
class GuiProjectToolBar(QWidget):
|
237
247
|
|
248
|
+
newDocumentFromTemplate = pyqtSignal(str)
|
249
|
+
|
238
250
|
def __init__(self, projView: GuiProjectView) -> None:
|
239
251
|
super().__init__(parent=projView)
|
240
252
|
|
@@ -304,6 +316,11 @@ class GuiProjectToolBar(QWidget):
|
|
304
316
|
lambda: self.projTree.newTreeItem(nwItemType.FOLDER)
|
305
317
|
)
|
306
318
|
|
319
|
+
self.mTemplates = _UpdatableMenu(self.mAdd)
|
320
|
+
self.mTemplates.setActionsVisible(False)
|
321
|
+
self.mTemplates.menuItemTriggered.connect(lambda h: self.newDocumentFromTemplate.emit(h))
|
322
|
+
self.mAdd.addMenu(self.mTemplates)
|
323
|
+
|
307
324
|
self.mAddRoot = self.mAdd.addMenu(trConst(nwLabels.ITEM_DESCRIPTION["root"]))
|
308
325
|
self._buildRootMenu()
|
309
326
|
|
@@ -384,7 +401,7 @@ class GuiProjectToolBar(QWidget):
|
|
384
401
|
self.tbAdd.setIcon(SHARED.theme.getIcon("add"))
|
385
402
|
self.tbMore.setIcon(SHARED.theme.getIcon("menu"))
|
386
403
|
|
387
|
-
self.
|
404
|
+
self.buildQuickLinksMenu()
|
388
405
|
self._buildRootMenu()
|
389
406
|
|
390
407
|
return
|
@@ -392,21 +409,48 @@ class GuiProjectToolBar(QWidget):
|
|
392
409
|
def clearContent(self) -> None:
|
393
410
|
"""Clear dynamic content on the tool bar."""
|
394
411
|
self.mQuick.clear()
|
412
|
+
self.mTemplates.clearMenu()
|
395
413
|
return
|
396
414
|
|
397
|
-
def
|
415
|
+
def buildQuickLinksMenu(self) -> None:
|
398
416
|
"""Build the quick link menu."""
|
399
417
|
logger.debug("Rebuilding quick links menu")
|
400
418
|
self.mQuick.clear()
|
401
|
-
for
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
lambda
|
419
|
+
for tHandle, nwItem in SHARED.project.tree.iterRoots(None):
|
420
|
+
action = self.mQuick.addAction(nwItem.itemName)
|
421
|
+
action.setData(tHandle)
|
422
|
+
action.setIcon(SHARED.theme.getIcon(nwLabels.CLASS_ICON[nwItem.itemClass]))
|
423
|
+
action.triggered.connect(
|
424
|
+
lambda _, tHandle=tHandle: self.projView.setSelectedHandle(tHandle, doScroll=True)
|
407
425
|
)
|
408
426
|
return
|
409
427
|
|
428
|
+
##
|
429
|
+
# Public Slots
|
430
|
+
##
|
431
|
+
|
432
|
+
@pyqtSlot(str, NWItem, QIcon)
|
433
|
+
def treeItemRefreshed(self, tHandle: str, nwItem: NWItem, icon: QIcon) -> None:
|
434
|
+
"""Process change in tree items to update menu content."""
|
435
|
+
if nwItem.isTemplateFile() and nwItem.isActive:
|
436
|
+
self.mTemplates.addUpdate(tHandle, nwItem.itemName, icon)
|
437
|
+
elif tHandle in self.mTemplates:
|
438
|
+
self.mTemplates.remove(tHandle)
|
439
|
+
return
|
440
|
+
|
441
|
+
@pyqtSlot(str)
|
442
|
+
def treeSelectionChanged(self, tHandle: str) -> None:
|
443
|
+
"""Toggle the visibility of the new item entries for novel
|
444
|
+
documents. They should only be visible if novel documents can
|
445
|
+
actually be added.
|
446
|
+
"""
|
447
|
+
nwItem = SHARED.project.tree[tHandle]
|
448
|
+
allowDoc = isinstance(nwItem, NWItem) and nwItem.documentAllowed()
|
449
|
+
self.aAddEmpty.setVisible(allowDoc)
|
450
|
+
self.aAddChap.setVisible(allowDoc)
|
451
|
+
self.aAddScene.setVisible(allowDoc)
|
452
|
+
return
|
453
|
+
|
410
454
|
##
|
411
455
|
# Internal Functions
|
412
456
|
##
|
@@ -422,7 +466,6 @@ class GuiProjectToolBar(QWidget):
|
|
422
466
|
|
423
467
|
self.mAddRoot.clear()
|
424
468
|
addClass(nwItemClass.NOVEL)
|
425
|
-
addClass(nwItemClass.ARCHIVE)
|
426
469
|
self.mAddRoot.addSeparator()
|
427
470
|
addClass(nwItemClass.PLOT)
|
428
471
|
addClass(nwItemClass.CHARACTER)
|
@@ -431,26 +474,12 @@ class GuiProjectToolBar(QWidget):
|
|
431
474
|
addClass(nwItemClass.OBJECT)
|
432
475
|
addClass(nwItemClass.ENTITY)
|
433
476
|
addClass(nwItemClass.CUSTOM)
|
477
|
+
self.mAddRoot.addSeparator()
|
478
|
+
addClass(nwItemClass.ARCHIVE)
|
479
|
+
addClass(nwItemClass.TEMPLATE)
|
434
480
|
|
435
481
|
return
|
436
482
|
|
437
|
-
##
|
438
|
-
# Private Slots
|
439
|
-
##
|
440
|
-
|
441
|
-
@pyqtSlot(str)
|
442
|
-
def _treeSelectionChanged(self, tHandle: str) -> None:
|
443
|
-
"""Toggle the visibility of the new item entries for novel
|
444
|
-
documents. They should only be visible if novel documents can
|
445
|
-
actually be added.
|
446
|
-
"""
|
447
|
-
nwItem = SHARED.project.tree[tHandle]
|
448
|
-
allowDoc = isinstance(nwItem, NWItem) and nwItem.documentAllowed()
|
449
|
-
self.aAddEmpty.setVisible(allowDoc)
|
450
|
-
self.aAddChap.setVisible(allowDoc)
|
451
|
-
self.aAddScene.setVisible(allowDoc)
|
452
|
-
return
|
453
|
-
|
454
483
|
# END Class GuiProjectToolBar
|
455
484
|
|
456
485
|
|
@@ -465,6 +494,8 @@ class GuiProjectTree(QTreeWidget):
|
|
465
494
|
D_HANDLE = Qt.ItemDataRole.UserRole
|
466
495
|
D_WORDS = Qt.ItemDataRole.UserRole + 1
|
467
496
|
|
497
|
+
itemRefreshed = pyqtSignal(str, NWItem, QIcon)
|
498
|
+
|
468
499
|
def __init__(self, projView: GuiProjectView) -> None:
|
469
500
|
super().__init__(parent=projView)
|
470
501
|
|
@@ -474,10 +505,15 @@ class GuiProjectTree(QTreeWidget):
|
|
474
505
|
self.mainGui = projView.mainGui
|
475
506
|
|
476
507
|
# Internal Variables
|
477
|
-
self._treeMap = {}
|
508
|
+
self._treeMap: dict[str, QTreeWidgetItem] = {}
|
478
509
|
self._timeChanged = 0.0
|
479
510
|
self._popAlert = None
|
480
511
|
|
512
|
+
# Cached Translations
|
513
|
+
self.trActive = self.tr("Active")
|
514
|
+
self.trInactive = self.tr("Inactive")
|
515
|
+
self.trPermDelete = self.tr("Permanently delete {0} file(s) from Trash?")
|
516
|
+
|
481
517
|
# Build GUI
|
482
518
|
# =========
|
483
519
|
|
@@ -524,10 +560,6 @@ class GuiProjectTree(QTreeWidget):
|
|
524
560
|
trRoot = self.invisibleRootItem()
|
525
561
|
trRoot.setFlags(trRoot.flags() ^ Qt.ItemFlag.ItemIsDropEnabled)
|
526
562
|
|
527
|
-
# Cached values
|
528
|
-
self._lblActive = self.tr("Active")
|
529
|
-
self._lblInactive = self.tr("Inactive")
|
530
|
-
|
531
563
|
# Set selection options
|
532
564
|
self.setSelectionMode(QAbstractItemView.SelectionMode.ExtendedSelection)
|
533
565
|
self.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows)
|
@@ -588,7 +620,7 @@ class GuiProjectTree(QTreeWidget):
|
|
588
620
|
return False
|
589
621
|
|
590
622
|
def newTreeItem(self, itemType: nwItemType, itemClass: nwItemClass | None = None,
|
591
|
-
hLevel: int = 1, isNote: bool = False) -> bool:
|
623
|
+
hLevel: int = 1, isNote: bool = False, copyDoc: str | None = None) -> bool:
|
592
624
|
"""Add new item to the tree, with a given itemType (and
|
593
625
|
itemClass if Root), and attach it to the selected handle. Also
|
594
626
|
make sure the item is added in a place it can be added, and that
|
@@ -628,7 +660,10 @@ class GuiProjectTree(QTreeWidget):
|
|
628
660
|
# Set default label and determine if new item is to be added
|
629
661
|
# as child or sibling to the selected item
|
630
662
|
if itemType == nwItemType.FILE:
|
631
|
-
if
|
663
|
+
if copyDoc and (cItem := SHARED.project.tree[copyDoc]):
|
664
|
+
newLabel = cItem.itemName
|
665
|
+
asChild = sIsParent and pItem.isDocumentLayout()
|
666
|
+
elif isNote:
|
632
667
|
newLabel = self.tr("New Note")
|
633
668
|
asChild = sIsParent
|
634
669
|
elif hLevel == 2:
|
@@ -676,12 +711,14 @@ class GuiProjectTree(QTreeWidget):
|
|
676
711
|
return True
|
677
712
|
|
678
713
|
# Handle new file creation
|
679
|
-
if itemType == nwItemType.FILE and
|
714
|
+
if itemType == nwItemType.FILE and copyDoc:
|
715
|
+
SHARED.project.copyFileContent(tHandle, copyDoc)
|
716
|
+
elif itemType == nwItemType.FILE and hLevel > 0:
|
680
717
|
SHARED.project.writeNewFile(tHandle, hLevel, not isNote)
|
681
718
|
|
682
719
|
# Add the new item to the project tree
|
683
720
|
self.revealNewTreeItem(tHandle, nHandle=nHandle, wordCount=True)
|
684
|
-
self.
|
721
|
+
self.projView.setTreeFocus() # See issue #1376
|
685
722
|
|
686
723
|
return True
|
687
724
|
|
@@ -771,8 +808,7 @@ class GuiProjectTree(QTreeWidget):
|
|
771
808
|
|
772
809
|
def renameTreeItem(self, tHandle: str, name: str = "") -> None:
|
773
810
|
"""Open a dialog to edit the label of an item."""
|
774
|
-
tItem
|
775
|
-
if tItem:
|
811
|
+
if tItem := SHARED.project.tree[tHandle]:
|
776
812
|
newLabel, dlgOk = GuiEditLabel.getLabel(self, text=name or tItem.itemName)
|
777
813
|
if dlgOk:
|
778
814
|
tItem.setName(newLabel)
|
@@ -786,24 +822,24 @@ class GuiProjectTree(QTreeWidget):
|
|
786
822
|
project structure, and must be called before any code that
|
787
823
|
depends on this order to be up to date.
|
788
824
|
"""
|
789
|
-
|
825
|
+
items = []
|
790
826
|
for i in range(self.topLevelItemCount()):
|
791
827
|
item = self.topLevelItem(i)
|
792
828
|
if isinstance(item, QTreeWidgetItem):
|
793
|
-
|
829
|
+
items = self._scanChildren(items, item, i)
|
794
830
|
logger.debug("Saving project tree item order")
|
795
|
-
SHARED.project.setTreeOrder(
|
831
|
+
SHARED.project.setTreeOrder(items)
|
796
832
|
return
|
797
833
|
|
798
834
|
def getTreeFromHandle(self, tHandle: str) -> list[str]:
|
799
835
|
"""Recursively return all the child items starting from a given
|
800
836
|
item handle.
|
801
837
|
"""
|
802
|
-
|
803
|
-
|
804
|
-
if
|
805
|
-
|
806
|
-
return
|
838
|
+
result = []
|
839
|
+
tIten = self._getTreeItem(tHandle)
|
840
|
+
if tIten is not None:
|
841
|
+
result = self._scanChildren(result, tIten, 0)
|
842
|
+
return result
|
807
843
|
|
808
844
|
def requestDeleteItem(self, tHandle: str | None = None) -> bool:
|
809
845
|
"""Request an item deleted from the project tree. This function
|
@@ -858,19 +894,16 @@ class GuiProjectTree(QTreeWidget):
|
|
858
894
|
SHARED.info(self.tr("There is currently no Trash folder in this project."))
|
859
895
|
return False
|
860
896
|
|
861
|
-
|
862
|
-
if trashHandle in
|
863
|
-
|
897
|
+
trashItems = self.getTreeFromHandle(trashHandle)
|
898
|
+
if trashHandle in trashItems:
|
899
|
+
trashItems.remove(trashHandle)
|
864
900
|
|
865
|
-
nTrash = len(
|
901
|
+
nTrash = len(trashItems)
|
866
902
|
if nTrash == 0:
|
867
903
|
SHARED.info(self.tr("The Trash folder is already empty."))
|
868
904
|
return False
|
869
905
|
|
870
|
-
|
871
|
-
self.tr("Permanently delete {0} file(s) from Trash?").format(nTrash)
|
872
|
-
)
|
873
|
-
if not msgYes:
|
906
|
+
if not SHARED.question(self.trPermDelete.format(nTrash)):
|
874
907
|
logger.info("Action cancelled by user")
|
875
908
|
return False
|
876
909
|
|
@@ -1017,7 +1050,7 @@ class GuiProjectTree(QTreeWidget):
|
|
1017
1050
|
|
1018
1051
|
if nwItem.isFileType():
|
1019
1052
|
iconName = "checked" if nwItem.isActive else "unchecked"
|
1020
|
-
toolTip = self.
|
1053
|
+
toolTip = self.trActive if nwItem.isActive else self.trInactive
|
1021
1054
|
trItem.setToolTip(self.C_ACTIVE, toolTip)
|
1022
1055
|
else:
|
1023
1056
|
iconName = "noncheckable"
|
@@ -1030,6 +1063,9 @@ class GuiProjectTree(QTreeWidget):
|
|
1030
1063
|
trFont.setUnderline(hLevel == "H1")
|
1031
1064
|
trItem.setFont(self.C_NAME, trFont)
|
1032
1065
|
|
1066
|
+
# Emit Refresh Signal
|
1067
|
+
self.itemRefreshed.emit(tHandle, nwItem, itemIcon)
|
1068
|
+
|
1033
1069
|
return
|
1034
1070
|
|
1035
1071
|
def propagateCount(self, tHandle: str, newCount: int, countChildren: bool = False) -> None:
|
@@ -1091,9 +1127,8 @@ class GuiProjectTree(QTreeWidget):
|
|
1091
1127
|
"""Get the currently selected handle. If multiple items are
|
1092
1128
|
selected, return the first.
|
1093
1129
|
"""
|
1094
|
-
|
1095
|
-
|
1096
|
-
return selItem[0].data(self.C_DATA, self.D_HANDLE)
|
1130
|
+
if items := self.selectedItems():
|
1131
|
+
return items[0].data(self.C_DATA, self.D_HANDLE)
|
1097
1132
|
return None
|
1098
1133
|
|
1099
1134
|
def setSelectedHandle(self, tHandle: str | None, doScroll: bool = False) -> bool:
|
@@ -1105,9 +1140,8 @@ class GuiProjectTree(QTreeWidget):
|
|
1105
1140
|
if tHandle in self._treeMap:
|
1106
1141
|
self.setCurrentItem(self._treeMap[tHandle])
|
1107
1142
|
|
1108
|
-
|
1109
|
-
|
1110
|
-
self.scrollTo(selIndex[0], QAbstractItemView.ScrollHint.PositionAtCenter)
|
1143
|
+
if (indexes := self.selectedIndexes()) and doScroll:
|
1144
|
+
self.scrollTo(indexes[0], QAbstractItemView.ScrollHint.PositionAtCenter)
|
1111
1145
|
|
1112
1146
|
return True
|
1113
1147
|
|
@@ -1122,10 +1156,8 @@ class GuiProjectTree(QTreeWidget):
|
|
1122
1156
|
|
1123
1157
|
def openContextOnSelected(self) -> bool:
|
1124
1158
|
"""Open the context menu on the current selected item."""
|
1125
|
-
|
1126
|
-
|
1127
|
-
pos = self.visualItemRect(selItem[0]).center()
|
1128
|
-
return self._openContextMenu(pos)
|
1159
|
+
if items := self.selectedItems():
|
1160
|
+
return self._openContextMenu(self.visualItemRect(items[0]).center())
|
1129
1161
|
return False
|
1130
1162
|
|
1131
1163
|
def changedSince(self, checkTime: float) -> bool:
|
@@ -1359,8 +1391,7 @@ class GuiProjectTree(QTreeWidget):
|
|
1359
1391
|
not including) a given item.
|
1360
1392
|
"""
|
1361
1393
|
if isinstance(trItem, QTreeWidgetItem):
|
1362
|
-
|
1363
|
-
for i in range(chCount):
|
1394
|
+
for i in range(trItem.childCount()):
|
1364
1395
|
chItem = trItem.child(i)
|
1365
1396
|
chItem.setExpanded(isExpanded)
|
1366
1397
|
self._recursiveSetExpanded(chItem, isExpanded)
|
@@ -1634,6 +1665,71 @@ class GuiProjectTree(QTreeWidget):
|
|
1634
1665
|
# END Class GuiProjectTree
|
1635
1666
|
|
1636
1667
|
|
1668
|
+
class _UpdatableMenu(QMenu):
|
1669
|
+
|
1670
|
+
menuItemTriggered = pyqtSignal(str)
|
1671
|
+
|
1672
|
+
def __init__(self, parent: QWidget) -> None:
|
1673
|
+
super().__init__(parent=parent)
|
1674
|
+
self._map: dict[str, QAction] = {}
|
1675
|
+
self.setTitle(self.tr("From Template"))
|
1676
|
+
self.triggered.connect(self._actionTriggered)
|
1677
|
+
return
|
1678
|
+
|
1679
|
+
def __contains__(self, tHandle: str) -> bool:
|
1680
|
+
"""Look up a handle in the menu."""
|
1681
|
+
return tHandle in self._map
|
1682
|
+
|
1683
|
+
##
|
1684
|
+
# Methods
|
1685
|
+
##
|
1686
|
+
|
1687
|
+
def addUpdate(self, tHandle: str, name: str, icon: QIcon) -> None:
|
1688
|
+
"""Add or update a template item."""
|
1689
|
+
if tHandle in self._map:
|
1690
|
+
action = self._map[tHandle]
|
1691
|
+
action.setText(name)
|
1692
|
+
action.setIcon(icon)
|
1693
|
+
else:
|
1694
|
+
action = QAction(icon, name, self)
|
1695
|
+
action.setData(tHandle)
|
1696
|
+
self.addAction(action)
|
1697
|
+
self._map[tHandle] = action
|
1698
|
+
self.setActionsVisible(True)
|
1699
|
+
return
|
1700
|
+
|
1701
|
+
def remove(self, tHandle: str) -> None:
|
1702
|
+
"""Remove a template item."""
|
1703
|
+
if action := self._map.pop(tHandle, None):
|
1704
|
+
self.removeAction(action)
|
1705
|
+
if not self._map:
|
1706
|
+
self.setActionsVisible(False)
|
1707
|
+
return
|
1708
|
+
|
1709
|
+
def clearMenu(self) -> None:
|
1710
|
+
"""Clear all menu content."""
|
1711
|
+
self._map.clear()
|
1712
|
+
self.clear()
|
1713
|
+
return
|
1714
|
+
|
1715
|
+
def setActionsVisible(self, value: bool) -> None:
|
1716
|
+
"""Set the visibility of root action."""
|
1717
|
+
self.menuAction().setVisible(value)
|
1718
|
+
return
|
1719
|
+
|
1720
|
+
##
|
1721
|
+
# Private Slots
|
1722
|
+
##
|
1723
|
+
|
1724
|
+
@pyqtSlot(QAction)
|
1725
|
+
def _actionTriggered(self, action: QAction) -> None:
|
1726
|
+
"""Translate the menu trigger into an item trigger."""
|
1727
|
+
self.menuItemTriggered.emit(str(action.data()))
|
1728
|
+
return
|
1729
|
+
|
1730
|
+
# END Class _UpdatableMenu
|
1731
|
+
|
1732
|
+
|
1637
1733
|
class _TreeContextMenu(QMenu):
|
1638
1734
|
|
1639
1735
|
def __init__(self, projTree: GuiProjectTree, nwItem: NWItem) -> None:
|
@@ -1644,13 +1740,13 @@ class _TreeContextMenu(QMenu):
|
|
1644
1740
|
|
1645
1741
|
self._item = nwItem
|
1646
1742
|
self._handle = nwItem.itemHandle
|
1647
|
-
self._items: list[
|
1743
|
+
self._items: list[NWItem] = []
|
1648
1744
|
|
1649
1745
|
logger.debug("Ready: _TreeContextMenu")
|
1650
1746
|
|
1651
1747
|
return
|
1652
1748
|
|
1653
|
-
def __del__(self): # pragma: no cover
|
1749
|
+
def __del__(self) -> None: # pragma: no cover
|
1654
1750
|
logger.debug("Delete: _TreeContextMenu")
|
1655
1751
|
return
|
1656
1752
|
|
@@ -1675,10 +1771,15 @@ class _TreeContextMenu(QMenu):
|
|
1675
1771
|
self._docActions()
|
1676
1772
|
self.addSeparator()
|
1677
1773
|
|
1774
|
+
# Create New Items
|
1775
|
+
self._itemCreation()
|
1776
|
+
self.addSeparator()
|
1777
|
+
|
1678
1778
|
# Edit Item Settings
|
1679
|
-
|
1680
|
-
|
1779
|
+
action = self.addAction(self.tr("Rename"))
|
1780
|
+
action.triggered.connect(lambda: self.projTree.renameTreeItem(self._handle))
|
1681
1781
|
if isFile:
|
1782
|
+
self._itemHeader()
|
1682
1783
|
self._itemActive(False)
|
1683
1784
|
self._itemStatusImport(False)
|
1684
1785
|
|
@@ -1692,13 +1793,17 @@ class _TreeContextMenu(QMenu):
|
|
1692
1793
|
|
1693
1794
|
return
|
1694
1795
|
|
1695
|
-
def buildMultiSelectMenu(self,
|
1796
|
+
def buildMultiSelectMenu(self, handles: list[str]) -> None:
|
1696
1797
|
"""Build the multi-select menu."""
|
1697
|
-
self._items =
|
1798
|
+
self._items = []
|
1799
|
+
for tHandle in handles:
|
1800
|
+
if (tItem := SHARED.project.tree[tHandle]):
|
1801
|
+
self._items.append(tItem)
|
1802
|
+
|
1698
1803
|
self._itemActive(True)
|
1699
1804
|
self._itemStatusImport(True)
|
1700
1805
|
self.addSeparator()
|
1701
|
-
self.
|
1806
|
+
self._multiMoveToTrash()
|
1702
1807
|
return
|
1703
1808
|
|
1704
1809
|
##
|
@@ -1717,13 +1822,32 @@ class _TreeContextMenu(QMenu):
|
|
1717
1822
|
)
|
1718
1823
|
return
|
1719
1824
|
|
1825
|
+
def _itemCreation(self) -> None:
|
1826
|
+
"""Add create item actions."""
|
1827
|
+
menu = self.addMenu(self.tr("Create New ..."))
|
1828
|
+
menu.addAction(self.projView.projBar.aAddEmpty)
|
1829
|
+
menu.addAction(self.projView.projBar.aAddChap)
|
1830
|
+
menu.addAction(self.projView.projBar.aAddScene)
|
1831
|
+
menu.addAction(self.projView.projBar.aAddNote)
|
1832
|
+
menu.addAction(self.projView.projBar.aAddFolder)
|
1833
|
+
return
|
1834
|
+
|
1835
|
+
def _itemHeader(self) -> None:
|
1836
|
+
"""Check if there is a header that can be used for rename."""
|
1837
|
+
if hItem := SHARED.project.index.getItemHeader(self._handle, "T0001"):
|
1838
|
+
action = self.addAction(self.tr("Rename to Heading"))
|
1839
|
+
action.triggered.connect(
|
1840
|
+
lambda: self.projTree.renameTreeItem(self._handle, hItem.title)
|
1841
|
+
)
|
1842
|
+
return
|
1843
|
+
|
1720
1844
|
def _itemActive(self, multi: bool) -> None:
|
1721
1845
|
"""Add Active/Inactive actions."""
|
1722
1846
|
if multi:
|
1723
1847
|
mSub = self.addMenu(self.tr("Set Active to ..."))
|
1724
|
-
aOne = mSub.addAction(SHARED.theme.getIcon("checked"), self.
|
1848
|
+
aOne = mSub.addAction(SHARED.theme.getIcon("checked"), self.projTree.trActive)
|
1725
1849
|
aOne.triggered.connect(lambda: self._iterItemActive(True))
|
1726
|
-
aTwo = mSub.addAction(SHARED.theme.getIcon("unchecked"), self.
|
1850
|
+
aTwo = mSub.addAction(SHARED.theme.getIcon("unchecked"), self.projTree.trInactive)
|
1727
1851
|
aTwo.triggered.connect(lambda: self._iterItemActive(False))
|
1728
1852
|
else:
|
1729
1853
|
action = self.addAction(self.tr("Toggle Active"))
|
@@ -1747,7 +1871,7 @@ class _TreeContextMenu(QMenu):
|
|
1747
1871
|
menu.addSeparator()
|
1748
1872
|
action = menu.addAction(self.tr("Manage Labels ..."))
|
1749
1873
|
action.triggered.connect(
|
1750
|
-
lambda: self.projView.projectSettingsRequest.emit(GuiProjectSettings.
|
1874
|
+
lambda: self.projView.projectSettingsRequest.emit(GuiProjectSettings.PAGE_STATUS)
|
1751
1875
|
)
|
1752
1876
|
else:
|
1753
1877
|
menu = self.addMenu(self.tr("Set Importance to ..."))
|
@@ -1764,13 +1888,13 @@ class _TreeContextMenu(QMenu):
|
|
1764
1888
|
menu.addSeparator()
|
1765
1889
|
action = menu.addAction(self.tr("Manage Labels ..."))
|
1766
1890
|
action.triggered.connect(
|
1767
|
-
lambda: self.projView.projectSettingsRequest.emit(GuiProjectSettings.
|
1891
|
+
lambda: self.projView.projectSettingsRequest.emit(GuiProjectSettings.PAGE_IMPORT)
|
1768
1892
|
)
|
1769
1893
|
return
|
1770
1894
|
|
1771
1895
|
def _itemTransform(self, isFile: bool, isFolder: bool, hasChild: bool) -> None:
|
1772
1896
|
"""Add actions for the Transform menu."""
|
1773
|
-
menu = self.addMenu(self.tr("Transform"))
|
1897
|
+
menu = self.addMenu(self.tr("Transform ..."))
|
1774
1898
|
|
1775
1899
|
tree = self.projTree
|
1776
1900
|
tHandle = self._handle
|
@@ -1838,10 +1962,14 @@ class _TreeContextMenu(QMenu):
|
|
1838
1962
|
|
1839
1963
|
return
|
1840
1964
|
|
1841
|
-
def
|
1965
|
+
def _multiMoveToTrash(self) -> None:
|
1842
1966
|
"""Add move to Trash action."""
|
1843
|
-
|
1844
|
-
if
|
1967
|
+
areTrash = [i.itemClass == nwItemClass.TRASH for i in self._items]
|
1968
|
+
if all(areTrash):
|
1969
|
+
action = self.addAction(self.tr("Delete Permanently"))
|
1970
|
+
action.triggered.connect(self._iterPermDelete)
|
1971
|
+
elif not any(areTrash):
|
1972
|
+
action = self.addAction(self.tr("Move to Trash"))
|
1845
1973
|
action.triggered.connect(self._iterMoveToTrash)
|
1846
1974
|
return
|
1847
1975
|
|
@@ -1853,10 +1981,19 @@ class _TreeContextMenu(QMenu):
|
|
1853
1981
|
def _iterMoveToTrash(self) -> None:
|
1854
1982
|
"""Iterate through files and move them to Trash."""
|
1855
1983
|
if SHARED.question(self.tr("Move {0} items to Trash?").format(len(self._items))):
|
1856
|
-
for
|
1857
|
-
tItem
|
1858
|
-
|
1859
|
-
|
1984
|
+
for tItem in self._items:
|
1985
|
+
if tItem.isFileType() and tItem.itemClass != nwItemClass.TRASH:
|
1986
|
+
self.projTree.moveItemToTrash(tItem.itemHandle, askFirst=False, flush=False)
|
1987
|
+
self.projTree.saveTreeOrder()
|
1988
|
+
return
|
1989
|
+
|
1990
|
+
@pyqtSlot()
|
1991
|
+
def _iterPermDelete(self) -> None:
|
1992
|
+
"""Iterate through files and delete them."""
|
1993
|
+
if SHARED.question(self.projTree.trPermDelete.format(len(self._items))):
|
1994
|
+
for tItem in self._items:
|
1995
|
+
if tItem.isFileType() and tItem.itemClass == nwItemClass.TRASH:
|
1996
|
+
self.projTree.permDeleteItem(tItem.itemHandle, askFirst=False, flush=False)
|
1860
1997
|
self.projTree.saveTreeOrder()
|
1861
1998
|
return
|
1862
1999
|
|
@@ -1874,12 +2011,11 @@ class _TreeContextMenu(QMenu):
|
|
1874
2011
|
|
1875
2012
|
def _iterItemActive(self, isActive: bool) -> None:
|
1876
2013
|
"""Set the active status of multiple items."""
|
1877
|
-
for
|
1878
|
-
tItem = SHARED.project.tree[tHandle]
|
2014
|
+
for tItem in self._items:
|
1879
2015
|
if tItem and tItem.isFileType():
|
1880
2016
|
tItem.setActive(isActive)
|
1881
|
-
self.projTree.setTreeItemValues(
|
1882
|
-
self.projTree._alertTreeChange(
|
2017
|
+
self.projTree.setTreeItemValues(tItem.itemHandle)
|
2018
|
+
self.projTree._alertTreeChange(tItem.itemHandle, flush=False)
|
1883
2019
|
return
|
1884
2020
|
|
1885
2021
|
def _changeItemStatus(self, key: str) -> None:
|
@@ -1891,12 +2027,11 @@ class _TreeContextMenu(QMenu):
|
|
1891
2027
|
|
1892
2028
|
def _iterSetItemStatus(self, key: str) -> None:
|
1893
2029
|
"""Change the status value for multiple items."""
|
1894
|
-
for
|
1895
|
-
tItem = SHARED.project.tree[tHandle]
|
2030
|
+
for tItem in self._items:
|
1896
2031
|
if tItem and tItem.isNovelLike():
|
1897
2032
|
tItem.setStatus(key)
|
1898
|
-
self.projTree.setTreeItemValues(
|
1899
|
-
self.projTree._alertTreeChange(
|
2033
|
+
self.projTree.setTreeItemValues(tItem.itemHandle)
|
2034
|
+
self.projTree._alertTreeChange(tItem.itemHandle, flush=False)
|
1900
2035
|
return
|
1901
2036
|
|
1902
2037
|
def _changeItemImport(self, key: str) -> None:
|
@@ -1908,12 +2043,11 @@ class _TreeContextMenu(QMenu):
|
|
1908
2043
|
|
1909
2044
|
def _iterSetItemImport(self, key: str) -> None:
|
1910
2045
|
"""Change the status value for multiple items."""
|
1911
|
-
for
|
1912
|
-
tItem = SHARED.project.tree[tHandle]
|
2046
|
+
for tItem in self._items:
|
1913
2047
|
if tItem and not tItem.isNovelLike():
|
1914
2048
|
tItem.setImport(key)
|
1915
|
-
self.projTree.setTreeItemValues(
|
1916
|
-
self.projTree._alertTreeChange(
|
2049
|
+
self.projTree.setTreeItemValues(tItem.itemHandle)
|
2050
|
+
self.projTree._alertTreeChange(tItem.itemHandle, flush=False)
|
1917
2051
|
return
|
1918
2052
|
|
1919
2053
|
def _changeItemLayout(self, itemLayout: nwItemLayout) -> None:
|