Restructured the way column state is preserved in the Outline tree

This commit is contained in:
Veronica K. B. Olsen
2020-03-10 23:18:58 +01:00
parent c9657a3515
commit 32c6d80efb
2 changed files with 134 additions and 103 deletions
+1 -1
View File
@@ -22,4 +22,4 @@ __all__ = [
"nwItemClass",
"nwItemLayout",
"nwItemType",
]
]
+133 -102
View File
@@ -15,10 +15,11 @@ import nw
from os import path
from time import time
from enum import Enum
from PyQt5.QtCore import Qt, QByteArray
from PyQt5.QtWidgets import (
QWidget, QVBoxLayout, QTreeWidget, QTreeWidgetItem,
QWidget, QVBoxLayout, QTreeWidget, QTreeWidgetItem, QMenu, QAction,
QAbstractItemView
)
@@ -26,44 +27,46 @@ from nw.constants import nwKeyWords, nwLabels
logger = logging.getLogger(__name__)
class HCols(Enum):
TITLE = 0
LEVEL = 1
LABEL = 2
LINE = 3
WCOUNT = 4
CCOUNT = 5
PCOUNT = 6
SYNOP = 7
POV = 8
CHAR = 9
PLOT = 10
TIME = 11
WORLD = 12
OBJECT = 13
ENTITY = 14
CUSTOM = 15
# END Enum HCols
class GuiProjectOutline(QTreeWidget):
I_TITLE = 0
I_LEVEL = 1
I_LABEL = 2
I_LINE = 3
I_WCOUNT = 4
I_CCOUNT = 5
I_PCOUNT = 6
I_SYNOP = 7
I_POV = 8
I_CHAR = 9
I_PLOT = 10
I_TIME = 11
I_WORLD = 12
I_OBJECT = 13
I_ENTITY = 14
I_CUSTOM = 15
COL_MAX = 15
COL_LABELS = {
I_TITLE : "Title",
I_LEVEL : "Level",
I_LABEL : "Document",
I_LINE : "Line",
I_WCOUNT : "Words",
I_CCOUNT : "Chars",
I_PCOUNT : "Pars",
I_SYNOP : "Synopsis",
I_POV : "POV",
I_CHAR : nwLabels.KEY_NAME[nwKeyWords.CHAR_KEY],
I_PLOT : nwLabels.KEY_NAME[nwKeyWords.PLOT_KEY],
I_TIME : nwLabels.KEY_NAME[nwKeyWords.TIME_KEY],
I_WORLD : nwLabels.KEY_NAME[nwKeyWords.WORLD_KEY],
I_OBJECT : nwLabels.KEY_NAME[nwKeyWords.OBJECT_KEY],
I_ENTITY : nwLabels.KEY_NAME[nwKeyWords.ENTITY_KEY],
I_CUSTOM : nwLabels.KEY_NAME[nwKeyWords.CUSTOM_KEY],
HCols.TITLE : "Title",
HCols.LEVEL : "Level",
HCols.LABEL : "Document",
HCols.LINE : "Line",
HCols.WCOUNT : "Words",
HCols.CCOUNT : "Chars",
HCols.PCOUNT : "Pars",
HCols.POV : "POV",
HCols.CHAR : nwLabels.KEY_NAME[nwKeyWords.CHAR_KEY],
HCols.PLOT : nwLabels.KEY_NAME[nwKeyWords.PLOT_KEY],
HCols.TIME : nwLabels.KEY_NAME[nwKeyWords.TIME_KEY],
HCols.WORLD : nwLabels.KEY_NAME[nwKeyWords.WORLD_KEY],
HCols.OBJECT : nwLabels.KEY_NAME[nwKeyWords.OBJECT_KEY],
HCols.ENTITY : nwLabels.KEY_NAME[nwKeyWords.ENTITY_KEY],
HCols.CUSTOM : nwLabels.KEY_NAME[nwKeyWords.CUSTOM_KEY],
HCols.SYNOP : "Synopsis",
}
def __init__(self, theParent, theProject):
@@ -76,6 +79,7 @@ class GuiProjectOutline(QTreeWidget):
self.theProject = theProject
self.theIndex = self.theParent.theIndex
self.optState = self.theProject.optState
self.headerMenu = GuiOutlineHeaderMenu(self)
self.firstView = True
self.lastBuild = 0
@@ -86,21 +90,16 @@ class GuiProjectOutline(QTreeWidget):
self.setDragEnabled(False)
self.itemDoubleClicked.connect(self._treeDoubleClick)
# self.mainHead = self.header()
# self.mainHead.setContextMenuPolicy(Qt.CustomContextMenu)
# self.mainHead.
self.treeHead = self.header()
self.treeHead.setContextMenuPolicy(Qt.CustomContextMenu)
self.treeHead.customContextMenuRequested.connect(self._headerRightClick)
self.treeHead.sectionMoved.connect(self._columnMoved)
self.treeMap = {}
self.treeCols = {
"order" : [
self.I_TITLE, self.I_LABEL,
self.I_WCOUNT, self.I_POV,
self.I_CHAR, self.I_PLOT,
self.I_WORLD, self.I_SYNOP
],
"width" : [150, 100, 80, 100, 100, 100, 100, 300],
}
self.colIndex = {}
self.treeOrder = self.COL_LABELS.keys()
self.treeNCols = len(self.treeOrder)
self.treeWidth = [150]*self.treeNCols
self.colIndex = {}
logger.debug("ProjectOutline initialisation complete")
@@ -123,11 +122,9 @@ class GuiProjectOutline(QTreeWidget):
def closeOutline(self):
"""Called before a project is closed.
"""
self._saveHeaderState()
self.clear()
self.firstView = True
return
##
@@ -138,6 +135,22 @@ class GuiProjectOutline(QTreeWidget):
print(tItem, tCol)
return
def _headerRightClick(self, clickPos):
print(clickPos)
globPos = self.mapToGlobal(clickPos)
print(globPos)
return
def _columnMoved(self, logIdx, oldVisualIdx, newVisualIdx):
"""Make sure the order and width read from settings file, or
with default values, is kept up-to-date when columns are moved
around. Otherwise, the original order will be restored on a tree
rebuild.
"""
self.treeOrder.insert(newVisualIdx, self.treeOrder.pop(oldVisualIdx))
self.treeWidth.insert(newVisualIdx, self.treeWidth.pop(oldVisualIdx))
return
##
# Internal Functions
##
@@ -147,20 +160,35 @@ class GuiProjectOutline(QTreeWidget):
and column width.
"""
treeCols = self.optState.getValue("GuiProjectOutline", "headerState", self.treeCols)
# Load whatever we saved last time, regardless of wether it
# contains the correct names or number of columns.
keysOrder = self.COL_LABELS.keys()
tempOrder = self.optState.getValue("GuiProjectOutline", "headerOrder", keysOrder)
treeOrder = []
for hName in tempOrder:
for hItem in HCols:
if hItem.name == hName:
treeOrder.append(hItem)
if "order" not in treeCols.keys(): return
if not isinstance(treeCols["order"], list): return
if len(treeCols["order"]) == 0: return
# Add columns that were not in tempOrder to treeOrder, but in
# the default column order.
for cItem in keysOrder:
if cItem not in treeOrder:
treeOrder.append(cItem)
self.treeCols["order"] = []
for colID in treeCols["order"]:
if colID >= 0 and colID <= self.COL_MAX:
self.treeCols["order"].append(colID)
# Check that we now have a complete list, and only if so, save
# the order loaded from file. Otherwise, we keep the default.
if len(treeOrder) == self.treeNCols:
self.treeOrder = treeOrder
else:
logger.error("Failed to extract outline column order from previous session")
logger.error("Column count doesn't match %d != %d" % (len(treeOrder), self.treeNCols))
if "width" in treeCols.keys():
if isinstance(treeCols["width"],list):
self.treeCols["width"] = treeCols["width"]
# The columns widths we just fill whatever we've got, and append
# the rest with defaults, and truncate to desired length.
tempWidth = self.optState.getValue("GuiProjectOutline", "headerWidth", [])
treeWidth = [int(w) for w in tempWidth]
self.treeWidth = (treeWidth + self.treeWidth)[0:self.treeNCols]
return
@@ -169,12 +197,15 @@ class GuiProjectOutline(QTreeWidget):
and column width.
"""
colW = []
treeWidth = []
treeOrder = []
for iCol in range(self.columnCount()):
colW.append(self.columnWidth(iCol))
treeOrder.append(self.treeOrder[iCol].name)
iLog = self.treeHead.logicalIndex(iCol)
treeWidth.append(self.columnWidth(iLog))
self.treeCols["width"] = colW
self.optState.setValue("GuiProjectOutline", "headerState", self.treeCols)
self.optState.setValue("GuiProjectOutline", "headerOrder", treeOrder)
self.optState.setValue("GuiProjectOutline", "headerWidth", treeWidth)
self.optState.saveSettings()
return
@@ -184,22 +215,19 @@ class GuiProjectOutline(QTreeWidget):
"""
theLabels = []
for i, n in enumerate(self.treeCols["order"]):
theLabels.append(self.COL_LABELS[n])
self.colIndex[n] = i
for i, hItem in enumerate(self.treeOrder):
theLabels.append(self.COL_LABELS[hItem])
self.colIndex[hItem] = i
self.clear()
self.setHeaderLabels(theLabels)
for n, colW in enumerate(self.treeCols["width"]):
for n, colW in enumerate(self.treeWidth):
self.setColumnWidth(n,colW)
treeHead = self.headerItem()
if self.I_CCOUNT in self.colIndex:
treeHead.setTextAlignment(self.colIndex[self.I_CCOUNT],Qt.AlignRight)
if self.I_WCOUNT in self.colIndex:
treeHead.setTextAlignment(self.colIndex[self.I_WCOUNT],Qt.AlignRight)
if self.I_PCOUNT in self.colIndex:
treeHead.setTextAlignment(self.colIndex[self.I_PCOUNT],Qt.AlignRight)
headItem = self.headerItem()
headItem.setTextAlignment(self.colIndex[HCols.CCOUNT],Qt.AlignRight)
headItem.setTextAlignment(self.colIndex[HCols.WCOUNT],Qt.AlignRight)
headItem.setTextAlignment(self.colIndex[HCols.PCOUNT],Qt.AlignRight)
currTitle = None
currChapter = None
@@ -267,35 +295,38 @@ class GuiProjectOutline(QTreeWidget):
novIdx = self.theIndex.novelIndex[tHandle][sTitle]
newItem = QTreeWidgetItem()
self._setItemText(newItem, self.I_TITLE, novIdx["title"])
self._setItemText(newItem, self.I_LEVEL, novIdx["level"])
self._setItemText(newItem, self.I_LABEL, nwItem.itemName)
self._setItemText(newItem, self.I_LINE, sTitle[1:])
self._setItemText(newItem, self.I_SYNOP, novIdx["synopsis"])
self._setItemText(newItem, self.I_CCOUNT, str(novIdx["cCount"]), True)
self._setItemText(newItem, self.I_WCOUNT, str(novIdx["wCount"]), True)
self._setItemText(newItem, self.I_PCOUNT, str(novIdx["pCount"]), True)
newItem.setText(self.colIndex[HCols.TITLE], novIdx["title"])
newItem.setText(self.colIndex[HCols.LEVEL], novIdx["level"])
newItem.setText(self.colIndex[HCols.LABEL], nwItem.itemName)
newItem.setText(self.colIndex[HCols.LINE], sTitle[1:])
newItem.setText(self.colIndex[HCols.SYNOP], novIdx["synopsis"])
newItem.setText(self.colIndex[HCols.CCOUNT], str(novIdx["cCount"]))
newItem.setText(self.colIndex[HCols.WCOUNT], str(novIdx["wCount"]))
newItem.setText(self.colIndex[HCols.PCOUNT], str(novIdx["pCount"]))
newItem.setTextAlignment(self.colIndex[HCols.CCOUNT], Qt.AlignRight)
newItem.setTextAlignment(self.colIndex[HCols.WCOUNT], Qt.AlignRight)
newItem.setTextAlignment(self.colIndex[HCols.PCOUNT], Qt.AlignRight)
theRefs = self.theIndex.getReferences(tHandle, sTitle)
self._setItemText(newItem, self.I_POV, ", ".join(theRefs[nwKeyWords.POV_KEY]))
self._setItemText(newItem, self.I_CHAR, ", ".join(theRefs[nwKeyWords.CHAR_KEY]))
self._setItemText(newItem, self.I_PLOT, ", ".join(theRefs[nwKeyWords.PLOT_KEY]))
self._setItemText(newItem, self.I_TIME, ", ".join(theRefs[nwKeyWords.TIME_KEY]))
self._setItemText(newItem, self.I_WORLD, ", ".join(theRefs[nwKeyWords.WORLD_KEY]))
self._setItemText(newItem, self.I_OBJECT, ", ".join(theRefs[nwKeyWords.OBJECT_KEY]))
self._setItemText(newItem, self.I_ENTITY, ", ".join(theRefs[nwKeyWords.ENTITY_KEY]))
self._setItemText(newItem, self.I_CUSTOM, ", ".join(theRefs[nwKeyWords.CUSTOM_KEY]))
newItem.setText(self.colIndex[HCols.POV], ", ".join(theRefs[nwKeyWords.POV_KEY]))
newItem.setText(self.colIndex[HCols.CHAR], ", ".join(theRefs[nwKeyWords.CHAR_KEY]))
newItem.setText(self.colIndex[HCols.PLOT], ", ".join(theRefs[nwKeyWords.PLOT_KEY]))
newItem.setText(self.colIndex[HCols.TIME], ", ".join(theRefs[nwKeyWords.TIME_KEY]))
newItem.setText(self.colIndex[HCols.WORLD], ", ".join(theRefs[nwKeyWords.WORLD_KEY]))
newItem.setText(self.colIndex[HCols.OBJECT], ", ".join(theRefs[nwKeyWords.OBJECT_KEY]))
newItem.setText(self.colIndex[HCols.ENTITY], ", ".join(theRefs[nwKeyWords.ENTITY_KEY]))
newItem.setText(self.colIndex[HCols.CUSTOM], ", ".join(theRefs[nwKeyWords.CUSTOM_KEY]))
return newItem
def _setItemText(self, tItem, colID, theText, rAlign=False):
"""Set the correct text in the correct column, and if necessary,
right align it.
"""
if colID in self.colIndex:
tItem.setText(self.colIndex[colID], theText)
if rAlign:
tItem.setTextAlignment(self.colIndex[colID], Qt.AlignRight)
# END Class GuiProjectOutline
class GuiOutlineHeaderMenu(QMenu):
def __init__(self, theParent):
QMenu.__init__(self, theParent)
return
# END Class GuiProjectOutline
# END Class GuiOutlineHeaderMenu