novelWriter 2.6b1__py3-none-any.whl → 2.6b2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {novelWriter-2.6b1.dist-info → novelWriter-2.6b2.dist-info}/METADATA +3 -3
- {novelWriter-2.6b1.dist-info → novelWriter-2.6b2.dist-info}/RECORD +68 -52
- {novelWriter-2.6b1.dist-info → novelWriter-2.6b2.dist-info}/WHEEL +1 -1
- novelwriter/__init__.py +49 -10
- novelwriter/assets/i18n/nw_de_DE.qm +0 -0
- novelwriter/assets/i18n/nw_pt_BR.qm +0 -0
- novelwriter/assets/i18n/nw_ru_RU.qm +0 -0
- novelwriter/assets/i18n/project_de_DE.json +2 -2
- novelwriter/assets/i18n/project_ru_RU.json +11 -0
- novelwriter/assets/icons/typicons_dark/icons.conf +7 -0
- novelwriter/assets/icons/typicons_dark/mixed_margin-bottom.svg +6 -0
- novelwriter/assets/icons/typicons_dark/mixed_margin-left.svg +6 -0
- novelwriter/assets/icons/typicons_dark/mixed_margin-right.svg +6 -0
- novelwriter/assets/icons/typicons_dark/mixed_margin-top.svg +6 -0
- novelwriter/assets/icons/typicons_dark/mixed_size-height.svg +6 -0
- novelwriter/assets/icons/typicons_dark/mixed_size-width.svg +6 -0
- novelwriter/assets/icons/typicons_dark/nw_toolbar.svg +5 -0
- novelwriter/assets/icons/typicons_light/icons.conf +7 -0
- novelwriter/assets/icons/typicons_light/mixed_margin-bottom.svg +6 -0
- novelwriter/assets/icons/typicons_light/mixed_margin-left.svg +6 -0
- novelwriter/assets/icons/typicons_light/mixed_margin-right.svg +6 -0
- novelwriter/assets/icons/typicons_light/mixed_margin-top.svg +6 -0
- novelwriter/assets/icons/typicons_light/mixed_size-height.svg +6 -0
- novelwriter/assets/icons/typicons_light/mixed_size-width.svg +6 -0
- novelwriter/assets/icons/typicons_light/nw_toolbar.svg +5 -0
- novelwriter/assets/manual.pdf +0 -0
- novelwriter/assets/sample.zip +0 -0
- novelwriter/assets/text/credits_en.htm +1 -0
- novelwriter/common.py +37 -2
- novelwriter/config.py +15 -12
- novelwriter/constants.py +24 -9
- novelwriter/core/coretools.py +111 -125
- novelwriter/core/docbuild.py +3 -2
- novelwriter/core/index.py +9 -19
- novelwriter/core/item.py +39 -6
- novelwriter/core/itemmodel.py +518 -0
- novelwriter/core/project.py +67 -89
- novelwriter/core/status.py +7 -5
- novelwriter/core/tree.py +268 -287
- novelwriter/dialogs/docmerge.py +7 -17
- novelwriter/dialogs/preferences.py +3 -3
- novelwriter/dialogs/projectsettings.py +2 -2
- novelwriter/enum.py +7 -0
- novelwriter/extensions/configlayout.py +6 -4
- novelwriter/formats/todocx.py +34 -38
- novelwriter/formats/tohtml.py +14 -15
- novelwriter/formats/tokenizer.py +21 -17
- novelwriter/formats/toodt.py +53 -124
- novelwriter/formats/toqdoc.py +92 -44
- novelwriter/gui/doceditor.py +230 -219
- novelwriter/gui/docviewer.py +38 -9
- novelwriter/gui/docviewerpanel.py +14 -22
- novelwriter/gui/itemdetails.py +17 -24
- novelwriter/gui/mainmenu.py +13 -8
- novelwriter/gui/noveltree.py +12 -12
- novelwriter/gui/outline.py +10 -11
- novelwriter/gui/projtree.py +548 -1202
- novelwriter/gui/search.py +9 -10
- novelwriter/gui/theme.py +7 -3
- novelwriter/guimain.py +59 -43
- novelwriter/shared.py +52 -23
- novelwriter/text/patterns.py +17 -5
- novelwriter/tools/manusbuild.py +13 -11
- novelwriter/tools/manussettings.py +42 -52
- novelwriter/types.py +7 -1
- {novelWriter-2.6b1.dist-info → novelWriter-2.6b2.dist-info}/LICENSE.md +0 -0
- {novelWriter-2.6b1.dist-info → novelWriter-2.6b2.dist-info}/entry_points.txt +0 -0
- {novelWriter-2.6b1.dist-info → novelWriter-2.6b2.dist-info}/top_level.txt +0 -0
novelwriter/gui/docviewer.py
CHANGED
@@ -31,16 +31,19 @@ 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
|
34
|
+
from PyQt5.QtGui import (
|
35
|
+
QCursor, QDesktopServices, QDragEnterEvent, QDragMoveEvent, QDropEvent,
|
36
|
+
QMouseEvent, QPalette, QResizeEvent, QTextCursor
|
37
|
+
)
|
35
38
|
from PyQt5.QtWidgets import (
|
36
39
|
QAction, QApplication, QFrame, QHBoxLayout, QMenu, QTextBrowser,
|
37
40
|
QToolButton, QWidget
|
38
41
|
)
|
39
42
|
|
40
43
|
from novelwriter import CONFIG, SHARED
|
41
|
-
from novelwriter.common import qtLambda
|
42
|
-
from novelwriter.constants import nwStyles, nwUnicode
|
43
|
-
from novelwriter.enum import nwDocAction, nwDocMode, nwItemType
|
44
|
+
from novelwriter.common import decodeMimeHandles, qtLambda
|
45
|
+
from novelwriter.constants import nwConst, nwStyles, nwUnicode
|
46
|
+
from novelwriter.enum import nwChange, nwDocAction, nwDocMode, nwItemType
|
44
47
|
from novelwriter.error import logException
|
45
48
|
from novelwriter.extensions.configlayout import NColourLabel
|
46
49
|
from novelwriter.extensions.eventfilters import WheelEventFilter
|
@@ -216,7 +219,7 @@ class GuiDocViewer(QTextBrowser):
|
|
216
219
|
qDoc = ToQTextDocument(SHARED.project)
|
217
220
|
qDoc.setJustify(CONFIG.doJustify)
|
218
221
|
qDoc.setDialogHighlight(True)
|
219
|
-
qDoc.
|
222
|
+
qDoc.setTextFont(CONFIG.textFont)
|
220
223
|
qDoc.setTheme(self._docTheme)
|
221
224
|
qDoc.initDocument()
|
222
225
|
qDoc.setKeywords(True)
|
@@ -343,10 +346,10 @@ class GuiDocViewer(QTextBrowser):
|
|
343
346
|
# Public Slots
|
344
347
|
##
|
345
348
|
|
346
|
-
@pyqtSlot(str)
|
347
|
-
def
|
349
|
+
@pyqtSlot(str, Enum)
|
350
|
+
def onProjectItemChanged(self, tHandle: str, change: nwChange) -> None:
|
348
351
|
"""Update the header title bar if needed."""
|
349
|
-
if tHandle and
|
352
|
+
if tHandle == self._docHandle and change == nwChange.UPDATE:
|
350
353
|
self.docHeader.setHandle(tHandle)
|
351
354
|
self.updateDocMargins()
|
352
355
|
return
|
@@ -445,6 +448,32 @@ class GuiDocViewer(QTextBrowser):
|
|
445
448
|
super().mouseReleaseEvent(event)
|
446
449
|
return
|
447
450
|
|
451
|
+
def dragEnterEvent(self, event: QDragEnterEvent) -> None:
|
452
|
+
"""Overload drag enter event to handle dragged items."""
|
453
|
+
if event.mimeData().hasFormat(nwConst.MIME_HANDLE):
|
454
|
+
event.acceptProposedAction()
|
455
|
+
else:
|
456
|
+
super().dragEnterEvent(event)
|
457
|
+
return
|
458
|
+
|
459
|
+
def dragMoveEvent(self, event: QDragMoveEvent) -> None:
|
460
|
+
"""Overload drag move event to handle dragged items."""
|
461
|
+
if event.mimeData().hasFormat(nwConst.MIME_HANDLE):
|
462
|
+
event.acceptProposedAction()
|
463
|
+
else:
|
464
|
+
super().dragMoveEvent(event)
|
465
|
+
return
|
466
|
+
|
467
|
+
def dropEvent(self, event: QDropEvent) -> None:
|
468
|
+
"""Overload drop event to handle dragged items."""
|
469
|
+
if event.mimeData().hasFormat(nwConst.MIME_HANDLE):
|
470
|
+
if handles := decodeMimeHandles(event.mimeData()):
|
471
|
+
if SHARED.project.tree.checkType(handles[0], nwItemType.FILE):
|
472
|
+
self.openDocumentRequest.emit(handles[0], nwDocMode.VIEW, "", True)
|
473
|
+
else:
|
474
|
+
super().dropEvent(event)
|
475
|
+
return
|
476
|
+
|
448
477
|
##
|
449
478
|
# Internal Functions
|
450
479
|
##
|
@@ -777,7 +806,7 @@ class GuiDocViewHeader(QWidget):
|
|
777
806
|
|
778
807
|
if CONFIG.showFullPath:
|
779
808
|
self.itemTitle.setText(f" {nwUnicode.U_RSAQUO} ".join(reversed(
|
780
|
-
[name for name in SHARED.project.tree.
|
809
|
+
[name for name in SHARED.project.tree.itemPath(tHandle, asName=True)]
|
781
810
|
)))
|
782
811
|
else:
|
783
812
|
self.itemTitle.setText(i.itemName if (i := SHARED.project.tree[tHandle]) else "")
|
@@ -29,18 +29,18 @@ from enum import Enum
|
|
29
29
|
|
30
30
|
from PyQt5.QtCore import QModelIndex, Qt, pyqtSignal, pyqtSlot
|
31
31
|
from PyQt5.QtWidgets import (
|
32
|
-
QAbstractItemView, QFrame,
|
33
|
-
|
32
|
+
QAbstractItemView, QFrame, QMenu, QTabWidget, QToolButton, QTreeWidget,
|
33
|
+
QTreeWidgetItem, QVBoxLayout, QWidget
|
34
34
|
)
|
35
35
|
|
36
36
|
from novelwriter import CONFIG, SHARED
|
37
37
|
from novelwriter.common import checkInt
|
38
38
|
from novelwriter.constants import nwLabels, nwLists, nwStyles, trConst
|
39
39
|
from novelwriter.core.index import IndexHeading, IndexItem
|
40
|
-
from novelwriter.enum import nwDocMode, nwItemClass
|
40
|
+
from novelwriter.enum import nwChange, nwDocMode, nwItemClass
|
41
41
|
from novelwriter.extensions.modified import NIconToolButton
|
42
42
|
from novelwriter.gui.theme import STYLES_FLAT_TABS, STYLES_MIN_TOOLBUTTON
|
43
|
-
from novelwriter.types import QtDecoration, QtUserRole
|
43
|
+
from novelwriter.types import QtDecoration, QtHeaderFixed, QtHeaderToContents, QtUserRole
|
44
44
|
|
45
45
|
logger = logging.getLogger(__name__)
|
46
46
|
|
@@ -151,8 +151,8 @@ class GuiDocViewerPanel(QWidget):
|
|
151
151
|
self.updateHandle(self._lastHandle)
|
152
152
|
return
|
153
153
|
|
154
|
-
@pyqtSlot(str)
|
155
|
-
def
|
154
|
+
@pyqtSlot(str, Enum)
|
155
|
+
def onProjectItemChanged(self, tHandle: str, change: nwChange) -> None:
|
156
156
|
"""Update meta data for project item."""
|
157
157
|
self.tabBackRefs.refreshDocument(tHandle)
|
158
158
|
activeOnly = self.aInactive.isChecked()
|
@@ -259,10 +259,10 @@ class _ViewPanelBackRefs(QTreeWidget):
|
|
259
259
|
treeHeader = self.header()
|
260
260
|
treeHeader.setStretchLastSection(True)
|
261
261
|
treeHeader.setMinimumSectionSize(iPx + cMg) # See Issue #1627
|
262
|
-
treeHeader.setSectionResizeMode(self.C_DOC,
|
263
|
-
treeHeader.setSectionResizeMode(self.C_EDIT,
|
264
|
-
treeHeader.setSectionResizeMode(self.C_VIEW,
|
265
|
-
treeHeader.setSectionResizeMode(self.C_TITLE,
|
262
|
+
treeHeader.setSectionResizeMode(self.C_DOC, QtHeaderToContents)
|
263
|
+
treeHeader.setSectionResizeMode(self.C_EDIT, QtHeaderFixed)
|
264
|
+
treeHeader.setSectionResizeMode(self.C_VIEW, QtHeaderFixed)
|
265
|
+
treeHeader.setSectionResizeMode(self.C_TITLE, QtHeaderToContents)
|
266
266
|
treeHeader.resizeSection(self.C_EDIT, iPx + cMg)
|
267
267
|
treeHeader.resizeSection(self.C_VIEW, iPx + cMg)
|
268
268
|
treeHeader.setSectionsMovable(False)
|
@@ -339,17 +339,13 @@ class _ViewPanelBackRefs(QTreeWidget):
|
|
339
339
|
def _setTreeItemValues(self, tHandle: str, sTitle: str, hItem: IndexHeading) -> None:
|
340
340
|
"""Add or update a tree item."""
|
341
341
|
if nwItem := SHARED.project.tree[tHandle]:
|
342
|
-
docIcon = SHARED.theme.getItemIcon(
|
343
|
-
nwItem.itemType, nwItem.itemClass,
|
344
|
-
nwItem.itemLayout, nwItem.mainHeading
|
345
|
-
)
|
346
342
|
iLevel = nwStyles.H_LEVEL.get(hItem.level, 0) if nwItem.isDocumentLayout() else 5
|
347
343
|
hDec = SHARED.theme.getHeaderDecorationNarrow(iLevel)
|
348
344
|
|
349
345
|
tKey = f"{tHandle}:{sTitle}"
|
350
346
|
trItem = self._treeMap[tKey] if tKey in self._treeMap else QTreeWidgetItem()
|
351
347
|
|
352
|
-
trItem.setIcon(self.C_DOC,
|
348
|
+
trItem.setIcon(self.C_DOC, nwItem.getMainIcon())
|
353
349
|
trItem.setText(self.C_DOC, nwItem.itemName)
|
354
350
|
trItem.setToolTip(self.C_DOC, nwItem.itemName)
|
355
351
|
trItem.setIcon(self.C_EDIT, self._editIcon)
|
@@ -407,8 +403,8 @@ class _ViewPanelKeyWords(QTreeWidget):
|
|
407
403
|
treeHeader = self.header()
|
408
404
|
treeHeader.setStretchLastSection(True)
|
409
405
|
treeHeader.setMinimumSectionSize(iPx + cMg) # See Issue #1627
|
410
|
-
treeHeader.setSectionResizeMode(self.C_EDIT,
|
411
|
-
treeHeader.setSectionResizeMode(self.C_VIEW,
|
406
|
+
treeHeader.setSectionResizeMode(self.C_EDIT, QtHeaderFixed)
|
407
|
+
treeHeader.setSectionResizeMode(self.C_VIEW, QtHeaderFixed)
|
412
408
|
treeHeader.resizeSection(self.C_EDIT, iPx + cMg)
|
413
409
|
treeHeader.resizeSection(self.C_VIEW, iPx + cMg)
|
414
410
|
treeHeader.setSectionsMovable(False)
|
@@ -448,10 +444,6 @@ class _ViewPanelKeyWords(QTreeWidget):
|
|
448
444
|
def addUpdateEntry(self, tag: str, name: str, iItem: IndexItem, hItem: IndexHeading) -> None:
|
449
445
|
"""Add a new entry, or update an existing one."""
|
450
446
|
nwItem = iItem.item
|
451
|
-
docIcon = SHARED.theme.getItemIcon(
|
452
|
-
nwItem.itemType, nwItem.itemClass,
|
453
|
-
nwItem.itemLayout, nwItem.mainHeading
|
454
|
-
)
|
455
447
|
impLabel, impIcon = nwItem.getImportStatus()
|
456
448
|
iLevel = nwStyles.H_LEVEL.get(hItem.level, 0) if nwItem.isDocumentLayout() else 5
|
457
449
|
hDec = SHARED.theme.getHeaderDecorationNarrow(iLevel)
|
@@ -468,7 +460,7 @@ class _ViewPanelKeyWords(QTreeWidget):
|
|
468
460
|
trItem.setIcon(self.C_IMPORT, impIcon)
|
469
461
|
trItem.setText(self.C_IMPORT, impLabel)
|
470
462
|
trItem.setToolTip(self.C_IMPORT, impLabel)
|
471
|
-
trItem.setIcon(self.C_DOC,
|
463
|
+
trItem.setIcon(self.C_DOC, nwItem.getMainIcon())
|
472
464
|
trItem.setText(self.C_DOC, nwItem.itemName)
|
473
465
|
trItem.setToolTip(self.C_DOC, nwItem.itemName)
|
474
466
|
trItem.setData(self.C_TITLE, QtDecoration, hDec)
|
novelwriter/gui/itemdetails.py
CHANGED
@@ -25,12 +25,15 @@ from __future__ import annotations
|
|
25
25
|
|
26
26
|
import logging
|
27
27
|
|
28
|
+
from enum import Enum
|
29
|
+
|
28
30
|
from PyQt5.QtCore import pyqtSlot
|
29
31
|
from PyQt5.QtWidgets import QGridLayout, QLabel, QWidget
|
30
32
|
|
31
33
|
from novelwriter import CONFIG, SHARED
|
32
34
|
from novelwriter.common import elide
|
33
35
|
from novelwriter.constants import nwLabels, nwStats, trConst
|
36
|
+
from novelwriter.enum import nwChange
|
34
37
|
from novelwriter.types import (
|
35
38
|
QtAlignLeft, QtAlignLeftBase, QtAlignRight, QtAlignRightBase,
|
36
39
|
QtAlignRightMiddle
|
@@ -220,19 +223,9 @@ class GuiItemDetails(QWidget):
|
|
220
223
|
self.updateViewBox(self._handle)
|
221
224
|
return
|
222
225
|
|
223
|
-
|
224
|
-
# Public Slots
|
225
|
-
##
|
226
|
-
|
227
|
-
@pyqtSlot(str)
|
228
|
-
def updateViewBox(self, tHandle: str) -> None:
|
226
|
+
def updateViewBox(self, tHandle: str | None) -> None:
|
229
227
|
"""Populate the details box from a given handle."""
|
230
|
-
if tHandle
|
231
|
-
self.clearDetails()
|
232
|
-
return
|
233
|
-
|
234
|
-
nwItem = SHARED.project.tree[tHandle]
|
235
|
-
if nwItem is None:
|
228
|
+
if not (tHandle and (nwItem := SHARED.project.tree[tHandle])):
|
236
229
|
self.clearDetails()
|
237
230
|
return
|
238
231
|
|
@@ -269,10 +262,7 @@ class GuiItemDetails(QWidget):
|
|
269
262
|
# Layout
|
270
263
|
# ======
|
271
264
|
|
272
|
-
usageIcon
|
273
|
-
nwItem.itemType, nwItem.itemClass, nwItem.itemLayout, nwItem.mainHeading
|
274
|
-
)
|
275
|
-
self.usageIcon.setPixmap(usageIcon.pixmap(iPx, iPx))
|
265
|
+
self.usageIcon.setPixmap(nwItem.getMainIcon().pixmap(iPx, iPx))
|
276
266
|
self.usageData.setText(nwItem.describeMe())
|
277
267
|
|
278
268
|
# Counts
|
@@ -289,13 +279,16 @@ class GuiItemDetails(QWidget):
|
|
289
279
|
|
290
280
|
return
|
291
281
|
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
282
|
+
##
|
283
|
+
# Public Slots
|
284
|
+
##
|
285
|
+
|
286
|
+
@pyqtSlot(str, Enum)
|
287
|
+
def onProjectItemChanged(self, tHandle: str, change: nwChange) -> None:
|
288
|
+
"""Process project item change."""
|
297
289
|
if tHandle == self._handle:
|
298
|
-
|
299
|
-
|
300
|
-
|
290
|
+
if change == nwChange.UPDATE:
|
291
|
+
self.updateViewBox(tHandle)
|
292
|
+
elif change == nwChange.DELETE:
|
293
|
+
self.updateViewBox(None)
|
301
294
|
return
|
novelwriter/gui/mainmenu.py
CHANGED
@@ -28,7 +28,7 @@ import logging
|
|
28
28
|
from pathlib import Path
|
29
29
|
from typing import TYPE_CHECKING
|
30
30
|
|
31
|
-
from PyQt5.QtCore import pyqtSignal, pyqtSlot
|
31
|
+
from PyQt5.QtCore import Qt, pyqtSignal, pyqtSlot
|
32
32
|
from PyQt5.QtWidgets import QAction, QMenuBar
|
33
33
|
|
34
34
|
from novelwriter import CONFIG, SHARED
|
@@ -162,19 +162,20 @@ class GuiMainMenu(QMenuBar):
|
|
162
162
|
self.projMenu.addSeparator()
|
163
163
|
|
164
164
|
# Project > Edit
|
165
|
-
self.
|
166
|
-
self.
|
167
|
-
self.aEditItem.triggered.connect(qtLambda(self.mainGui.projView.renameTreeItem, None))
|
168
|
-
self.mainGui.addAction(self.aEditItem)
|
165
|
+
self.aRenameItem = self.projMenu.addAction(self.tr("Rename Item"))
|
166
|
+
self.aRenameItem.setShortcut("F2")
|
169
167
|
|
170
168
|
# Project > Delete
|
171
169
|
self.aDeleteItem = self.projMenu.addAction(self.tr("Delete Item"))
|
172
|
-
self.aDeleteItem.setShortcut("
|
173
|
-
self.aDeleteItem.
|
170
|
+
self.aDeleteItem.setShortcut("Del")
|
171
|
+
self.aDeleteItem.setShortcutContext(Qt.ShortcutContext.WidgetShortcut)
|
174
172
|
|
175
173
|
# Project > Empty Trash
|
176
174
|
self.aEmptyTrash = self.projMenu.addAction(self.tr("Empty Trash"))
|
177
|
-
|
175
|
+
|
176
|
+
self.mainGui.projView.connectMenuActions(
|
177
|
+
self.aRenameItem, self.aDeleteItem, self.aEmptyTrash
|
178
|
+
)
|
178
179
|
|
179
180
|
# Project > Separator
|
180
181
|
self.projMenu.addSeparator()
|
@@ -337,12 +338,16 @@ class GuiMainMenu(QMenuBar):
|
|
337
338
|
# View > Go Backward
|
338
339
|
self.aViewPrev = self.viewMenu.addAction(self.tr("Navigate Backward"))
|
339
340
|
self.aViewPrev.setShortcut("Alt+Left")
|
341
|
+
self.aViewPrev.setShortcutContext(Qt.ShortcutContext.WidgetShortcut)
|
340
342
|
self.aViewPrev.triggered.connect(self.mainGui.docViewer.navBackward)
|
343
|
+
self.mainGui.docViewer.addAction(self.aViewPrev)
|
341
344
|
|
342
345
|
# View > Go Forward
|
343
346
|
self.aViewNext = self.viewMenu.addAction(self.tr("Navigate Forward"))
|
344
347
|
self.aViewNext.setShortcut("Alt+Right")
|
348
|
+
self.aViewNext.setShortcutContext(Qt.ShortcutContext.WidgetShortcut)
|
345
349
|
self.aViewNext.triggered.connect(self.mainGui.docViewer.navForward)
|
350
|
+
self.mainGui.docViewer.addAction(self.aViewNext)
|
346
351
|
|
347
352
|
# View > Separator
|
348
353
|
self.viewMenu.addSeparator()
|
novelwriter/gui/noveltree.py
CHANGED
@@ -33,22 +33,22 @@ from time import time
|
|
33
33
|
from PyQt5.QtCore import QModelIndex, QPoint, Qt, pyqtSignal, pyqtSlot
|
34
34
|
from PyQt5.QtGui import QFocusEvent, QFont, QMouseEvent, QPalette, QResizeEvent
|
35
35
|
from PyQt5.QtWidgets import (
|
36
|
-
QAbstractItemView, QActionGroup, QFrame, QHBoxLayout,
|
37
|
-
|
38
|
-
QWidget
|
36
|
+
QAbstractItemView, QActionGroup, QFrame, QHBoxLayout, QInputDialog, QMenu,
|
37
|
+
QToolTip, QTreeWidget, QTreeWidgetItem, QVBoxLayout, QWidget
|
39
38
|
)
|
40
39
|
|
41
40
|
from novelwriter import CONFIG, SHARED
|
42
41
|
from novelwriter.common import minmax, qtLambda
|
43
42
|
from novelwriter.constants import nwKeyWords, nwLabels, nwStyles, trConst
|
44
43
|
from novelwriter.core.index import IndexHeading
|
45
|
-
from novelwriter.enum import nwDocMode, nwItemClass, nwOutline
|
44
|
+
from novelwriter.enum import nwChange, nwDocMode, nwItemClass, nwOutline
|
46
45
|
from novelwriter.extensions.modified import NIconToolButton
|
47
46
|
from novelwriter.extensions.novelselector import NovelSelector
|
48
47
|
from novelwriter.gui.theme import STYLES_MIN_TOOLBUTTON
|
49
48
|
from novelwriter.types import (
|
50
|
-
QtAlignRight, QtDecoration,
|
51
|
-
|
49
|
+
QtAlignRight, QtDecoration, QtHeaderStretch, QtHeaderToContents,
|
50
|
+
QtMouseLeft, QtMouseMiddle, QtScrollAlwaysOff, QtScrollAsNeeded,
|
51
|
+
QtSizeExpanding, QtUserRole
|
52
52
|
)
|
53
53
|
|
54
54
|
logger = logging.getLogger(__name__)
|
@@ -174,8 +174,8 @@ class GuiNovelView(QWidget):
|
|
174
174
|
self.novelTree.refreshTree(rootHandle=SHARED.project.data.getLastHandle("novelTree"))
|
175
175
|
return
|
176
176
|
|
177
|
-
@pyqtSlot(str)
|
178
|
-
def updateRootItem(self, tHandle: str) -> None:
|
177
|
+
@pyqtSlot(str, Enum)
|
178
|
+
def updateRootItem(self, tHandle: str, change: nwChange) -> None:
|
179
179
|
"""If any root item changes, rebuild the novel root menu."""
|
180
180
|
self.novelBar.buildNovelRootMenu()
|
181
181
|
return
|
@@ -406,10 +406,10 @@ class GuiNovelTree(QTreeWidget):
|
|
406
406
|
treeHeader = self.header()
|
407
407
|
treeHeader.setStretchLastSection(False)
|
408
408
|
treeHeader.setMinimumSectionSize(iPx + cMg)
|
409
|
-
treeHeader.setSectionResizeMode(self.C_TITLE,
|
410
|
-
treeHeader.setSectionResizeMode(self.C_WORDS,
|
411
|
-
treeHeader.setSectionResizeMode(self.C_EXTRA,
|
412
|
-
treeHeader.setSectionResizeMode(self.C_MORE,
|
409
|
+
treeHeader.setSectionResizeMode(self.C_TITLE, QtHeaderStretch)
|
410
|
+
treeHeader.setSectionResizeMode(self.C_WORDS, QtHeaderToContents)
|
411
|
+
treeHeader.setSectionResizeMode(self.C_EXTRA, QtHeaderToContents)
|
412
|
+
treeHeader.setSectionResizeMode(self.C_MORE, QtHeaderToContents)
|
413
413
|
|
414
414
|
# Pre-Generate Tree Formatting
|
415
415
|
fH1 = self.font()
|
novelwriter/gui/outline.py
CHANGED
@@ -43,7 +43,7 @@ from PyQt5.QtWidgets import (
|
|
43
43
|
from novelwriter import CONFIG, SHARED
|
44
44
|
from novelwriter.common import checkInt, formatFileFilter, makeFileNameSafe
|
45
45
|
from novelwriter.constants import nwKeyWords, nwLabels, nwStats, nwStyles, trConst
|
46
|
-
from novelwriter.enum import nwDocMode, nwItemClass, nwItemLayout, nwItemType, nwOutline
|
46
|
+
from novelwriter.enum import nwChange, nwDocMode, nwItemClass, nwItemLayout, nwItemType, nwOutline
|
47
47
|
from novelwriter.error import logException
|
48
48
|
from novelwriter.extensions.configlayout import NColourLabel
|
49
49
|
from novelwriter.extensions.novelselector import NovelSelector
|
@@ -165,8 +165,8 @@ class GuiOutlineView(QWidget):
|
|
165
165
|
# Public Slots
|
166
166
|
##
|
167
167
|
|
168
|
-
@pyqtSlot(str)
|
169
|
-
def updateRootItem(self, tHandle: str) -> None:
|
168
|
+
@pyqtSlot(str, Enum)
|
169
|
+
def updateRootItem(self, tHandle: str, change: nwChange) -> None:
|
170
170
|
"""Handle tasks whenever a root folders changes."""
|
171
171
|
self.outlineBar.populateNovelList()
|
172
172
|
self.outlineData.updateClasses()
|
@@ -380,8 +380,8 @@ class GuiOutlineTree(QTreeWidget):
|
|
380
380
|
self.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection)
|
381
381
|
self.setExpandsOnDoubleClick(False)
|
382
382
|
self.setDragEnabled(False)
|
383
|
-
self.itemDoubleClicked.connect(self.
|
384
|
-
self.itemSelectionChanged.connect(self.
|
383
|
+
self.itemDoubleClicked.connect(self._onItemDoubleClicked)
|
384
|
+
self.itemSelectionChanged.connect(self._onItemSelectionChanged)
|
385
385
|
|
386
386
|
self.setIconSize(SHARED.theme.baseIconSize)
|
387
387
|
self.setIndentation(0)
|
@@ -563,7 +563,7 @@ class GuiOutlineTree(QTreeWidget):
|
|
563
563
|
##
|
564
564
|
|
565
565
|
@pyqtSlot("QTreeWidgetItem*", int)
|
566
|
-
def
|
566
|
+
def _onItemDoubleClicked(self, tItem: QTreeWidgetItem, tCol: int) -> None:
|
567
567
|
"""Extract the handle and line number of the title double-
|
568
568
|
clicked, and send it to the main gui class for opening in the
|
569
569
|
document editor.
|
@@ -574,14 +574,13 @@ class GuiOutlineTree(QTreeWidget):
|
|
574
574
|
return
|
575
575
|
|
576
576
|
@pyqtSlot()
|
577
|
-
def
|
577
|
+
def _onItemSelectionChanged(self) -> None:
|
578
578
|
"""Extract the handle and line number of the currently selected
|
579
579
|
title, and send it to the details panel.
|
580
580
|
"""
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
sTitle = selItems[0].data(self._colIdx[nwOutline.TITLE], self.D_TITLE)
|
581
|
+
if items := self.selectedItems():
|
582
|
+
tHandle = items[0].data(self._colIdx[nwOutline.TITLE], self.D_HANDLE)
|
583
|
+
sTitle = items[0].data(self._colIdx[nwOutline.TITLE], self.D_TITLE)
|
585
584
|
self.activeItemChanged.emit(tHandle, sTitle)
|
586
585
|
return
|
587
586
|
|