Change the menu icon to three dots
This commit is contained in:
@@ -48,7 +48,7 @@ edit = typ_pencil.svg
|
|||||||
export = typ_export.svg
|
export = typ_export.svg
|
||||||
forward = typ_chevron-right.svg
|
forward = typ_chevron-right.svg
|
||||||
maximise = typ_arrow-maximise.svg
|
maximise = typ_arrow-maximise.svg
|
||||||
menu = typ_th-menu.svg
|
menu = typ_th-dot-menu.svg
|
||||||
minimise = typ_arrow-minimise.svg
|
minimise = typ_arrow-minimise.svg
|
||||||
noncheckable = mixed_input-none.svg
|
noncheckable = mixed_input-none.svg
|
||||||
proj_chapter = mixed_document-chapter.svg
|
proj_chapter = mixed_document-chapter.svg
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg width="24" height="24" version="1.2" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="m12 2a2.6315 2.6315 0 0 0-2.6314 2.6314 2.6315 2.6315 0 0 0 2.6314 2.6314 2.6315 2.6315 0 0 0 2.6314-2.6314 2.6315 2.6315 0 0 0-2.6314-2.6314zm0 7.3686a2.6315 2.6315 0 0 0-2.6314 2.6314 2.6315 2.6315 0 0 0 2.6314 2.6314 2.6315 2.6315 0 0 0 2.6314-2.6314 2.6315 2.6315 0 0 0-2.6314-2.6314zm0 7.3686a2.6315 2.6315 0 0 0-2.6314 2.6314 2.6315 2.6315 0 0 0 2.6314 2.6314 2.6315 2.6315 0 0 0 2.6314-2.6314 2.6315 2.6315 0 0 0-2.6314-2.6314z" fill="#aeaeae" stroke-width=".90909"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 629 B |
@@ -1,4 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<svg width="24" height="24" version="1.2" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path d="M19 17h-14c-1.103 0-2 .897-2 2s.897 2 2 2h14c1.103 0 2-.897 2-2s-.897-2-2-2zM19 10h-14c-1.103 0-2 .897-2 2s.897 2 2 2h14c1.103 0 2-.897 2-2s-.897-2-2-2zM19 3h-14c-1.103 0-2 .897-2 2s.897 2 2 2h14c1.103 0 2-.897 2-2s-.897-2-2-2z" fill="#69c"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 397 B |
@@ -48,7 +48,7 @@ edit = typ_pencil.svg
|
|||||||
export = typ_export.svg
|
export = typ_export.svg
|
||||||
forward = typ_chevron-right.svg
|
forward = typ_chevron-right.svg
|
||||||
maximise = typ_arrow-maximise.svg
|
maximise = typ_arrow-maximise.svg
|
||||||
menu = typ_th-menu.svg
|
menu = typ_th-dot-menu.svg
|
||||||
minimise = typ_arrow-minimise.svg
|
minimise = typ_arrow-minimise.svg
|
||||||
noncheckable = mixed_input-none.svg
|
noncheckable = mixed_input-none.svg
|
||||||
proj_chapter = mixed_document-chapter.svg
|
proj_chapter = mixed_document-chapter.svg
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg width="24" height="24" version="1.2" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="m12 2a2.6315 2.6315 0 0 0-2.6314 2.6314 2.6315 2.6315 0 0 0 2.6314 2.6314 2.6315 2.6315 0 0 0 2.6314-2.6314 2.6315 2.6315 0 0 0-2.6314-2.6314zm0 7.3686a2.6315 2.6315 0 0 0-2.6314 2.6314 2.6315 2.6315 0 0 0 2.6314 2.6314 2.6315 2.6315 0 0 0 2.6314-2.6314 2.6315 2.6315 0 0 0-2.6314-2.6314zm0 7.3686a2.6315 2.6315 0 0 0-2.6314 2.6314 2.6315 2.6315 0 0 0 2.6314 2.6314 2.6315 2.6315 0 0 0 2.6314-2.6314 2.6315 2.6315 0 0 0-2.6314-2.6314z" fill-opacity=".78039" stroke-width=".90909"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 636 B |
@@ -1,4 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<svg width="24" height="24" version="1.2" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path d="M19 17h-14c-1.103 0-2 .897-2 2s.897 2 2 2h14c1.103 0 2-.897 2-2s-.897-2-2-2zM19 10h-14c-1.103 0-2 .897-2 2s.897 2 2 2h14c1.103 0 2-.897 2-2s-.897-2-2-2zM19 3h-14c-1.103 0-2 .897-2 2s.897 2 2 2h14c1.103 0 2-.897 2-2s-.897-2-2-2z" fill="#4271ae"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 400 B |
@@ -28,7 +28,7 @@ import json
|
|||||||
import logging
|
import logging
|
||||||
|
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from typing import TYPE_CHECKING, Any
|
from typing import TYPE_CHECKING, Any, TypeVar
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from novelwriter.error import logException
|
from novelwriter.error import logException
|
||||||
@@ -40,6 +40,8 @@ if TYPE_CHECKING: # pragma: no cover
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
NWEnum = TypeVar("NWEnum", bound=Enum)
|
||||||
|
|
||||||
VALID_MAP = {
|
VALID_MAP = {
|
||||||
"GuiWritingStats": {
|
"GuiWritingStats": {
|
||||||
"winWidth", "winHeight", "widthCol0", "widthCol1", "widthCol2",
|
"winWidth", "winHeight", "widthCol0", "widthCol1", "widthCol2",
|
||||||
@@ -201,11 +203,11 @@ class OptionState:
|
|||||||
return checkBool(self._state[group].get(name, default), default)
|
return checkBool(self._state[group].get(name, default), default)
|
||||||
return default
|
return default
|
||||||
|
|
||||||
def getEnum(self, group: str, name: str, lookup: type, default: Enum) -> Enum:
|
def getEnum(self, group: str, name: str, lookup: type, default: NWEnum) -> NWEnum:
|
||||||
"""Return the value mapped to an enum. Otherwise return the
|
"""Return the value mapped to an enum. Otherwise return the
|
||||||
default value.
|
default value.
|
||||||
"""
|
"""
|
||||||
if issubclass(lookup, Enum):
|
if issubclass(lookup, type(default)):
|
||||||
if group in self._state:
|
if group in self._state:
|
||||||
if name in self._state[group]:
|
if name in self._state[group]:
|
||||||
value = self._state[group][name]
|
value = self._state[group][name]
|
||||||
|
|||||||
+100
-124
@@ -29,9 +29,10 @@ import logging
|
|||||||
|
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from time import time
|
from time import time
|
||||||
|
from typing import TYPE_CHECKING
|
||||||
|
|
||||||
from PyQt5.QtGui import QFont, QPalette
|
from PyQt5.QtGui import QFocusEvent, QFont, QMouseEvent, QPalette, QResizeEvent
|
||||||
from PyQt5.QtCore import Qt, QSize, pyqtSlot, pyqtSignal
|
from PyQt5.QtCore import QModelIndex, QPoint, Qt, QSize, pyqtSlot, pyqtSignal
|
||||||
from PyQt5.QtWidgets import (
|
from PyQt5.QtWidgets import (
|
||||||
QAbstractItemView, QActionGroup, QFrame, QHBoxLayout, QHeaderView,
|
QAbstractItemView, QActionGroup, QFrame, QHBoxLayout, QHeaderView,
|
||||||
QInputDialog, QMenu, QSizePolicy, QToolButton, QToolTip, QTreeWidget,
|
QInputDialog, QMenu, QSizePolicy, QToolButton, QToolTip, QTreeWidget,
|
||||||
@@ -42,8 +43,12 @@ from novelwriter import CONFIG, SHARED
|
|||||||
from novelwriter.enum import nwDocMode, nwItemClass, nwOutline
|
from novelwriter.enum import nwDocMode, nwItemClass, nwOutline
|
||||||
from novelwriter.common import minmax
|
from novelwriter.common import minmax
|
||||||
from novelwriter.constants import nwHeaders, nwKeyWords, nwLabels, trConst
|
from novelwriter.constants import nwHeaders, nwKeyWords, nwLabels, trConst
|
||||||
|
from novelwriter.core.index import IndexHeading
|
||||||
from novelwriter.extensions.novelselector import NovelSelector
|
from novelwriter.extensions.novelselector import NovelSelector
|
||||||
|
|
||||||
|
if TYPE_CHECKING: # pragma: no cover
|
||||||
|
from novelwriter.guimain import GuiMain
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@@ -63,7 +68,7 @@ class GuiNovelView(QWidget):
|
|||||||
selectedItemChanged = pyqtSignal(str)
|
selectedItemChanged = pyqtSignal(str)
|
||||||
openDocumentRequest = pyqtSignal(str, Enum, str, bool)
|
openDocumentRequest = pyqtSignal(str, Enum, str, bool)
|
||||||
|
|
||||||
def __init__(self, mainGui):
|
def __init__(self, mainGui: GuiMain) -> None:
|
||||||
super().__init__(parent=mainGui)
|
super().__init__(parent=mainGui)
|
||||||
|
|
||||||
self.mainGui = mainGui
|
self.mainGui = mainGui
|
||||||
@@ -92,33 +97,29 @@ class GuiNovelView(QWidget):
|
|||||||
# Methods
|
# Methods
|
||||||
##
|
##
|
||||||
|
|
||||||
def updateTheme(self):
|
def updateTheme(self) -> None:
|
||||||
"""Update theme elements.
|
"""Update theme elements."""
|
||||||
"""
|
|
||||||
self.novelBar.updateTheme()
|
self.novelBar.updateTheme()
|
||||||
self.novelTree.updateTheme()
|
self.novelTree.updateTheme()
|
||||||
self.refreshTree()
|
self.refreshTree()
|
||||||
return
|
return
|
||||||
|
|
||||||
def initSettings(self):
|
def initSettings(self) -> None:
|
||||||
"""Initialise GUI elements that depend on specific settings.
|
"""Initialise GUI elements that depend on specific settings."""
|
||||||
"""
|
|
||||||
self.novelTree.initSettings()
|
self.novelTree.initSettings()
|
||||||
return
|
return
|
||||||
|
|
||||||
def clearNovelView(self):
|
def clearNovelView(self) -> None:
|
||||||
"""Clear project-related GUI content.
|
"""Clear project-related GUI content."""
|
||||||
"""
|
|
||||||
self.novelTree.clearContent()
|
self.novelTree.clearContent()
|
||||||
self.novelBar.clearContent()
|
self.novelBar.clearContent()
|
||||||
self.novelBar.setEnabled(False)
|
self.novelBar.setEnabled(False)
|
||||||
return
|
return
|
||||||
|
|
||||||
def openProjectTasks(self):
|
def openProjectTasks(self) -> None:
|
||||||
"""Run open project tasks.
|
"""Run open project tasks."""
|
||||||
"""
|
|
||||||
lastNovel = SHARED.project.data.getLastHandle("novelTree")
|
lastNovel = SHARED.project.data.getLastHandle("novelTree")
|
||||||
if lastNovel not in SHARED.project.tree:
|
if lastNovel and lastNovel not in SHARED.project.tree:
|
||||||
lastNovel = SHARED.project.tree.findRoot(nwItemClass.NOVEL)
|
lastNovel = SHARED.project.tree.findRoot(nwItemClass.NOVEL)
|
||||||
|
|
||||||
logger.debug("Setting novel tree to root item '%s'", lastNovel)
|
logger.debug("Setting novel tree to root item '%s'", lastNovel)
|
||||||
@@ -140,7 +141,7 @@ class GuiNovelView(QWidget):
|
|||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def closeProjectTasks(self):
|
def closeProjectTasks(self) -> None:
|
||||||
"""Run closing project tasks."""
|
"""Run closing project tasks."""
|
||||||
lastColType = self.novelTree.lastColType
|
lastColType = self.novelTree.lastColType
|
||||||
lastColSize = self.novelTree.lastColSize
|
lastColSize = self.novelTree.lastColSize
|
||||||
@@ -150,15 +151,13 @@ class GuiNovelView(QWidget):
|
|||||||
self.clearNovelView()
|
self.clearNovelView()
|
||||||
return
|
return
|
||||||
|
|
||||||
def setTreeFocus(self):
|
def setTreeFocus(self) -> None:
|
||||||
"""Set the focus to the tree widget.
|
"""Set the focus to the tree widget."""
|
||||||
"""
|
|
||||||
self.novelTree.setFocus()
|
self.novelTree.setFocus()
|
||||||
return
|
return
|
||||||
|
|
||||||
def treeHasFocus(self):
|
def treeHasFocus(self) -> bool:
|
||||||
"""Check if the novel tree has focus.
|
"""Check if the novel tree has focus."""
|
||||||
"""
|
|
||||||
return self.novelTree.hasFocus()
|
return self.novelTree.hasFocus()
|
||||||
|
|
||||||
##
|
##
|
||||||
@@ -166,21 +165,19 @@ class GuiNovelView(QWidget):
|
|||||||
##
|
##
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def refreshTree(self):
|
def refreshTree(self) -> None:
|
||||||
"""Refresh the current tree.
|
"""Refresh the current tree."""
|
||||||
"""
|
|
||||||
self.novelTree.refreshTree(rootHandle=SHARED.project.data.getLastHandle("novelTree"))
|
self.novelTree.refreshTree(rootHandle=SHARED.project.data.getLastHandle("novelTree"))
|
||||||
return
|
return
|
||||||
|
|
||||||
@pyqtSlot(str)
|
@pyqtSlot(str)
|
||||||
def updateRootItem(self, tHandle):
|
def updateRootItem(self, tHandle: str) -> None:
|
||||||
"""If any root item changes, rebuild the novel root menu.
|
"""If any root item changes, rebuild the novel root menu."""
|
||||||
"""
|
|
||||||
self.novelBar.buildNovelRootMenu()
|
self.novelBar.buildNovelRootMenu()
|
||||||
return
|
return
|
||||||
|
|
||||||
@pyqtSlot(str)
|
@pyqtSlot(str)
|
||||||
def updateNovelItemMeta(self, tHandle):
|
def updateNovelItemMeta(self, tHandle: str) -> None:
|
||||||
"""The meta data of a novel item has changed, and the tree item
|
"""The meta data of a novel item has changed, and the tree item
|
||||||
needs to be refreshed.
|
needs to be refreshed.
|
||||||
"""
|
"""
|
||||||
@@ -192,7 +189,7 @@ class GuiNovelView(QWidget):
|
|||||||
|
|
||||||
class GuiNovelToolBar(QWidget):
|
class GuiNovelToolBar(QWidget):
|
||||||
|
|
||||||
def __init__(self, novelView):
|
def __init__(self, novelView: GuiNovelView) -> None:
|
||||||
super().__init__(parent=novelView)
|
super().__init__(parent=novelView)
|
||||||
|
|
||||||
logger.debug("Create: GuiNovelToolBar")
|
logger.debug("Create: GuiNovelToolBar")
|
||||||
@@ -269,9 +266,8 @@ class GuiNovelToolBar(QWidget):
|
|||||||
# Methods
|
# Methods
|
||||||
##
|
##
|
||||||
|
|
||||||
def updateTheme(self):
|
def updateTheme(self) -> None:
|
||||||
"""Update theme elements.
|
"""Update theme elements."""
|
||||||
"""
|
|
||||||
# Icons
|
# Icons
|
||||||
self.tbNovel.setIcon(SHARED.theme.getIcon("cls_novel"))
|
self.tbNovel.setIcon(SHARED.theme.getIcon("cls_novel"))
|
||||||
self.tbRefresh.setIcon(SHARED.theme.getIcon("refresh"))
|
self.tbRefresh.setIcon(SHARED.theme.getIcon("refresh"))
|
||||||
@@ -287,10 +283,11 @@ class GuiNovelToolBar(QWidget):
|
|||||||
"QToolButton {{padding: {0}px; border: none; background: transparent;}} "
|
"QToolButton {{padding: {0}px; border: none; background: transparent;}} "
|
||||||
"QToolButton:hover {{border: none; background: rgba({1},{2},{3},0.2);}}"
|
"QToolButton:hover {{border: none; background: rgba({1},{2},{3},0.2);}}"
|
||||||
).format(CONFIG.pxInt(2), fadeCol.red(), fadeCol.green(), fadeCol.blue())
|
).format(CONFIG.pxInt(2), fadeCol.red(), fadeCol.green(), fadeCol.blue())
|
||||||
|
buttonStyleMenu = f"{buttonStyle} QToolButton::menu-indicator {{image: none;}}"
|
||||||
|
|
||||||
self.tbNovel.setStyleSheet(buttonStyle)
|
self.tbNovel.setStyleSheet(buttonStyle)
|
||||||
self.tbRefresh.setStyleSheet(buttonStyle)
|
self.tbRefresh.setStyleSheet(buttonStyle)
|
||||||
self.tbMore.setStyleSheet(buttonStyle)
|
self.tbMore.setStyleSheet(buttonStyleMenu)
|
||||||
|
|
||||||
self.novelValue.setStyleSheet(
|
self.novelValue.setStyleSheet(
|
||||||
"QComboBox {border-style: none; padding-left: 0;} "
|
"QComboBox {border-style: none; padding-left: 0;} "
|
||||||
@@ -301,30 +298,26 @@ class GuiNovelToolBar(QWidget):
|
|||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def clearContent(self):
|
def clearContent(self) -> None:
|
||||||
"""Run clearing project tasks.
|
"""Run clearing project tasks."""
|
||||||
"""
|
|
||||||
self.novelValue.clear()
|
self.novelValue.clear()
|
||||||
self.novelValue.setToolTip("")
|
self.novelValue.setToolTip("")
|
||||||
return
|
return
|
||||||
|
|
||||||
def buildNovelRootMenu(self):
|
def buildNovelRootMenu(self) -> None:
|
||||||
"""Build the novel root menu.
|
"""Build the novel root menu."""
|
||||||
"""
|
|
||||||
self.novelValue.updateList(prefix=self.novelPrefix)
|
self.novelValue.updateList(prefix=self.novelPrefix)
|
||||||
self.tbNovel.setVisible(self.novelValue.count() > 1)
|
self.tbNovel.setVisible(self.novelValue.count() > 1)
|
||||||
return
|
return
|
||||||
|
|
||||||
def setCurrentRoot(self, rootHandle):
|
def setCurrentRoot(self, rootHandle: str | None) -> None:
|
||||||
"""Set the current active root handle.
|
"""Set the current active root handle."""
|
||||||
"""
|
|
||||||
self.novelValue.setHandle(rootHandle)
|
self.novelValue.setHandle(rootHandle)
|
||||||
self.novelView.novelTree.refreshTree(rootHandle=rootHandle, overRide=True)
|
self.novelView.novelTree.refreshTree(rootHandle=rootHandle, overRide=True)
|
||||||
return
|
return
|
||||||
|
|
||||||
def setLastColType(self, colType, doRefresh=True):
|
def setLastColType(self, colType: NovelTreeColumn, doRefresh: bool = True) -> None:
|
||||||
"""Set the last column type.
|
"""Set the last column type."""
|
||||||
"""
|
|
||||||
self.aLastCol[colType].setChecked(True)
|
self.aLastCol[colType].setChecked(True)
|
||||||
self.novelView.novelTree.setLastColType(colType, doRefresh=doRefresh)
|
self.novelView.novelTree.setLastColType(colType, doRefresh=doRefresh)
|
||||||
return
|
return
|
||||||
@@ -334,24 +327,21 @@ class GuiNovelToolBar(QWidget):
|
|||||||
##
|
##
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def _openNovelSelector(self):
|
def _openNovelSelector(self) -> None:
|
||||||
"""Trigger the dropdown list of the novel selector.
|
"""Trigger the dropdown list of the novel selector."""
|
||||||
"""
|
|
||||||
self.novelValue.showPopup()
|
self.novelValue.showPopup()
|
||||||
return
|
return
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def _refreshNovelTree(self):
|
def _refreshNovelTree(self) -> None:
|
||||||
"""Rebuild the current tree.
|
"""Rebuild the current tree."""
|
||||||
"""
|
|
||||||
rootHandle = SHARED.project.data.getLastHandle("novelTree")
|
rootHandle = SHARED.project.data.getLastHandle("novelTree")
|
||||||
self.novelView.novelTree.refreshTree(rootHandle=rootHandle, overRide=True)
|
self.novelView.novelTree.refreshTree(rootHandle=rootHandle, overRide=True)
|
||||||
return
|
return
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def _selectLastColumnSize(self):
|
def _selectLastColumnSize(self) -> None:
|
||||||
"""Set the maximum width for the last column.
|
"""Set the maximum width for the last column."""
|
||||||
"""
|
|
||||||
oldSize = self.novelView.novelTree.lastColSize
|
oldSize = self.novelView.novelTree.lastColSize
|
||||||
newSize, isOk = QInputDialog.getInt(
|
newSize, isOk = QInputDialog.getInt(
|
||||||
self, self.tr("Column Size"), self.tr("Maximum column size in %"), oldSize, 15, 75, 5
|
self, self.tr("Column Size"), self.tr("Maximum column size in %"), oldSize, 15, 75, 5
|
||||||
@@ -365,9 +355,8 @@ class GuiNovelToolBar(QWidget):
|
|||||||
# Internal Functions
|
# Internal Functions
|
||||||
##
|
##
|
||||||
|
|
||||||
def _addLastColAction(self, colType, actionLabel):
|
def _addLastColAction(self, colType, actionLabel) -> None:
|
||||||
"""Add a column selection entry to the last column menu.
|
"""Add a column selection entry to the last column menu."""
|
||||||
"""
|
|
||||||
aLast = self.mLastCol.addAction(actionLabel)
|
aLast = self.mLastCol.addAction(actionLabel)
|
||||||
aLast.setCheckable(True)
|
aLast.setCheckable(True)
|
||||||
aLast.setActionGroup(self.gLastCol)
|
aLast.setActionGroup(self.gLastCol)
|
||||||
@@ -391,7 +380,7 @@ class GuiNovelTree(QTreeWidget):
|
|||||||
D_KEY = Qt.ItemDataRole.UserRole + 2
|
D_KEY = Qt.ItemDataRole.UserRole + 2
|
||||||
D_EXTRA = Qt.ItemDataRole.UserRole + 3
|
D_EXTRA = Qt.ItemDataRole.UserRole + 3
|
||||||
|
|
||||||
def __init__(self, novelView):
|
def __init__(self, novelView: GuiNovelView) -> None:
|
||||||
super().__init__(parent=novelView)
|
super().__init__(parent=novelView)
|
||||||
|
|
||||||
logger.debug("Create: GuiNovelTree")
|
logger.debug("Create: GuiNovelTree")
|
||||||
@@ -461,9 +450,8 @@ class GuiNovelTree(QTreeWidget):
|
|||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def initSettings(self):
|
def initSettings(self) -> None:
|
||||||
"""Set or update tree widget settings.
|
"""Set or update tree widget settings."""
|
||||||
"""
|
|
||||||
# Scroll bars
|
# Scroll bars
|
||||||
if CONFIG.hideVScroll:
|
if CONFIG.hideVScroll:
|
||||||
self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
||||||
@@ -477,9 +465,8 @@ class GuiNovelTree(QTreeWidget):
|
|||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def updateTheme(self):
|
def updateTheme(self) -> None:
|
||||||
"""Update theme elements.
|
"""Update theme elements."""
|
||||||
"""
|
|
||||||
iPx = SHARED.theme.baseIconSize
|
iPx = SHARED.theme.baseIconSize
|
||||||
self._pMore = SHARED.theme.loadDecoration("deco_doc_more", pxH=iPx)
|
self._pMore = SHARED.theme.loadDecoration("deco_doc_more", pxH=iPx)
|
||||||
return
|
return
|
||||||
@@ -489,28 +476,26 @@ class GuiNovelTree(QTreeWidget):
|
|||||||
##
|
##
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def lastColType(self):
|
def lastColType(self) -> NovelTreeColumn:
|
||||||
return self._lastCol
|
return self._lastCol
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def lastColSize(self):
|
def lastColSize(self) -> int:
|
||||||
return int(self._lastColSize * 100)
|
return int(self._lastColSize * 100)
|
||||||
|
|
||||||
##
|
##
|
||||||
# Class Methods
|
# Class Methods
|
||||||
##
|
##
|
||||||
|
|
||||||
def clearContent(self):
|
def clearContent(self) -> None:
|
||||||
"""Clear the GUI content and the related maps.
|
"""Clear the GUI content and the related maps."""
|
||||||
"""
|
|
||||||
self.clear()
|
self.clear()
|
||||||
self._treeMap = {}
|
self._treeMap = {}
|
||||||
self._lastBuild = 0
|
self._lastBuild = 0
|
||||||
return
|
return
|
||||||
|
|
||||||
def refreshTree(self, rootHandle=None, overRide=False):
|
def refreshTree(self, rootHandle: str | None = None, overRide: bool = False) -> None:
|
||||||
"""Refresh the tree if it has been changed.
|
"""Refresh the tree if it has been changed."""
|
||||||
"""
|
|
||||||
logger.debug("Requesting refresh of the novel tree")
|
logger.debug("Requesting refresh of the novel tree")
|
||||||
if rootHandle is None:
|
if rootHandle is None:
|
||||||
rootHandle = SHARED.project.tree.findRoot(nwItemClass.NOVEL)
|
rootHandle = SHARED.project.tree.findRoot(nwItemClass.NOVEL)
|
||||||
@@ -534,9 +519,8 @@ class GuiNovelTree(QTreeWidget):
|
|||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def refreshHandle(self, tHandle):
|
def refreshHandle(self, tHandle: str) -> None:
|
||||||
"""Refresh the data for a given handle.
|
"""Refresh the data for a given handle."""
|
||||||
"""
|
|
||||||
idxData = SHARED.project.index.getItemData(tHandle)
|
idxData = SHARED.project.index.getItemData(tHandle)
|
||||||
if idxData is None:
|
if idxData is None:
|
||||||
return
|
return
|
||||||
@@ -554,7 +538,7 @@ class GuiNovelTree(QTreeWidget):
|
|||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def getSelectedHandle(self):
|
def getSelectedHandle(self) -> tuple[str | None, str | None]:
|
||||||
"""Get the currently selected or active handle. If multiple
|
"""Get the currently selected or active handle. If multiple
|
||||||
items are selected, return the first.
|
items are selected, return the first.
|
||||||
"""
|
"""
|
||||||
@@ -566,9 +550,8 @@ class GuiNovelTree(QTreeWidget):
|
|||||||
return tHandle, sTitle
|
return tHandle, sTitle
|
||||||
return None, None
|
return None, None
|
||||||
|
|
||||||
def setLastColType(self, colType, doRefresh=True):
|
def setLastColType(self, colType: NovelTreeColumn, doRefresh: bool = True) -> None:
|
||||||
"""Change the content type of the last column and rebuild.
|
"""Change the content type of the last column and rebuild."""
|
||||||
"""
|
|
||||||
if self._lastCol != colType:
|
if self._lastCol != colType:
|
||||||
logger.debug("Changing last column to %s", colType.name)
|
logger.debug("Changing last column to %s", colType.name)
|
||||||
self._lastCol = colType
|
self._lastCol = colType
|
||||||
@@ -578,15 +561,13 @@ class GuiNovelTree(QTreeWidget):
|
|||||||
self.refreshTree(rootHandle=lastNovel, overRide=True)
|
self.refreshTree(rootHandle=lastNovel, overRide=True)
|
||||||
return
|
return
|
||||||
|
|
||||||
def setLastColSize(self, colSize):
|
def setLastColSize(self, colSize: int) -> None:
|
||||||
"""Set the column size in integer values between 15 and 75.
|
"""Set the column size in integer values between 15 and 75."""
|
||||||
"""
|
|
||||||
self._lastColSize = minmax(colSize, 15, 75)/100.0
|
self._lastColSize = minmax(colSize, 15, 75)/100.0
|
||||||
return
|
return
|
||||||
|
|
||||||
def setActiveHandle(self, tHandle):
|
def setActiveHandle(self, tHandle: str | None) -> None:
|
||||||
"""Highlight the rows associated with a given handle.
|
"""Highlight the rows associated with a given handle."""
|
||||||
"""
|
|
||||||
tStart = time()
|
tStart = time()
|
||||||
|
|
||||||
self._actHandle = tHandle
|
self._actHandle = tHandle
|
||||||
@@ -612,20 +593,20 @@ class GuiNovelTree(QTreeWidget):
|
|||||||
# Events
|
# Events
|
||||||
##
|
##
|
||||||
|
|
||||||
def mousePressEvent(self, theEvent):
|
def mousePressEvent(self, event: QMouseEvent) -> None:
|
||||||
"""Overload mousePressEvent to clear selection if clicking the
|
"""Overload mousePressEvent to clear selection if clicking the
|
||||||
mouse in a blank area of the tree view, and to load a document
|
mouse in a blank area of the tree view, and to load a document
|
||||||
for viewing if the user middle-clicked.
|
for viewing if the user middle-clicked.
|
||||||
"""
|
"""
|
||||||
super().mousePressEvent(theEvent)
|
super().mousePressEvent(event)
|
||||||
|
|
||||||
if theEvent.button() == Qt.LeftButton:
|
if event.button() == Qt.LeftButton:
|
||||||
selItem = self.indexAt(theEvent.pos())
|
selItem = self.indexAt(event.pos())
|
||||||
if not selItem.isValid():
|
if not selItem.isValid():
|
||||||
self.clearSelection()
|
self.clearSelection()
|
||||||
|
|
||||||
elif theEvent.button() == Qt.MiddleButton:
|
elif event.button() == Qt.MiddleButton:
|
||||||
selItem = self.itemAt(theEvent.pos())
|
selItem = self.itemAt(event.pos())
|
||||||
if not isinstance(selItem, QTreeWidgetItem):
|
if not isinstance(selItem, QTreeWidgetItem):
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -637,16 +618,14 @@ class GuiNovelTree(QTreeWidget):
|
|||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def focusOutEvent(self, theEvent):
|
def focusOutEvent(self, event: QFocusEvent) -> None:
|
||||||
"""Clear the selection when the tree no longer has focus.
|
"""Clear the selection when the tree no longer has focus."""
|
||||||
"""
|
super().focusOutEvent(event)
|
||||||
super().focusOutEvent(theEvent)
|
|
||||||
self.clearSelection()
|
self.clearSelection()
|
||||||
return
|
return
|
||||||
|
|
||||||
def resizeEvent(self, event):
|
def resizeEvent(self, event: QResizeEvent) -> None:
|
||||||
"""Elide labels in the extra column.
|
"""Elide labels in the extra column."""
|
||||||
"""
|
|
||||||
super().resizeEvent(event)
|
super().resizeEvent(event)
|
||||||
newW = event.size().width()
|
newW = event.size().width()
|
||||||
oldW = event.oldSize().width()
|
oldW = event.oldSize().width()
|
||||||
@@ -665,18 +644,17 @@ class GuiNovelTree(QTreeWidget):
|
|||||||
##
|
##
|
||||||
|
|
||||||
@pyqtSlot("QModelIndex")
|
@pyqtSlot("QModelIndex")
|
||||||
def _treeItemClicked(self, mIndex):
|
def _treeItemClicked(self, index: QModelIndex) -> None:
|
||||||
"""The user clicked on an item in the tree.
|
"""The user clicked on an item in the tree."""
|
||||||
"""
|
if index.column() == self.C_MORE:
|
||||||
if mIndex.column() == self.C_MORE:
|
tHandle = index.siblingAtColumn(self.C_DATA).data(self.D_HANDLE)
|
||||||
tHandle = mIndex.siblingAtColumn(self.C_DATA).data(self.D_HANDLE)
|
sTitle = index.siblingAtColumn(self.C_DATA).data(self.D_TITLE)
|
||||||
sTitle = mIndex.siblingAtColumn(self.C_DATA).data(self.D_TITLE)
|
tipPos = self.mapToGlobal(self.visualRect(index).topRight())
|
||||||
tipPos = self.mapToGlobal(self.visualRect(mIndex).topRight())
|
|
||||||
self._popMetaBox(tipPos, tHandle, sTitle)
|
self._popMetaBox(tipPos, tHandle, sTitle)
|
||||||
return
|
return
|
||||||
|
|
||||||
@pyqtSlot()
|
@pyqtSlot()
|
||||||
def _treeSelectionChange(self):
|
def _treeSelectionChange(self) -> None:
|
||||||
"""Extract the handle and line number of the currently selected
|
"""Extract the handle and line number of the currently selected
|
||||||
title, and send it to the tree meta panel.
|
title, and send it to the tree meta panel.
|
||||||
"""
|
"""
|
||||||
@@ -686,7 +664,7 @@ class GuiNovelTree(QTreeWidget):
|
|||||||
return
|
return
|
||||||
|
|
||||||
@pyqtSlot("QTreeWidgetItem*", int)
|
@pyqtSlot("QTreeWidgetItem*", int)
|
||||||
def _treeDoubleClick(self, tItem, colNo):
|
def _treeDoubleClick(self, item: QTreeWidgetItem, column: int) -> None:
|
||||||
"""Extract the handle and line number of the title double-
|
"""Extract the handle and line number of the title double-
|
||||||
clicked, and send it to the main gui class for opening in the
|
clicked, and send it to the main gui class for opening in the
|
||||||
document editor.
|
document editor.
|
||||||
@@ -699,9 +677,8 @@ class GuiNovelTree(QTreeWidget):
|
|||||||
# Internal Functions
|
# Internal Functions
|
||||||
##
|
##
|
||||||
|
|
||||||
def _populateTree(self, rootHandle):
|
def _populateTree(self, rootHandle: str | None) -> None:
|
||||||
"""Build the tree based on the project index.
|
"""Build the tree based on the project index."""
|
||||||
"""
|
|
||||||
self.clearContent()
|
self.clearContent()
|
||||||
tStart = time()
|
tStart = time()
|
||||||
logger.debug("Building novel tree for root item '%s'", rootHandle)
|
logger.debug("Building novel tree for root item '%s'", rootHandle)
|
||||||
@@ -728,9 +705,9 @@ class GuiNovelTree(QTreeWidget):
|
|||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def _updateTreeItemValues(self, trItem, idxItem, tHandle, sTitle):
|
def _updateTreeItemValues(self, trItem: QTreeWidgetItem, idxItem: IndexHeading,
|
||||||
"""Set the tree item values from the index entry.
|
tHandle: str, sTitle: str) -> None:
|
||||||
"""
|
"""Set the tree item values from the index entry."""
|
||||||
iLevel = nwHeaders.H_LEVEL.get(idxItem.level, 0)
|
iLevel = nwHeaders.H_LEVEL.get(idxItem.level, 0)
|
||||||
hDec = SHARED.theme.getHeaderDecoration(iLevel)
|
hDec = SHARED.theme.getHeaderDecoration(iLevel)
|
||||||
|
|
||||||
@@ -750,9 +727,8 @@ class GuiNovelTree(QTreeWidget):
|
|||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
def _getLastColumnText(self, tHandle, sTitle):
|
def _getLastColumnText(self, tHandle: str, sTitle: str) -> tuple[str, str]:
|
||||||
"""Generate the text for the last column based on user settings.
|
"""Generate text for the last column based on user settings."""
|
||||||
"""
|
|
||||||
if self._lastCol == NovelTreeColumn.HIDDEN:
|
if self._lastCol == NovelTreeColumn.HIDDEN:
|
||||||
return "", ""
|
return "", ""
|
||||||
|
|
||||||
@@ -777,14 +753,15 @@ class GuiNovelTree(QTreeWidget):
|
|||||||
|
|
||||||
return "", ""
|
return "", ""
|
||||||
|
|
||||||
def _popMetaBox(self, qPos, tHandle, sTitle):
|
def _popMetaBox(self, qPos: QPoint, tHandle: str, sTitle: str) -> None:
|
||||||
"""Show the novel meta data box.
|
"""Show the novel meta data box."""
|
||||||
"""
|
|
||||||
logger.debug("Generating meta data tooltip for '%s:%s'", tHandle, sTitle)
|
logger.debug("Generating meta data tooltip for '%s:%s'", tHandle, sTitle)
|
||||||
|
|
||||||
pIndex = SHARED.project.index
|
pIndex = SHARED.project.index
|
||||||
novIdx = pIndex.getItemHeader(tHandle, sTitle)
|
novIdx = pIndex.getItemHeader(tHandle, sTitle)
|
||||||
refTags = pIndex.getReferences(tHandle, sTitle)
|
refTags = pIndex.getReferences(tHandle, sTitle)
|
||||||
|
if not novIdx:
|
||||||
|
return
|
||||||
|
|
||||||
synopText = novIdx.synopsis
|
synopText = novIdx.synopsis
|
||||||
if synopText:
|
if synopText:
|
||||||
@@ -814,9 +791,8 @@ class GuiNovelTree(QTreeWidget):
|
|||||||
return
|
return
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _appendMetaTag(refs, key, lines):
|
def _appendMetaTag(refs: dict, key: str, lines: list[str]) -> list[str]:
|
||||||
"""Generate a reference list for a given reference key.
|
"""Generate a reference list for a given reference key."""
|
||||||
"""
|
|
||||||
tags = ", ".join(refs.get(key, []))
|
tags = ", ".join(refs.get(key, []))
|
||||||
if tags:
|
if tags:
|
||||||
lines.append(f"<b>{trConst(nwLabels.KEY_NAME[key])}</b>: {tags}")
|
lines.append(f"<b>{trConst(nwLabels.KEY_NAME[key])}</b>: {tags}")
|
||||||
|
|||||||
@@ -261,6 +261,7 @@ class GuiOutlineToolBar(QToolBar):
|
|||||||
self.novelValue.updateList(includeAll=True)
|
self.novelValue.updateList(includeAll=True)
|
||||||
self.aRefresh.setIcon(SHARED.theme.getIcon("refresh"))
|
self.aRefresh.setIcon(SHARED.theme.getIcon("refresh"))
|
||||||
self.tbColumns.setIcon(SHARED.theme.getIcon("menu"))
|
self.tbColumns.setIcon(SHARED.theme.getIcon("menu"))
|
||||||
|
self.tbColumns.setStyleSheet("QToolButton::menu-indicator {image: none;}")
|
||||||
return
|
return
|
||||||
|
|
||||||
def populateNovelList(self) -> None:
|
def populateNovelList(self) -> None:
|
||||||
|
|||||||
@@ -361,12 +361,13 @@ class GuiProjectToolBar(QWidget):
|
|||||||
"QToolButton {{padding: {0}px; border: none; background: transparent;}} "
|
"QToolButton {{padding: {0}px; border: none; background: transparent;}} "
|
||||||
"QToolButton:hover {{border: none; background: rgba({1},{2},{3},0.2);}}"
|
"QToolButton:hover {{border: none; background: rgba({1},{2},{3},0.2);}}"
|
||||||
).format(CONFIG.pxInt(2), fadeCol.red(), fadeCol.green(), fadeCol.blue())
|
).format(CONFIG.pxInt(2), fadeCol.red(), fadeCol.green(), fadeCol.blue())
|
||||||
|
buttonStyleMenu = f"{buttonStyle} QToolButton::menu-indicator {{image: none;}}"
|
||||||
|
|
||||||
self.tbQuick.setStyleSheet(buttonStyle)
|
self.tbQuick.setStyleSheet(buttonStyleMenu)
|
||||||
self.tbMoveU.setStyleSheet(buttonStyle)
|
self.tbMoveU.setStyleSheet(buttonStyle)
|
||||||
self.tbMoveD.setStyleSheet(buttonStyle)
|
self.tbMoveD.setStyleSheet(buttonStyle)
|
||||||
self.tbAdd.setStyleSheet(buttonStyle)
|
self.tbAdd.setStyleSheet(buttonStyleMenu)
|
||||||
self.tbMore.setStyleSheet(buttonStyle)
|
self.tbMore.setStyleSheet(buttonStyleMenu)
|
||||||
|
|
||||||
self.tbQuick.setIcon(SHARED.theme.getIcon("bookmark"))
|
self.tbQuick.setIcon(SHARED.theme.getIcon("bookmark"))
|
||||||
self.tbMoveU.setIcon(SHARED.theme.getIcon("up"))
|
self.tbMoveU.setIcon(SHARED.theme.getIcon("up"))
|
||||||
|
|||||||
Reference in New Issue
Block a user