Add a toolbar to the Outline view
This commit is contained in:
@@ -59,7 +59,6 @@ The main shorcuts are as follows:
|
|||||||
":kbd:`Ctrl`:kbd:`Y`", "Redo latest undo."
|
":kbd:`Ctrl`:kbd:`Y`", "Redo latest undo."
|
||||||
":kbd:`Ctrl`:kbd:`Z`", "Undo latest changes."
|
":kbd:`Ctrl`:kbd:`Z`", "Undo latest changes."
|
||||||
":kbd:`Ctrl`:kbd:`F7`", "Toggle spell checking."
|
":kbd:`Ctrl`:kbd:`F7`", "Toggle spell checking."
|
||||||
":kbd:`Ctrl`:kbd:`F10`", "Toggle automatic updating of project outline."
|
|
||||||
":kbd:`Ctrl`:kbd:`Up`", "Move item one step up in the project tree."
|
":kbd:`Ctrl`:kbd:`Up`", "Move item one step up in the project tree."
|
||||||
":kbd:`Ctrl`:kbd:`Down`", "Move item one step down in the project tree."
|
":kbd:`Ctrl`:kbd:`Down`", "Move item one step down in the project tree."
|
||||||
":kbd:`Ctrl`:kbd:`Del`", "Delete next word in editor."
|
":kbd:`Ctrl`:kbd:`Del`", "Delete next word in editor."
|
||||||
@@ -88,7 +87,6 @@ The main shorcuts are as follows:
|
|||||||
":kbd:`F7`", "Re-run spell checker."
|
":kbd:`F7`", "Re-run spell checker."
|
||||||
":kbd:`F8`", "Activate :guilabel:`Focus Mode`, hiding the project tree and document viewer."
|
":kbd:`F8`", "Activate :guilabel:`Focus Mode`, hiding the project tree and document viewer."
|
||||||
":kbd:`F9`", "Re-build the project index."
|
":kbd:`F9`", "Re-build the project index."
|
||||||
":kbd:`F10`", "Re-build the project outline."
|
|
||||||
":kbd:`F11`", "Activate full screen mode."
|
":kbd:`F11`", "Activate full screen mode."
|
||||||
":kbd:`Shift`:kbd:`F1`", "Open the local user manual (PDF) if it is available."
|
":kbd:`Shift`:kbd:`F1`", "Open the local user manual (PDF) if it is available."
|
||||||
":kbd:`Shift`:kbd:`F3`", "Find previous occurrence of search word in current document."
|
":kbd:`Shift`:kbd:`F3`", "Find previous occurrence of search word in current document."
|
||||||
|
|||||||
@@ -273,6 +273,15 @@ class NWTree():
|
|||||||
rootClasses.add(nwItem.itemClass)
|
rootClasses.add(nwItem.itemClass)
|
||||||
return rootClasses
|
return rootClasses
|
||||||
|
|
||||||
|
def novelRoots(self):
|
||||||
|
"""Return a doctionary of all novel-like root items.
|
||||||
|
"""
|
||||||
|
novelItems = {}
|
||||||
|
for tHandle, nwItem in self._treeRoots.items():
|
||||||
|
if nwItem.isNovelLike():
|
||||||
|
novelItems[tHandle] = nwItem
|
||||||
|
return novelItems
|
||||||
|
|
||||||
def isRoot(self, tHandle):
|
def isRoot(self, tHandle):
|
||||||
"""Check if a handle is a root item.
|
"""Check if a handle is a root item.
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -81,12 +81,6 @@ class GuiMainMenu(QMenuBar):
|
|||||||
self.aSpellCheck.setChecked(theMode)
|
self.aSpellCheck.setChecked(theMode)
|
||||||
return
|
return
|
||||||
|
|
||||||
def setAutoOutline(self, theMode):
|
|
||||||
"""Forward auto outline check state to its action.
|
|
||||||
"""
|
|
||||||
self.aAutoOutline.setChecked(theMode)
|
|
||||||
return
|
|
||||||
|
|
||||||
def setFocusMode(self, theMode):
|
def setFocusMode(self, theMode):
|
||||||
"""Forward focus mode check state to its action.
|
"""Forward focus mode check state to its action.
|
||||||
"""
|
"""
|
||||||
@@ -105,12 +99,6 @@ class GuiMainMenu(QMenuBar):
|
|||||||
self.theParent.docEditor.toggleSpellCheck(None)
|
self.theParent.docEditor.toggleSpellCheck(None)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _toggleAutoOutline(self, theMode):
|
|
||||||
"""Toggle auto outline when the menu entry is checked.
|
|
||||||
"""
|
|
||||||
self.theProject.setAutoOutline(theMode)
|
|
||||||
return True
|
|
||||||
|
|
||||||
def _openWebsite(self, theUrl):
|
def _openWebsite(self, theUrl):
|
||||||
"""Open a URL in the system's default browser.
|
"""Open a URL in the system's default browser.
|
||||||
"""
|
"""
|
||||||
@@ -889,19 +877,6 @@ class GuiMainMenu(QMenuBar):
|
|||||||
self.aRebuildIndex.triggered.connect(lambda: self.theParent.rebuildIndex())
|
self.aRebuildIndex.triggered.connect(lambda: self.theParent.rebuildIndex())
|
||||||
self.toolsMenu.addAction(self.aRebuildIndex)
|
self.toolsMenu.addAction(self.aRebuildIndex)
|
||||||
|
|
||||||
# Tools > Rebuild Outline
|
|
||||||
self.aRebuildOutline = QAction(self.tr("Rebuild Outline"), self)
|
|
||||||
self.aRebuildOutline.setShortcut("F10")
|
|
||||||
self.aRebuildOutline.triggered.connect(lambda: self.theParent.rebuildOutline())
|
|
||||||
self.toolsMenu.addAction(self.aRebuildOutline)
|
|
||||||
|
|
||||||
# Tools > Toggle Auto Build Outline
|
|
||||||
self.aAutoOutline = QAction(self.tr("Auto-Update Outline"), self)
|
|
||||||
self.aAutoOutline.setCheckable(True)
|
|
||||||
self.aAutoOutline.toggled.connect(self._toggleAutoOutline)
|
|
||||||
self.aAutoOutline.setShortcut("Ctrl+F10")
|
|
||||||
self.toolsMenu.addAction(self.aAutoOutline)
|
|
||||||
|
|
||||||
# Tools > Separator
|
# Tools > Separator
|
||||||
self.toolsMenu.addSeparator()
|
self.toolsMenu.addSeparator()
|
||||||
|
|
||||||
|
|||||||
+150
-45
@@ -4,9 +4,11 @@ novelWriter – GUI Project Outline
|
|||||||
GUI class for the project outline view
|
GUI class for the project outline view
|
||||||
|
|
||||||
File History:
|
File History:
|
||||||
Created: 2019-11-16 [0.4.1] GuiOutlineView, GuiOutlineHeaderMenu
|
|
||||||
Created: 2020-06-02 [0.7.0] GuiOutlineDetails
|
|
||||||
Created: 2022-05-15 [1.7b1] GuiOutline
|
Created: 2022-05-15 [1.7b1] GuiOutline
|
||||||
|
Created: 2022-05-22 [1.7b1] GuiOutlineToolBar
|
||||||
|
Created: 2019-11-16 [0.4.1] GuiOutlineView
|
||||||
|
Created: 2019-11-16 [0.4.1] GuiOutlineHeaderMenu
|
||||||
|
Created: 2020-06-02 [0.7.0] GuiOutlineDetails
|
||||||
|
|
||||||
This file is a part of novelWriter
|
This file is a part of novelWriter
|
||||||
Copyright 2018–2022, Veronica Berglyd Olsen
|
Copyright 2018–2022, Veronica Berglyd Olsen
|
||||||
@@ -29,6 +31,7 @@ import logging
|
|||||||
import novelwriter
|
import novelwriter
|
||||||
|
|
||||||
from time import time
|
from time import time
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
from PyQt5.QtCore import (
|
from PyQt5.QtCore import (
|
||||||
Qt, pyqtSignal, pyqtSlot, QSize, QT_TRANSLATE_NOOP
|
Qt, pyqtSignal, pyqtSlot, QSize, QT_TRANSLATE_NOOP
|
||||||
@@ -36,7 +39,7 @@ from PyQt5.QtCore import (
|
|||||||
from PyQt5.QtWidgets import (
|
from PyQt5.QtWidgets import (
|
||||||
QAbstractItemView, QAction, QGridLayout, QGroupBox, QHBoxLayout, QLabel,
|
QAbstractItemView, QAction, QGridLayout, QGroupBox, QHBoxLayout, QLabel,
|
||||||
QMenu, QScrollArea, QSplitter, QTreeWidget, QTreeWidgetItem, QVBoxLayout,
|
QMenu, QScrollArea, QSplitter, QTreeWidget, QTreeWidgetItem, QVBoxLayout,
|
||||||
QWidget, QFrame
|
QWidget, QFrame, QToolBar, QSizePolicy, QComboBox, QToolButton
|
||||||
)
|
)
|
||||||
|
|
||||||
from novelwriter.enum import (
|
from novelwriter.enum import (
|
||||||
@@ -60,6 +63,7 @@ class GuiOutline(QWidget):
|
|||||||
self.theParent = theParent
|
self.theParent = theParent
|
||||||
self.theProject = theParent.theProject
|
self.theProject = theParent.theProject
|
||||||
|
|
||||||
|
self.outlineBar = GuiOutlineToolBar(self)
|
||||||
self.outlineView = GuiOutlineView(self)
|
self.outlineView = GuiOutlineView(self)
|
||||||
self.outlineData = GuiOutlineDetails(self)
|
self.outlineData = GuiOutlineDetails(self)
|
||||||
|
|
||||||
@@ -71,13 +75,20 @@ class GuiOutline(QWidget):
|
|||||||
# Assemble
|
# Assemble
|
||||||
self.outerBox = QVBoxLayout()
|
self.outerBox = QVBoxLayout()
|
||||||
self.outerBox.setContentsMargins(0, 0, 0, 0)
|
self.outerBox.setContentsMargins(0, 0, 0, 0)
|
||||||
|
self.outerBox.addWidget(self.outlineBar)
|
||||||
self.outerBox.addWidget(self.splitOutline)
|
self.outerBox.addWidget(self.splitOutline)
|
||||||
|
|
||||||
self.setLayout(self.outerBox)
|
self.setLayout(self.outerBox)
|
||||||
|
|
||||||
|
# Connect Signals
|
||||||
|
self.outlineView.hiddenStateChanged.connect(self._updateMenuColumns)
|
||||||
|
self.outlineBar.columnToggled.connect(self.outlineView.menuColumnToggled)
|
||||||
|
self.outlineBar.viewRefreshRequested.connect(
|
||||||
|
lambda: self.outlineView.refreshTree(overRide=True)
|
||||||
|
)
|
||||||
|
|
||||||
# Function Mappings
|
# Function Mappings
|
||||||
self.getSelectedHandle = self.outlineView.getSelectedHandle
|
self.getSelectedHandle = self.outlineView.getSelectedHandle
|
||||||
self.updateClasses = self.outlineData.updateClasses
|
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -112,9 +123,112 @@ class GuiOutline(QWidget):
|
|||||||
def setTreeFocus(self):
|
def setTreeFocus(self):
|
||||||
return self.outlineView.setFocus()
|
return self.outlineView.setFocus()
|
||||||
|
|
||||||
|
##
|
||||||
|
# Slots
|
||||||
|
##
|
||||||
|
|
||||||
|
@pyqtSlot()
|
||||||
|
def projectUpdated(self):
|
||||||
|
"""Should be called whenever the number of root folders change.
|
||||||
|
"""
|
||||||
|
self.outlineBar.populateNovelList()
|
||||||
|
self.outlineData.updateClasses()
|
||||||
|
return
|
||||||
|
|
||||||
|
@pyqtSlot()
|
||||||
|
def _updateMenuColumns(self):
|
||||||
|
"""Trigger an update of the toggled state of the column menu
|
||||||
|
checkboxes whenever a signal is received that the hidden state
|
||||||
|
of columns has changed.
|
||||||
|
"""
|
||||||
|
self.outlineBar.setColumnHiddenState(self.outlineView.hiddenColumns)
|
||||||
|
return
|
||||||
|
|
||||||
# END Class GuiOutline
|
# END Class GuiOutline
|
||||||
|
|
||||||
|
|
||||||
|
class GuiOutlineToolBar(QToolBar):
|
||||||
|
|
||||||
|
columnToggled = pyqtSignal(bool, Enum)
|
||||||
|
viewRefreshRequested = pyqtSignal()
|
||||||
|
|
||||||
|
def __init__(self, theOutline):
|
||||||
|
QTreeWidget.__init__(self, theOutline)
|
||||||
|
|
||||||
|
logger.debug("Initialising GuiOutlineToolBar ...")
|
||||||
|
|
||||||
|
self.mainConf = novelwriter.CONFIG
|
||||||
|
self.theOutline = theOutline
|
||||||
|
self.theParent = theOutline.theParent
|
||||||
|
self.theProject = theOutline.theParent.theProject
|
||||||
|
self.theTheme = theOutline.theParent.theTheme
|
||||||
|
|
||||||
|
iPx = self.mainConf.pxInt(22)
|
||||||
|
mPx = self.mainConf.pxInt(12)
|
||||||
|
|
||||||
|
self.setMovable(False)
|
||||||
|
self.setIconSize(QSize(iPx, iPx))
|
||||||
|
self.setContentsMargins(0, 0, 0, 0)
|
||||||
|
self.setStyleSheet("QToolBar {border: 0px;}")
|
||||||
|
|
||||||
|
stretch = QWidget(self)
|
||||||
|
stretch.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
|
||||||
|
|
||||||
|
# Novel Selector
|
||||||
|
self.novelLabel = QLabel(self.tr("Outline of"))
|
||||||
|
self.novelLabel.setContentsMargins(0, 0, mPx, 0)
|
||||||
|
|
||||||
|
self.novelValue = QComboBox(self)
|
||||||
|
self.novelValue.setMinimumWidth(self.mainConf.pxInt(200))
|
||||||
|
|
||||||
|
# Actions
|
||||||
|
self.aRefresh = QAction(self.tr("Refresh"), self)
|
||||||
|
self.aRefresh.setIcon(self.theTheme.getIcon("refresh"))
|
||||||
|
self.aRefresh.triggered.connect(
|
||||||
|
lambda: self.viewRefreshRequested.emit()
|
||||||
|
)
|
||||||
|
|
||||||
|
# Column Menu
|
||||||
|
self.mColumns = GuiOutlineHeaderMenu(self)
|
||||||
|
self.mColumns.columnToggled.connect(
|
||||||
|
lambda isChecked, tItem: self.columnToggled.emit(isChecked, tItem)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.tbColumns = QToolButton(self)
|
||||||
|
self.tbColumns.setIcon(self.theTheme.getIcon("menu"))
|
||||||
|
self.tbColumns.setMenu(self.mColumns)
|
||||||
|
self.tbColumns.setPopupMode(QToolButton.InstantPopup)
|
||||||
|
|
||||||
|
# Assemble
|
||||||
|
self.addWidget(self.novelLabel)
|
||||||
|
self.addWidget(self.novelValue)
|
||||||
|
self.addSeparator()
|
||||||
|
self.addAction(self.aRefresh)
|
||||||
|
self.addWidget(self.tbColumns)
|
||||||
|
self.addWidget(stretch)
|
||||||
|
|
||||||
|
self.populateNovelList()
|
||||||
|
|
||||||
|
logger.debug("GuiOutlineToolBar initialisation complete")
|
||||||
|
|
||||||
|
def populateNovelList(self):
|
||||||
|
"""Fill the novel combo box.
|
||||||
|
"""
|
||||||
|
self.novelValue.clear()
|
||||||
|
for tHandle, nwItem in self.theProject.projTree.novelRoots().items():
|
||||||
|
self.novelValue.addItem(
|
||||||
|
self.theTheme.getIcon(nwLabels.CLASS_ICON[nwItem.itemClass]),
|
||||||
|
nwItem.itemName, tHandle
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
def setColumnHiddenState(self, hiddenState):
|
||||||
|
self.mColumns.setHiddenState(hiddenState)
|
||||||
|
return
|
||||||
|
|
||||||
|
# END Class GuiOutlineToolBar
|
||||||
|
|
||||||
|
|
||||||
class GuiOutlineView(QTreeWidget):
|
class GuiOutlineView(QTreeWidget):
|
||||||
|
|
||||||
DEF_WIDTH = {
|
DEF_WIDTH = {
|
||||||
@@ -157,10 +271,12 @@ class GuiOutlineView(QTreeWidget):
|
|||||||
nwOutline.SYNOP: False,
|
nwOutline.SYNOP: False,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hiddenStateChanged = pyqtSignal()
|
||||||
|
|
||||||
def __init__(self, theOutline):
|
def __init__(self, theOutline):
|
||||||
QTreeWidget.__init__(self, theOutline)
|
QTreeWidget.__init__(self, theOutline)
|
||||||
|
|
||||||
logger.debug("Initialising GuiOutline ...")
|
logger.debug("Initialising GuiOutlineView ...")
|
||||||
|
|
||||||
self.mainConf = novelwriter.CONFIG
|
self.mainConf = novelwriter.CONFIG
|
||||||
self.theOutline = theOutline
|
self.theOutline = theOutline
|
||||||
@@ -169,7 +285,6 @@ class GuiOutlineView(QTreeWidget):
|
|||||||
self.theTheme = theOutline.theParent.theTheme
|
self.theTheme = theOutline.theParent.theTheme
|
||||||
self.theIndex = theOutline.theParent.theIndex
|
self.theIndex = theOutline.theParent.theIndex
|
||||||
self.optState = theOutline.theParent.theProject.optState
|
self.optState = theOutline.theParent.theProject.optState
|
||||||
self.headerMenu = GuiOutlineHeaderMenu(self)
|
|
||||||
|
|
||||||
self.setFrameStyle(QFrame.NoFrame)
|
self.setFrameStyle(QFrame.NoFrame)
|
||||||
self.setSelectionBehavior(QAbstractItemView.SelectRows)
|
self.setSelectionBehavior(QAbstractItemView.SelectRows)
|
||||||
@@ -184,8 +299,6 @@ class GuiOutlineView(QTreeWidget):
|
|||||||
self.setIndentation(iPx)
|
self.setIndentation(iPx)
|
||||||
|
|
||||||
self.treeHead = self.header()
|
self.treeHead = self.header()
|
||||||
self.treeHead.setContextMenuPolicy(Qt.CustomContextMenu)
|
|
||||||
self.treeHead.customContextMenuRequested.connect(self._headerRightClick)
|
|
||||||
self.treeHead.sectionMoved.connect(self._columnMoved)
|
self.treeHead.sectionMoved.connect(self._columnMoved)
|
||||||
|
|
||||||
# Internals
|
# Internals
|
||||||
@@ -199,12 +312,25 @@ class GuiOutlineView(QTreeWidget):
|
|||||||
|
|
||||||
self.initOutline()
|
self.initOutline()
|
||||||
self.clearOutline()
|
self.clearOutline()
|
||||||
self.headerMenu.setHiddenState(self._colHidden)
|
|
||||||
|
|
||||||
logger.debug("GuiOutline initialisation complete")
|
self.hiddenStateChanged.emit()
|
||||||
|
|
||||||
|
logger.debug("GuiOutlineView initialisation complete")
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
##
|
||||||
|
# Properties
|
||||||
|
##
|
||||||
|
|
||||||
|
@property
|
||||||
|
def hiddenColumns(self):
|
||||||
|
return self._colHidden
|
||||||
|
|
||||||
|
##
|
||||||
|
# Methods
|
||||||
|
##
|
||||||
|
|
||||||
def initOutline(self):
|
def initOutline(self):
|
||||||
"""Set or update outline settings.
|
"""Set or update outline settings.
|
||||||
"""
|
"""
|
||||||
@@ -314,13 +440,6 @@ class GuiOutlineView(QTreeWidget):
|
|||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
@pyqtSlot("QPoint")
|
|
||||||
def _headerRightClick(self, clickPos):
|
|
||||||
"""Show the header column menu.
|
|
||||||
"""
|
|
||||||
self.headerMenu.exec_(self.mapToGlobal(clickPos))
|
|
||||||
return
|
|
||||||
|
|
||||||
@pyqtSlot(int, int, int)
|
@pyqtSlot(int, int, int)
|
||||||
def _columnMoved(self, logIdx, oldVisualIdx, newVisualIdx):
|
def _columnMoved(self, logIdx, oldVisualIdx, newVisualIdx):
|
||||||
"""Make sure the order array is up to date with the actual order
|
"""Make sure the order array is up to date with the actual order
|
||||||
@@ -330,9 +449,10 @@ class GuiOutlineView(QTreeWidget):
|
|||||||
self._saveHeaderState()
|
self._saveHeaderState()
|
||||||
return
|
return
|
||||||
|
|
||||||
def _menuColumnToggled(self, isChecked, theItem):
|
@pyqtSlot(bool, Enum)
|
||||||
|
def menuColumnToggled(self, isChecked, theItem):
|
||||||
"""Receive the changes to column visibility forwarded by the
|
"""Receive the changes to column visibility forwarded by the
|
||||||
header context menu.
|
column selection menu.
|
||||||
"""
|
"""
|
||||||
logger.verbose("User toggled Outline column '%s'", theItem.name)
|
logger.verbose("User toggled Outline column '%s'", theItem.name)
|
||||||
if theItem in self._colIdx:
|
if theItem in self._colIdx:
|
||||||
@@ -389,7 +509,7 @@ class GuiOutlineView(QTreeWidget):
|
|||||||
except Exception:
|
except Exception:
|
||||||
logger.warning("Ignored unknown outline column '%s'", str(hName))
|
logger.warning("Ignored unknown outline column '%s'", str(hName))
|
||||||
|
|
||||||
self.headerMenu.setHiddenState(self._colHidden)
|
self.hiddenStateChanged.emit()
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -558,10 +678,11 @@ class GuiOutlineView(QTreeWidget):
|
|||||||
|
|
||||||
class GuiOutlineHeaderMenu(QMenu):
|
class GuiOutlineHeaderMenu(QMenu):
|
||||||
|
|
||||||
def __init__(self, theParent):
|
columnToggled = pyqtSignal(bool, Enum)
|
||||||
QMenu.__init__(self, theParent)
|
|
||||||
|
def __init__(self, theOutline):
|
||||||
|
QMenu.__init__(self, theOutline)
|
||||||
|
|
||||||
self.theParent = theParent
|
|
||||||
self.acceptToggle = True
|
self.acceptToggle = True
|
||||||
|
|
||||||
mnuHead = QAction(self.tr("Select Columns"), self)
|
mnuHead = QAction(self.tr("Select Columns"), self)
|
||||||
@@ -575,7 +696,7 @@ class GuiOutlineHeaderMenu(QMenu):
|
|||||||
self.actionMap[hItem] = QAction(trConst(nwLabels.OUTLINE_COLS[hItem]), self)
|
self.actionMap[hItem] = QAction(trConst(nwLabels.OUTLINE_COLS[hItem]), self)
|
||||||
self.actionMap[hItem].setCheckable(True)
|
self.actionMap[hItem].setCheckable(True)
|
||||||
self.actionMap[hItem].toggled.connect(
|
self.actionMap[hItem].toggled.connect(
|
||||||
lambda isChecked, tItem=hItem: self._columnToggled(isChecked, tItem)
|
lambda isChecked, tItem=hItem: self.columnToggled.emit(isChecked, tItem)
|
||||||
)
|
)
|
||||||
self.addAction(self.actionMap[hItem])
|
self.addAction(self.actionMap[hItem])
|
||||||
|
|
||||||
@@ -596,18 +717,6 @@ class GuiOutlineHeaderMenu(QMenu):
|
|||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
##
|
|
||||||
# Slots
|
|
||||||
##
|
|
||||||
|
|
||||||
def _columnToggled(self, isChecked, theItem):
|
|
||||||
"""The user has toggled the visibility of a column. Forward the
|
|
||||||
event to the parent class only if we're accepting changes.
|
|
||||||
"""
|
|
||||||
if self.acceptToggle:
|
|
||||||
self.theParent._menuColumnToggled(isChecked, theItem)
|
|
||||||
return
|
|
||||||
|
|
||||||
# END Class GuiOutlineHeaderMenu
|
# END Class GuiOutlineHeaderMenu
|
||||||
|
|
||||||
|
|
||||||
@@ -945,16 +1054,12 @@ class GuiOutlineDetails(QScrollArea):
|
|||||||
# Internal Functions
|
# Internal Functions
|
||||||
##
|
##
|
||||||
|
|
||||||
def _formatTags(self, theRefs, theKey):
|
def _formatTags(self, refs, key):
|
||||||
"""Format the tags as clickable links.
|
"""Format the tags as clickable links.
|
||||||
"""
|
"""
|
||||||
if theKey not in theRefs:
|
mKey = key[1:]
|
||||||
return ""
|
return ", ".join(
|
||||||
refTags = []
|
[f"<a href='#{mKey}={tag}'>{tag}</a>" for tag in refs.get(key, [])]
|
||||||
for tTag in theRefs[theKey]:
|
)
|
||||||
refTags.append("<a href='#%s=%s'>%s</a>" % (
|
|
||||||
theKey[1:], tTag, tTag
|
|
||||||
))
|
|
||||||
return ", ".join(refTags)
|
|
||||||
|
|
||||||
# END Class GuiOutlineDetails
|
# END Class GuiOutlineDetails
|
||||||
|
|||||||
+3
-17
@@ -126,7 +126,7 @@ class GuiMain(QMainWindow):
|
|||||||
self.treeView.itemDoubleClicked.connect(self._treeDoubleClick)
|
self.treeView.itemDoubleClicked.connect(self._treeDoubleClick)
|
||||||
self.treeView.novelItemChanged.connect(self._treeNovelItemChanged)
|
self.treeView.novelItemChanged.connect(self._treeNovelItemChanged)
|
||||||
self.treeView.wordCountsChanged.connect(self._updateStatusWordCount)
|
self.treeView.wordCountsChanged.connect(self._updateStatusWordCount)
|
||||||
self.treeView.rootFoldersChanged.connect(self.projView.updateClasses)
|
self.treeView.rootFoldersChanged.connect(self.projView.projectUpdated)
|
||||||
|
|
||||||
self.viewsBar.viewChangeRequested.connect(self._changeView)
|
self.viewsBar.viewChangeRequested.connect(self._changeView)
|
||||||
self.projView.viewChangeRequested.connect(self._changeView)
|
self.projView.viewChangeRequested.connect(self._changeView)
|
||||||
@@ -353,7 +353,7 @@ class GuiMain(QMainWindow):
|
|||||||
self.rebuildTrees()
|
self.rebuildTrees()
|
||||||
self.saveProject()
|
self.saveProject()
|
||||||
self.docEditor.setDictionaries()
|
self.docEditor.setDictionaries()
|
||||||
self.projView.updateClasses()
|
self.projView.projectUpdated()
|
||||||
self.rebuildIndex(beQuiet=True)
|
self.rebuildIndex(beQuiet=True)
|
||||||
self.statusBar.setRefTime(self.theProject.projOpened)
|
self.statusBar.setRefTime(self.theProject.projOpened)
|
||||||
self.statusBar.setProjectStatus(nwState.GOOD)
|
self.statusBar.setProjectStatus(nwState.GOOD)
|
||||||
@@ -499,9 +499,8 @@ class GuiMain(QMainWindow):
|
|||||||
self.rebuildTrees()
|
self.rebuildTrees()
|
||||||
self.docEditor.setDictionaries()
|
self.docEditor.setDictionaries()
|
||||||
self.docEditor.toggleSpellCheck(self.theProject.spellCheck)
|
self.docEditor.toggleSpellCheck(self.theProject.spellCheck)
|
||||||
self.mainMenu.setAutoOutline(self.theProject.autoOutline)
|
|
||||||
self.statusBar.setRefTime(self.theProject.projOpened)
|
self.statusBar.setRefTime(self.theProject.projOpened)
|
||||||
self.projView.updateClasses()
|
self.projView.projectUpdated()
|
||||||
self._updateStatusWordCount()
|
self._updateStatusWordCount()
|
||||||
|
|
||||||
# Restore previously open documents, if any
|
# Restore previously open documents, if any
|
||||||
@@ -895,19 +894,6 @@ class GuiMain(QMainWindow):
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def rebuildOutline(self):
|
|
||||||
"""Force a rebuild of the Outline view.
|
|
||||||
"""
|
|
||||||
if not self.hasProject:
|
|
||||||
logger.error("No project open")
|
|
||||||
return False
|
|
||||||
|
|
||||||
logger.verbose("Forcing a rebuild of the Project Outline")
|
|
||||||
self._changeView(nwView.OUTLINE)
|
|
||||||
self.projView.refreshView(overRide=True)
|
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
##
|
##
|
||||||
# Main Dialogs
|
# Main Dialogs
|
||||||
##
|
##
|
||||||
|
|||||||
@@ -61,7 +61,6 @@ def testGuiMain_ProjectBlocker(monkeypatch, nwGUI):
|
|||||||
assert nwGUI.editItem() is False
|
assert nwGUI.editItem() is False
|
||||||
assert nwGUI.requestNovelTreeRefresh() is False
|
assert nwGUI.requestNovelTreeRefresh() is False
|
||||||
assert nwGUI.rebuildIndex() is False
|
assert nwGUI.rebuildIndex() is False
|
||||||
assert nwGUI.rebuildOutline() is False
|
|
||||||
assert nwGUI.showProjectSettingsDialog() is False
|
assert nwGUI.showProjectSettingsDialog() is False
|
||||||
assert nwGUI.showProjectDetailsDialog() is False
|
assert nwGUI.showProjectDetailsDialog() is False
|
||||||
assert nwGUI.showBuildProjectDialog() is False
|
assert nwGUI.showBuildProjectDialog() is False
|
||||||
|
|||||||
@@ -21,10 +21,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from PyQt5.QtCore import Qt, QPoint
|
from PyQt5.QtWidgets import QTreeWidgetItem, QMessageBox
|
||||||
from PyQt5.QtWidgets import QAction, QTreeWidgetItem, QMessageBox
|
|
||||||
|
|
||||||
from novelwriter.enum import nwOutline
|
|
||||||
|
|
||||||
keyDelay = 2
|
keyDelay = 2
|
||||||
typeDelay = 1
|
typeDelay = 1
|
||||||
@@ -51,16 +48,16 @@ def testGuiOutline_Main(qtbot, monkeypatch, nwGUI, nwLipsum):
|
|||||||
assert outlineView.topLevelItemCount() > 0
|
assert outlineView.topLevelItemCount() > 0
|
||||||
|
|
||||||
# Context Menu
|
# Context Menu
|
||||||
outlineView._headerRightClick(QPoint(1, 1))
|
# outlineView._headerRightClick(QPoint(1, 1))
|
||||||
outlineView.headerMenu.actionMap[nwOutline.CCOUNT].activate(QAction.Trigger)
|
# outlineView.headerMenu.actionMap[nwOutline.CCOUNT].activate(QAction.Trigger)
|
||||||
outlineView.headerMenu.close()
|
# outlineView.headerMenu.close()
|
||||||
qtbot.mouseClick(outlineView, Qt.LeftButton)
|
# qtbot.mouseClick(outlineView, Qt.LeftButton)
|
||||||
|
|
||||||
outlineView._loadHeaderState()
|
# outlineView._loadHeaderState()
|
||||||
assert not outlineView._colHidden[nwOutline.CCOUNT]
|
# assert not outlineView._colHidden[nwOutline.CCOUNT]
|
||||||
|
|
||||||
# First Item
|
# First Item
|
||||||
nwGUI.rebuildOutline()
|
outlineView.refreshTree()
|
||||||
selItem = outlineView.topLevelItem(0)
|
selItem = outlineView.topLevelItem(0)
|
||||||
assert isinstance(selItem, QTreeWidgetItem)
|
assert isinstance(selItem, QTreeWidgetItem)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user