Wrap the novel tree in an outer widget
This commit is contained in:
@@ -23,7 +23,7 @@ from novelwriter.gui.doceditor import GuiDocEditor
|
||||
from novelwriter.gui.docviewer import GuiDocViewer, GuiDocViewDetails
|
||||
from novelwriter.gui.itemdetails import GuiItemDetails
|
||||
from novelwriter.gui.mainmenu import GuiMainMenu
|
||||
from novelwriter.gui.noveltree import GuiNovelTree
|
||||
from novelwriter.gui.noveltree import GuiNovelView
|
||||
from novelwriter.gui.outline import GuiOutlineView
|
||||
from novelwriter.gui.projtree import GuiProjectView
|
||||
from novelwriter.gui.statusbar import GuiMainStatus
|
||||
@@ -37,7 +37,7 @@ __all__ = [
|
||||
"GuiItemDetails",
|
||||
"GuiMainMenu",
|
||||
"GuiMainStatus",
|
||||
"GuiNovelTree",
|
||||
"GuiNovelView",
|
||||
"GuiOutlineView",
|
||||
"GuiProjectView",
|
||||
"GuiTheme",
|
||||
|
||||
@@ -30,7 +30,8 @@ from time import time
|
||||
|
||||
from PyQt5.QtCore import Qt, QSize
|
||||
from PyQt5.QtWidgets import (
|
||||
QTreeWidget, QTreeWidgetItem, QAbstractItemView, QFrame
|
||||
QAbstractItemView, QFrame, QTreeWidget, QTreeWidgetItem, QVBoxLayout,
|
||||
QWidget
|
||||
)
|
||||
|
||||
from novelwriter.common import checkInt
|
||||
@@ -39,21 +40,88 @@ from novelwriter.constants import nwKeyWords
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class GuiNovelView(QWidget):
|
||||
|
||||
def __init__(self, mainGui):
|
||||
QWidget.__init__(self, mainGui)
|
||||
|
||||
self.mainGui = mainGui
|
||||
|
||||
# Build GUI
|
||||
self.novelTree = GuiNovelTree(self)
|
||||
self.novelBar = GuiNovelToolBar(self)
|
||||
|
||||
# Assemble
|
||||
self.outerBox = QVBoxLayout()
|
||||
self.outerBox.addWidget(self.novelBar, 0)
|
||||
self.outerBox.addWidget(self.novelTree, 1)
|
||||
self.outerBox.setContentsMargins(0, 0, 0, 0)
|
||||
self.outerBox.setSpacing(0)
|
||||
|
||||
self.setLayout(self.outerBox)
|
||||
|
||||
# Function Mappings
|
||||
self.refreshTree = self.novelTree.refreshTree
|
||||
self.updateWordCounts = self.novelTree.updateWordCounts
|
||||
self.getSelectedHandle = self.novelTree.getSelectedHandle
|
||||
|
||||
return
|
||||
|
||||
##
|
||||
# Methods
|
||||
##
|
||||
|
||||
def initSettings(self):
|
||||
self.novelTree.initSettings()
|
||||
return
|
||||
|
||||
def clearProject(self):
|
||||
self.novelTree.clearTree()
|
||||
return
|
||||
|
||||
def setFocus(self):
|
||||
"""Forward the set focus call to the tree widget.
|
||||
"""
|
||||
self.novelTree.setFocus()
|
||||
return
|
||||
|
||||
def treeFocus(self):
|
||||
"""Check if the novel tree has focus.
|
||||
"""
|
||||
return self.novelTree.hasFocus()
|
||||
|
||||
# END Class GuiNovelView
|
||||
|
||||
|
||||
class GuiNovelToolBar(QWidget):
|
||||
|
||||
def __init__(self, novelView):
|
||||
QTreeWidget.__init__(self, novelView)
|
||||
|
||||
self.mainConf = novelwriter.CONFIG
|
||||
self.novelView = novelView
|
||||
|
||||
return
|
||||
|
||||
# END Class GuiNovelToolBar
|
||||
|
||||
|
||||
class GuiNovelTree(QTreeWidget):
|
||||
|
||||
C_TITLE = 0
|
||||
C_WORDS = 1
|
||||
C_POV = 2
|
||||
|
||||
def __init__(self, mainGui):
|
||||
QTreeWidget.__init__(self, mainGui)
|
||||
def __init__(self, novelView):
|
||||
QTreeWidget.__init__(self, novelView)
|
||||
|
||||
logger.debug("Initialising GuiNovelTree ...")
|
||||
|
||||
self.mainConf = novelwriter.CONFIG
|
||||
self.mainGui = mainGui
|
||||
self.mainTheme = mainGui.mainTheme
|
||||
self.theProject = mainGui.theProject
|
||||
self.novelView = novelView
|
||||
self.mainGui = novelView.mainGui
|
||||
self.mainTheme = novelView.mainGui.mainTheme
|
||||
self.theProject = novelView.mainGui.theProject
|
||||
|
||||
# Internal Variables
|
||||
self._treeMap = {}
|
||||
@@ -97,13 +165,13 @@ class GuiNovelTree(QTreeWidget):
|
||||
self.resizeColumnToContents(self.C_POV)
|
||||
|
||||
# Set custom settings
|
||||
self.initTree()
|
||||
self.initSettings()
|
||||
|
||||
logger.debug("GuiNovelTree initialisation complete")
|
||||
|
||||
return
|
||||
|
||||
def initTree(self):
|
||||
def initSettings(self):
|
||||
"""Set or update tree widget settings.
|
||||
"""
|
||||
# Scroll bars
|
||||
@@ -162,15 +230,6 @@ class GuiNovelTree(QTreeWidget):
|
||||
self._treeMap[titleKey].setText(self.C_WORDS, f"{wCount:n}")
|
||||
return
|
||||
|
||||
def getColumnSizes(self):
|
||||
"""Return the column widths for the tree columns.
|
||||
"""
|
||||
retVals = [
|
||||
self.columnWidth(0),
|
||||
self.columnWidth(1),
|
||||
]
|
||||
return retVals
|
||||
|
||||
def getSelectedHandle(self):
|
||||
"""Get the currently selected handle. If multiple items are
|
||||
selected, return the first.
|
||||
|
||||
@@ -40,7 +40,7 @@ from PyQt5.QtWidgets import (
|
||||
|
||||
from novelwriter.gui import (
|
||||
GuiDocEditor, GuiDocViewDetails, GuiDocViewer, GuiItemDetails, GuiMainMenu,
|
||||
GuiMainStatus, GuiNovelTree, GuiOutlineView, GuiProjectView, GuiTheme,
|
||||
GuiMainStatus, GuiNovelView, GuiOutlineView, GuiProjectView, GuiTheme,
|
||||
GuiViewsBar
|
||||
)
|
||||
from novelwriter.dialogs import (
|
||||
@@ -106,7 +106,7 @@ class GuiMain(QMainWindow):
|
||||
# Main GUI Elements
|
||||
self.statusBar = GuiMainStatus(self)
|
||||
self.projView = GuiProjectView(self)
|
||||
self.novelView = GuiNovelTree(self)
|
||||
self.novelView = GuiNovelView(self)
|
||||
self.docEditor = GuiDocEditor(self)
|
||||
self.viewMeta = GuiDocViewDetails(self)
|
||||
self.docViewer = GuiDocViewer(self)
|
||||
@@ -292,7 +292,7 @@ class GuiMain(QMainWindow):
|
||||
"""
|
||||
# Project Area
|
||||
self.projView.clearProject()
|
||||
self.novelView.clearTree()
|
||||
self.novelView.clearProject()
|
||||
self.itemDetails.clearDetails()
|
||||
|
||||
# Work Area
|
||||
@@ -791,7 +791,7 @@ class GuiMain(QMainWindow):
|
||||
tLine = None
|
||||
if self.projView.treeFocus():
|
||||
tHandle = self.projView.getSelectedHandle()
|
||||
elif self.novelView.hasFocus():
|
||||
elif self.novelView.treeFocus():
|
||||
tHandle, tLine = self.novelView.getSelectedHandle()
|
||||
elif self.outlineView.treeFocus():
|
||||
tHandle, tLine = self.outlineView.getSelectedHandle()
|
||||
@@ -920,7 +920,7 @@ class GuiMain(QMainWindow):
|
||||
self.docEditor.initEditor()
|
||||
self.docViewer.initViewer()
|
||||
self.projView.initSettings()
|
||||
self.novelView.initTree()
|
||||
self.novelView.initSettings()
|
||||
self.outlineView.initOutline()
|
||||
self._updateStatusWordCount()
|
||||
|
||||
@@ -1161,7 +1161,6 @@ class GuiMain(QMainWindow):
|
||||
self.mainConf.setViewPanePos(self.splitView.sizes())
|
||||
|
||||
self.mainConf.setShowRefPanel(self.viewMeta.isVisible())
|
||||
self.mainConf.setNovelColWidths(self.novelView.getColumnSizes())
|
||||
if not self.mainConf.isFullScreen:
|
||||
self.mainConf.setWinSize(self.width(), self.height())
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ from tools import cmpFiles, buildTestProject, XML_IGNORE, writeFile
|
||||
from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtWidgets import QMessageBox, QInputDialog
|
||||
|
||||
from novelwriter.gui import GuiDocEditor, GuiNovelTree, GuiOutlineView
|
||||
from novelwriter.gui import GuiDocEditor, GuiNovelView, GuiOutlineView
|
||||
from novelwriter.enum import nwItemType, nwWidget
|
||||
from novelwriter.tools import GuiProjectWizard
|
||||
from novelwriter.gui.projtree import GuiProjectTree
|
||||
@@ -134,12 +134,12 @@ def testGuiMain_ProjectTreeItems(qtbot, monkeypatch, nwGUI, fncProj, mockRnd):
|
||||
nwGUI.projStack.setCurrentIndex(1)
|
||||
nwGUI.novelView.refreshTree(True)
|
||||
with monkeypatch.context() as mp:
|
||||
mp.setattr(GuiNovelTree, "hasFocus", lambda *a: True)
|
||||
mp.setattr(GuiNovelView, "treeFocus", lambda *a: True)
|
||||
assert nwGUI.docEditor.docHandle() is None
|
||||
actItem = nwGUI.novelView.topLevelItem(0)
|
||||
actItem = nwGUI.novelView.novelTree.topLevelItem(0)
|
||||
chpItem = actItem.child(0)
|
||||
selItem = chpItem.child(0)
|
||||
nwGUI.novelView.setCurrentItem(selItem)
|
||||
nwGUI.novelView.novelTree.setCurrentItem(selItem)
|
||||
nwGUI._keyPressReturn()
|
||||
assert nwGUI.docEditor.docHandle() == sHandle
|
||||
assert nwGUI.closeDocument() is True
|
||||
|
||||
@@ -37,23 +37,24 @@ def testGuiNovelTree_TreeItems(qtbot, monkeypatch, nwGUI, nwMinimal):
|
||||
monkeypatch.setattr(QMessageBox, "information", lambda *a: QMessageBox.Yes)
|
||||
|
||||
nwGUI.openProject(nwMinimal)
|
||||
nwTree = nwGUI.novelView
|
||||
novelView = nwGUI.novelView
|
||||
novelTree = novelView.novelTree
|
||||
|
||||
##
|
||||
# Show/Hide Scrollbars
|
||||
##
|
||||
|
||||
nwTree.mainConf.hideVScroll = True
|
||||
nwTree.mainConf.hideHScroll = True
|
||||
nwTree.initTree()
|
||||
assert not nwTree.verticalScrollBar().isVisible()
|
||||
assert not nwTree.horizontalScrollBar().isVisible()
|
||||
nwGUI.mainConf.hideVScroll = True
|
||||
nwGUI.mainConf.hideHScroll = True
|
||||
novelView.initSettings()
|
||||
assert not novelTree.verticalScrollBar().isVisible()
|
||||
assert not novelTree.horizontalScrollBar().isVisible()
|
||||
|
||||
nwTree.mainConf.hideVScroll = False
|
||||
nwTree.mainConf.hideHScroll = False
|
||||
nwTree.initTree()
|
||||
assert nwTree.verticalScrollBar().isEnabled()
|
||||
assert nwTree.horizontalScrollBar().isEnabled()
|
||||
nwGUI.mainConf.hideVScroll = False
|
||||
nwGUI.mainConf.hideHScroll = False
|
||||
novelView.initSettings()
|
||||
assert novelTree.verticalScrollBar().isEnabled()
|
||||
assert novelTree.horizontalScrollBar().isEnabled()
|
||||
|
||||
##
|
||||
# Populate Tree
|
||||
@@ -61,31 +62,31 @@ def testGuiNovelTree_TreeItems(qtbot, monkeypatch, nwGUI, nwMinimal):
|
||||
|
||||
nwGUI.projStack.setCurrentIndex(nwGUI.idxNovelView)
|
||||
nwGUI.rebuildIndex()
|
||||
nwTree._populateTree()
|
||||
assert nwTree.topLevelItemCount() == 1
|
||||
novelTree._populateTree()
|
||||
assert novelTree.topLevelItemCount() == 1
|
||||
|
||||
# Rebuild should preserve selection
|
||||
topItem = nwTree.topLevelItem(0)
|
||||
topItem = novelTree.topLevelItem(0)
|
||||
assert not topItem.isSelected()
|
||||
topItem.setSelected(True)
|
||||
assert nwTree.selectedItems()[0] == topItem
|
||||
assert nwTree.getSelectedHandle() == ("a35baf2e93843", 0)
|
||||
assert novelTree.selectedItems()[0] == topItem
|
||||
assert novelView.getSelectedHandle() == ("a35baf2e93843", 0)
|
||||
|
||||
nwTree.refreshTree()
|
||||
assert nwTree.topLevelItem(0).isSelected()
|
||||
novelView.refreshTree()
|
||||
assert novelTree.topLevelItem(0).isSelected()
|
||||
|
||||
##
|
||||
# Open Items
|
||||
##
|
||||
|
||||
# Clear selection
|
||||
nwTree.clearSelection()
|
||||
scItem = nwTree.topLevelItem(0).child(0).child(0)
|
||||
novelTree.clearSelection()
|
||||
scItem = novelTree.topLevelItem(0).child(0).child(0)
|
||||
scItem.setSelected(True)
|
||||
assert scItem.isSelected()
|
||||
|
||||
# Clear selection with mouse
|
||||
vPort = nwTree.viewport()
|
||||
vPort = novelTree.viewport()
|
||||
qtbot.mouseClick(vPort, Qt.LeftButton, pos=vPort.rect().center(), delay=10)
|
||||
assert not scItem.isSelected()
|
||||
|
||||
@@ -93,7 +94,7 @@ def testGuiNovelTree_TreeItems(qtbot, monkeypatch, nwGUI, nwMinimal):
|
||||
scItem.setSelected(True)
|
||||
assert scItem.isSelected()
|
||||
assert nwGUI.docEditor.docHandle() is None
|
||||
nwTree._treeDoubleClick(scItem, 0)
|
||||
novelTree._treeDoubleClick(scItem, 0)
|
||||
assert nwGUI.docEditor.docHandle() == "8c659a11cd429"
|
||||
|
||||
# Open item with middle mouse button
|
||||
@@ -103,13 +104,13 @@ def testGuiNovelTree_TreeItems(qtbot, monkeypatch, nwGUI, nwMinimal):
|
||||
qtbot.mouseClick(vPort, Qt.MiddleButton, pos=vPort.rect().center(), delay=10)
|
||||
assert nwGUI.docViewer.docHandle() is None
|
||||
|
||||
scRect = nwTree.visualItemRect(scItem)
|
||||
oldData = scItem.data(nwTree.C_TITLE, Qt.UserRole)
|
||||
scItem.setData(nwTree.C_TITLE, Qt.UserRole, (None, "", ""))
|
||||
scRect = novelTree.visualItemRect(scItem)
|
||||
oldData = scItem.data(novelTree.C_TITLE, Qt.UserRole)
|
||||
scItem.setData(novelTree.C_TITLE, Qt.UserRole, (None, "", ""))
|
||||
qtbot.mouseClick(vPort, Qt.MiddleButton, pos=scRect.center(), delay=10)
|
||||
assert nwGUI.docViewer.docHandle() is None
|
||||
|
||||
scItem.setData(nwTree.C_TITLE, Qt.UserRole, oldData)
|
||||
scItem.setData(novelTree.C_TITLE, Qt.UserRole, oldData)
|
||||
qtbot.mouseClick(vPort, Qt.MiddleButton, pos=scRect.center(), delay=10)
|
||||
assert nwGUI.docViewer.docHandle() == "8c659a11cd429"
|
||||
|
||||
@@ -132,23 +133,23 @@ def testGuiNovelTree_TreeItems(qtbot, monkeypatch, nwGUI, nwMinimal):
|
||||
"#### Section\n\n"
|
||||
))
|
||||
nwGUI.rebuildIndex()
|
||||
nwTree._populateTree()
|
||||
assert nwTree.topLevelItem(0).text(nwTree.C_TITLE) == "Section wo/Scene"
|
||||
assert nwTree.topLevelItem(1).text(nwTree.C_TITLE) == "Scene wo/Chapter"
|
||||
assert nwTree.topLevelItem(2).text(nwTree.C_TITLE) == "Chapter wo/Title"
|
||||
assert nwTree.topLevelItem(3).text(nwTree.C_TITLE) == "Title"
|
||||
novelTree._populateTree()
|
||||
assert novelTree.topLevelItem(0).text(novelTree.C_TITLE) == "Section wo/Scene"
|
||||
assert novelTree.topLevelItem(1).text(novelTree.C_TITLE) == "Scene wo/Chapter"
|
||||
assert novelTree.topLevelItem(2).text(novelTree.C_TITLE) == "Chapter wo/Title"
|
||||
assert novelTree.topLevelItem(3).text(novelTree.C_TITLE) == "Title"
|
||||
|
||||
tTitle = nwTree.topLevelItem(3)
|
||||
assert tTitle.child(0).text(nwTree.C_TITLE) == "Section w/Title, wo/Scene"
|
||||
assert tTitle.child(1).text(nwTree.C_TITLE) == "Scene w/Title, wo/Chapter"
|
||||
assert tTitle.child(2).text(nwTree.C_TITLE) == "Chapter"
|
||||
tTitle = novelTree.topLevelItem(3)
|
||||
assert tTitle.child(0).text(novelTree.C_TITLE) == "Section w/Title, wo/Scene"
|
||||
assert tTitle.child(1).text(novelTree.C_TITLE) == "Scene w/Title, wo/Chapter"
|
||||
assert tTitle.child(2).text(novelTree.C_TITLE) == "Chapter"
|
||||
|
||||
tChap = tTitle.child(2)
|
||||
assert tChap.child(0).text(nwTree.C_TITLE) == "Section w/Chapter, wo/Scene"
|
||||
assert tChap.child(1).text(nwTree.C_TITLE) == "Scene"
|
||||
assert tChap.child(0).text(novelTree.C_TITLE) == "Section w/Chapter, wo/Scene"
|
||||
assert tChap.child(1).text(novelTree.C_TITLE) == "Scene"
|
||||
|
||||
tScene = tChap.child(1)
|
||||
assert tScene.child(0).text(nwTree.C_TITLE) == "Section"
|
||||
assert tScene.child(0).text(novelTree.C_TITLE) == "Section"
|
||||
|
||||
##
|
||||
# Close
|
||||
|
||||
Reference in New Issue
Block a user