Restructured the way column state is preserved in the Outline tree
This commit is contained in:
@@ -22,4 +22,4 @@ __all__ = [
|
|||||||
"nwItemClass",
|
"nwItemClass",
|
||||||
"nwItemLayout",
|
"nwItemLayout",
|
||||||
"nwItemType",
|
"nwItemType",
|
||||||
]
|
]
|
||||||
|
|||||||
+133
-102
@@ -15,10 +15,11 @@ import nw
|
|||||||
|
|
||||||
from os import path
|
from os import path
|
||||||
from time import time
|
from time import time
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
from PyQt5.QtCore import Qt, QByteArray
|
from PyQt5.QtCore import Qt, QByteArray
|
||||||
from PyQt5.QtWidgets import (
|
from PyQt5.QtWidgets import (
|
||||||
QWidget, QVBoxLayout, QTreeWidget, QTreeWidgetItem,
|
QWidget, QVBoxLayout, QTreeWidget, QTreeWidgetItem, QMenu, QAction,
|
||||||
QAbstractItemView
|
QAbstractItemView
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -26,44 +27,46 @@ from nw.constants import nwKeyWords, nwLabels
|
|||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
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):
|
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 = {
|
COL_LABELS = {
|
||||||
I_TITLE : "Title",
|
HCols.TITLE : "Title",
|
||||||
I_LEVEL : "Level",
|
HCols.LEVEL : "Level",
|
||||||
I_LABEL : "Document",
|
HCols.LABEL : "Document",
|
||||||
I_LINE : "Line",
|
HCols.LINE : "Line",
|
||||||
I_WCOUNT : "Words",
|
HCols.WCOUNT : "Words",
|
||||||
I_CCOUNT : "Chars",
|
HCols.CCOUNT : "Chars",
|
||||||
I_PCOUNT : "Pars",
|
HCols.PCOUNT : "Pars",
|
||||||
I_SYNOP : "Synopsis",
|
HCols.POV : "POV",
|
||||||
I_POV : "POV",
|
HCols.CHAR : nwLabels.KEY_NAME[nwKeyWords.CHAR_KEY],
|
||||||
I_CHAR : nwLabels.KEY_NAME[nwKeyWords.CHAR_KEY],
|
HCols.PLOT : nwLabels.KEY_NAME[nwKeyWords.PLOT_KEY],
|
||||||
I_PLOT : nwLabels.KEY_NAME[nwKeyWords.PLOT_KEY],
|
HCols.TIME : nwLabels.KEY_NAME[nwKeyWords.TIME_KEY],
|
||||||
I_TIME : nwLabels.KEY_NAME[nwKeyWords.TIME_KEY],
|
HCols.WORLD : nwLabels.KEY_NAME[nwKeyWords.WORLD_KEY],
|
||||||
I_WORLD : nwLabels.KEY_NAME[nwKeyWords.WORLD_KEY],
|
HCols.OBJECT : nwLabels.KEY_NAME[nwKeyWords.OBJECT_KEY],
|
||||||
I_OBJECT : nwLabels.KEY_NAME[nwKeyWords.OBJECT_KEY],
|
HCols.ENTITY : nwLabels.KEY_NAME[nwKeyWords.ENTITY_KEY],
|
||||||
I_ENTITY : nwLabels.KEY_NAME[nwKeyWords.ENTITY_KEY],
|
HCols.CUSTOM : nwLabels.KEY_NAME[nwKeyWords.CUSTOM_KEY],
|
||||||
I_CUSTOM : nwLabels.KEY_NAME[nwKeyWords.CUSTOM_KEY],
|
HCols.SYNOP : "Synopsis",
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, theParent, theProject):
|
def __init__(self, theParent, theProject):
|
||||||
@@ -76,6 +79,7 @@ class GuiProjectOutline(QTreeWidget):
|
|||||||
self.theProject = theProject
|
self.theProject = theProject
|
||||||
self.theIndex = self.theParent.theIndex
|
self.theIndex = self.theParent.theIndex
|
||||||
self.optState = self.theProject.optState
|
self.optState = self.theProject.optState
|
||||||
|
self.headerMenu = GuiOutlineHeaderMenu(self)
|
||||||
|
|
||||||
self.firstView = True
|
self.firstView = True
|
||||||
self.lastBuild = 0
|
self.lastBuild = 0
|
||||||
@@ -86,21 +90,16 @@ class GuiProjectOutline(QTreeWidget):
|
|||||||
self.setDragEnabled(False)
|
self.setDragEnabled(False)
|
||||||
self.itemDoubleClicked.connect(self._treeDoubleClick)
|
self.itemDoubleClicked.connect(self._treeDoubleClick)
|
||||||
|
|
||||||
# self.mainHead = self.header()
|
self.treeHead = self.header()
|
||||||
# self.mainHead.setContextMenuPolicy(Qt.CustomContextMenu)
|
self.treeHead.setContextMenuPolicy(Qt.CustomContextMenu)
|
||||||
# self.mainHead.
|
self.treeHead.customContextMenuRequested.connect(self._headerRightClick)
|
||||||
|
self.treeHead.sectionMoved.connect(self._columnMoved)
|
||||||
|
|
||||||
self.treeMap = {}
|
self.treeMap = {}
|
||||||
self.treeCols = {
|
self.treeOrder = self.COL_LABELS.keys()
|
||||||
"order" : [
|
self.treeNCols = len(self.treeOrder)
|
||||||
self.I_TITLE, self.I_LABEL,
|
self.treeWidth = [150]*self.treeNCols
|
||||||
self.I_WCOUNT, self.I_POV,
|
self.colIndex = {}
|
||||||
self.I_CHAR, self.I_PLOT,
|
|
||||||
self.I_WORLD, self.I_SYNOP
|
|
||||||
],
|
|
||||||
"width" : [150, 100, 80, 100, 100, 100, 100, 300],
|
|
||||||
}
|
|
||||||
self.colIndex = {}
|
|
||||||
|
|
||||||
logger.debug("ProjectOutline initialisation complete")
|
logger.debug("ProjectOutline initialisation complete")
|
||||||
|
|
||||||
@@ -123,11 +122,9 @@ class GuiProjectOutline(QTreeWidget):
|
|||||||
def closeOutline(self):
|
def closeOutline(self):
|
||||||
"""Called before a project is closed.
|
"""Called before a project is closed.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self._saveHeaderState()
|
self._saveHeaderState()
|
||||||
self.clear()
|
self.clear()
|
||||||
self.firstView = True
|
self.firstView = True
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
##
|
##
|
||||||
@@ -138,6 +135,22 @@ class GuiProjectOutline(QTreeWidget):
|
|||||||
print(tItem, tCol)
|
print(tItem, tCol)
|
||||||
return
|
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
|
# Internal Functions
|
||||||
##
|
##
|
||||||
@@ -147,20 +160,35 @@ class GuiProjectOutline(QTreeWidget):
|
|||||||
and column width.
|
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
|
# Add columns that were not in tempOrder to treeOrder, but in
|
||||||
if not isinstance(treeCols["order"], list): return
|
# the default column order.
|
||||||
if len(treeCols["order"]) == 0: return
|
for cItem in keysOrder:
|
||||||
|
if cItem not in treeOrder:
|
||||||
|
treeOrder.append(cItem)
|
||||||
|
|
||||||
self.treeCols["order"] = []
|
# Check that we now have a complete list, and only if so, save
|
||||||
for colID in treeCols["order"]:
|
# the order loaded from file. Otherwise, we keep the default.
|
||||||
if colID >= 0 and colID <= self.COL_MAX:
|
if len(treeOrder) == self.treeNCols:
|
||||||
self.treeCols["order"].append(colID)
|
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():
|
# The columns widths we just fill whatever we've got, and append
|
||||||
if isinstance(treeCols["width"],list):
|
# the rest with defaults, and truncate to desired length.
|
||||||
self.treeCols["width"] = treeCols["width"]
|
tempWidth = self.optState.getValue("GuiProjectOutline", "headerWidth", [])
|
||||||
|
treeWidth = [int(w) for w in tempWidth]
|
||||||
|
self.treeWidth = (treeWidth + self.treeWidth)[0:self.treeNCols]
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -169,12 +197,15 @@ class GuiProjectOutline(QTreeWidget):
|
|||||||
and column width.
|
and column width.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
colW = []
|
treeWidth = []
|
||||||
|
treeOrder = []
|
||||||
for iCol in range(self.columnCount()):
|
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", "headerOrder", treeOrder)
|
||||||
self.optState.setValue("GuiProjectOutline", "headerState", self.treeCols)
|
self.optState.setValue("GuiProjectOutline", "headerWidth", treeWidth)
|
||||||
self.optState.saveSettings()
|
self.optState.saveSettings()
|
||||||
|
|
||||||
return
|
return
|
||||||
@@ -184,22 +215,19 @@ class GuiProjectOutline(QTreeWidget):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
theLabels = []
|
theLabels = []
|
||||||
for i, n in enumerate(self.treeCols["order"]):
|
for i, hItem in enumerate(self.treeOrder):
|
||||||
theLabels.append(self.COL_LABELS[n])
|
theLabels.append(self.COL_LABELS[hItem])
|
||||||
self.colIndex[n] = i
|
self.colIndex[hItem] = i
|
||||||
|
|
||||||
self.clear()
|
self.clear()
|
||||||
self.setHeaderLabels(theLabels)
|
self.setHeaderLabels(theLabels)
|
||||||
for n, colW in enumerate(self.treeCols["width"]):
|
for n, colW in enumerate(self.treeWidth):
|
||||||
self.setColumnWidth(n,colW)
|
self.setColumnWidth(n,colW)
|
||||||
|
|
||||||
treeHead = self.headerItem()
|
headItem = self.headerItem()
|
||||||
if self.I_CCOUNT in self.colIndex:
|
headItem.setTextAlignment(self.colIndex[HCols.CCOUNT],Qt.AlignRight)
|
||||||
treeHead.setTextAlignment(self.colIndex[self.I_CCOUNT],Qt.AlignRight)
|
headItem.setTextAlignment(self.colIndex[HCols.WCOUNT],Qt.AlignRight)
|
||||||
if self.I_WCOUNT in self.colIndex:
|
headItem.setTextAlignment(self.colIndex[HCols.PCOUNT],Qt.AlignRight)
|
||||||
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)
|
|
||||||
|
|
||||||
currTitle = None
|
currTitle = None
|
||||||
currChapter = None
|
currChapter = None
|
||||||
@@ -267,35 +295,38 @@ class GuiProjectOutline(QTreeWidget):
|
|||||||
novIdx = self.theIndex.novelIndex[tHandle][sTitle]
|
novIdx = self.theIndex.novelIndex[tHandle][sTitle]
|
||||||
|
|
||||||
newItem = QTreeWidgetItem()
|
newItem = QTreeWidgetItem()
|
||||||
self._setItemText(newItem, self.I_TITLE, novIdx["title"])
|
|
||||||
self._setItemText(newItem, self.I_LEVEL, novIdx["level"])
|
newItem.setText(self.colIndex[HCols.TITLE], novIdx["title"])
|
||||||
self._setItemText(newItem, self.I_LABEL, nwItem.itemName)
|
newItem.setText(self.colIndex[HCols.LEVEL], novIdx["level"])
|
||||||
self._setItemText(newItem, self.I_LINE, sTitle[1:])
|
newItem.setText(self.colIndex[HCols.LABEL], nwItem.itemName)
|
||||||
self._setItemText(newItem, self.I_SYNOP, novIdx["synopsis"])
|
newItem.setText(self.colIndex[HCols.LINE], sTitle[1:])
|
||||||
self._setItemText(newItem, self.I_CCOUNT, str(novIdx["cCount"]), True)
|
newItem.setText(self.colIndex[HCols.SYNOP], novIdx["synopsis"])
|
||||||
self._setItemText(newItem, self.I_WCOUNT, str(novIdx["wCount"]), True)
|
newItem.setText(self.colIndex[HCols.CCOUNT], str(novIdx["cCount"]))
|
||||||
self._setItemText(newItem, self.I_PCOUNT, str(novIdx["pCount"]), True)
|
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)
|
theRefs = self.theIndex.getReferences(tHandle, sTitle)
|
||||||
self._setItemText(newItem, self.I_POV, ", ".join(theRefs[nwKeyWords.POV_KEY]))
|
newItem.setText(self.colIndex[HCols.POV], ", ".join(theRefs[nwKeyWords.POV_KEY]))
|
||||||
self._setItemText(newItem, self.I_CHAR, ", ".join(theRefs[nwKeyWords.CHAR_KEY]))
|
newItem.setText(self.colIndex[HCols.CHAR], ", ".join(theRefs[nwKeyWords.CHAR_KEY]))
|
||||||
self._setItemText(newItem, self.I_PLOT, ", ".join(theRefs[nwKeyWords.PLOT_KEY]))
|
newItem.setText(self.colIndex[HCols.PLOT], ", ".join(theRefs[nwKeyWords.PLOT_KEY]))
|
||||||
self._setItemText(newItem, self.I_TIME, ", ".join(theRefs[nwKeyWords.TIME_KEY]))
|
newItem.setText(self.colIndex[HCols.TIME], ", ".join(theRefs[nwKeyWords.TIME_KEY]))
|
||||||
self._setItemText(newItem, self.I_WORLD, ", ".join(theRefs[nwKeyWords.WORLD_KEY]))
|
newItem.setText(self.colIndex[HCols.WORLD], ", ".join(theRefs[nwKeyWords.WORLD_KEY]))
|
||||||
self._setItemText(newItem, self.I_OBJECT, ", ".join(theRefs[nwKeyWords.OBJECT_KEY]))
|
newItem.setText(self.colIndex[HCols.OBJECT], ", ".join(theRefs[nwKeyWords.OBJECT_KEY]))
|
||||||
self._setItemText(newItem, self.I_ENTITY, ", ".join(theRefs[nwKeyWords.ENTITY_KEY]))
|
newItem.setText(self.colIndex[HCols.ENTITY], ", ".join(theRefs[nwKeyWords.ENTITY_KEY]))
|
||||||
self._setItemText(newItem, self.I_CUSTOM, ", ".join(theRefs[nwKeyWords.CUSTOM_KEY]))
|
newItem.setText(self.colIndex[HCols.CUSTOM], ", ".join(theRefs[nwKeyWords.CUSTOM_KEY]))
|
||||||
|
|
||||||
return newItem
|
return newItem
|
||||||
|
|
||||||
def _setItemText(self, tItem, colID, theText, rAlign=False):
|
# END Class GuiProjectOutline
|
||||||
"""Set the correct text in the correct column, and if necessary,
|
|
||||||
right align it.
|
class GuiOutlineHeaderMenu(QMenu):
|
||||||
"""
|
|
||||||
if colID in self.colIndex:
|
def __init__(self, theParent):
|
||||||
tItem.setText(self.colIndex[colID], theText)
|
QMenu.__init__(self, theParent)
|
||||||
if rAlign:
|
|
||||||
tItem.setTextAlignment(self.colIndex[colID], Qt.AlignRight)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
# END Class GuiProjectOutline
|
# END Class GuiOutlineHeaderMenu
|
||||||
|
|||||||
Reference in New Issue
Block a user