The menu for selecting columsn and storing column width now works

This commit is contained in:
Veronica K. B. Olsen
2020-04-11 17:58:13 +02:00
parent 9678a49f22
commit 0991d1b1a8
+156 -69
View File
@@ -29,23 +29,42 @@ logger = logging.getLogger(__name__)
class GuiProjectOutline(QTreeWidget): class GuiProjectOutline(QTreeWidget):
COL_DEF = { DEF_WIDTH = {
nwOutline.TITLE : (200, True, nwLabels.OUTLINE_COLS[nwOutline.TITLE]), nwOutline.TITLE : 200,
nwOutline.LEVEL : ( 40, False, nwLabels.OUTLINE_COLS[nwOutline.LEVEL]), nwOutline.LEVEL : 40,
nwOutline.LABEL : (150, True, nwLabels.OUTLINE_COLS[nwOutline.LABEL]), nwOutline.LABEL : 150,
nwOutline.LINE : ( 40, False, nwLabels.OUTLINE_COLS[nwOutline.LINE]), nwOutline.LINE : 40,
nwOutline.CCOUNT : ( 50, False, nwLabels.OUTLINE_COLS[nwOutline.CCOUNT]), nwOutline.CCOUNT : 50,
nwOutline.WCOUNT : ( 50, True, nwLabels.OUTLINE_COLS[nwOutline.WCOUNT]), nwOutline.WCOUNT : 50,
nwOutline.PCOUNT : ( 50, True, nwLabels.OUTLINE_COLS[nwOutline.PCOUNT]), nwOutline.PCOUNT : 50,
nwOutline.POV : (100, True, nwLabels.OUTLINE_COLS[nwOutline.POV]), nwOutline.POV : 100,
nwOutline.CHAR : (100, True, nwLabels.OUTLINE_COLS[nwOutline.CHAR]), nwOutline.CHAR : 100,
nwOutline.PLOT : (100, True, nwLabels.OUTLINE_COLS[nwOutline.PLOT]), nwOutline.PLOT : 100,
nwOutline.TIME : (100, False, nwLabels.OUTLINE_COLS[nwOutline.TIME]), nwOutline.TIME : 100,
nwOutline.WORLD : (100, True, nwLabels.OUTLINE_COLS[nwOutline.WORLD]), nwOutline.WORLD : 100,
nwOutline.OBJECT : (100, False, nwLabels.OUTLINE_COLS[nwOutline.OBJECT]), nwOutline.OBJECT : 100,
nwOutline.ENTITY : (100, False, nwLabels.OUTLINE_COLS[nwOutline.ENTITY]), nwOutline.ENTITY : 100,
nwOutline.CUSTOM : (100, False, nwLabels.OUTLINE_COLS[nwOutline.CUSTOM]), nwOutline.CUSTOM : 100,
nwOutline.SYNOP : (200, True, nwLabels.OUTLINE_COLS[nwOutline.SYNOP]), nwOutline.SYNOP : 200,
}
DEF_HIDDEN = {
nwOutline.TITLE : False,
nwOutline.LEVEL : True,
nwOutline.LABEL : False,
nwOutline.LINE : True,
nwOutline.CCOUNT : True,
nwOutline.WCOUNT : False,
nwOutline.PCOUNT : False,
nwOutline.POV : False,
nwOutline.CHAR : False,
nwOutline.PLOT : False,
nwOutline.TIME : True,
nwOutline.WORLD : False,
nwOutline.OBJECT : True,
nwOutline.ENTITY : True,
nwOutline.CUSTOM : True,
nwOutline.SYNOP : False,
} }
def __init__(self, theParent, theProject): def __init__(self, theParent, theProject):
@@ -58,7 +77,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.COL_DEF, nwOutline.TITLE) self.headerMenu = GuiOutlineHeaderMenu(self)
self.firstView = True self.firstView = True
self.lastBuild = 0 self.lastBuild = 0
@@ -75,28 +94,45 @@ class GuiProjectOutline(QTreeWidget):
self.treeHead.sectionMoved.connect(self._columnMoved) self.treeHead.sectionMoved.connect(self._columnMoved)
self.treeMap = {} self.treeMap = {}
self.treeOrder = self.COL_DEF.keys() self.treeOrder = []
self.treeNCols = len(self.treeOrder) self.colWidth = {}
self.colWidth = [150]*self.treeNCols self.colHidden = {}
self.colHidden = [False]*self.treeNCols
self.colIndex = {} self.colIndex = {}
self.treeNCols = 0
# Set defaults self.initOutline()
for hItem in self.treeOrder: self.headerMenu.setHiddenState(self.colHidden)
self.colWidth[hItem.value] = self.COL_DEF[hItem][0]
self.colHidden[hItem.value] = self.COL_DEF[hItem][1]
logger.debug("ProjectOutline initialisation complete") logger.debug("ProjectOutline initialisation complete")
return return
def refreshTree(self): def initOutline(self):
"""Set the default values for the Outline tree.
"""
self.treeOrder = []
self.colWidth = {}
self.colHidden = {}
self.colIndex = {}
self.treeNCols = 0
for hItem in nwOutline:
self.treeOrder.append(hItem)
self.colWidth[hItem] = self.DEF_WIDTH[hItem]
self.colHidden[hItem] = self.DEF_HIDDEN[hItem]
self.treeNCols = len(self.treeOrder)
return
def refreshTree(self, overRide=False):
"""Called whenever the Outline tab is activated and controls """Called whenever the Outline tab is activated and controls
what data to load, and if necessary, force a rebuild of the what data to load, and if necessary, force a rebuild of the
tree. tree.
""" """
if self.firstView: if self.firstView or overRide:
self._loadHeaderState() self._loadHeaderState()
self._populateTree() self._populateTree()
@@ -121,18 +157,24 @@ class GuiProjectOutline(QTreeWidget):
return return
def _headerRightClick(self, clickPos): def _headerRightClick(self, clickPos):
"""Show the header column menu, and check afterwards if a
column's visibility was changed.
"""
self.headerMenu.exec_(self.mapToGlobal(clickPos)) self.headerMenu.exec_(self.mapToGlobal(clickPos))
print("Menu closed")
hItem = self.headerMenu.toggledItem
if hItem is not None:
self.setColumnHidden(self.colIndex[hItem], not self.headerMenu.toggleState)
self.headerMenu.toggledItem = None
self.headerMenu.toggleState = None
return return
def _columnMoved(self, logIdx, oldVisualIdx, newVisualIdx): def _columnMoved(self, logIdx, oldVisualIdx, newVisualIdx):
"""Make sure the order and width read from settings file, or """Make sure the order array is up to date with the actual order
with default values, is kept up-to-date when columns are moved of the columns.
around. Otherwise, the original order will be restored on a tree
rebuild.
""" """
self.treeOrder.insert(newVisualIdx, self.treeOrder.pop(oldVisualIdx)) self.treeOrder.insert(newVisualIdx, self.treeOrder.pop(oldVisualIdx))
self.colWidth.insert(newVisualIdx, self.colWidth.pop(oldVisualIdx))
return return
## ##
@@ -146,19 +188,19 @@ class GuiProjectOutline(QTreeWidget):
# Load whatever we saved last time, regardless of wether it # Load whatever we saved last time, regardless of wether it
# contains the correct names or number of columns. # contains the correct names or number of columns.
keysOrder = self.COL_DEF.keys() tempOrder = self.optState.getValue("GuiProjectOutline", "headerOrder", [])
tempOrder = self.optState.getValue("GuiProjectOutline", "headerOrder", keysOrder)
treeOrder = [] treeOrder = []
for hName in tempOrder: for hName in tempOrder:
for hItem in nwOutline: try:
if hItem.name == hName: treeOrder.append(nwOutline[hName])
treeOrder.append(hItem) except:
logger.warning("Ignored unknown outline column '%s'" % str(hName))
# Add columns that were not in tempOrder to treeOrder, but in # Add columns that were not in tempOrder to treeOrder, but in
# the default column order. # the default column order.
for cItem in keysOrder: for hItem in nwOutline:
if cItem not in treeOrder: if hItem not in treeOrder:
treeOrder.append(cItem) treeOrder.append(hItem)
# Check that we now have a complete list, and only if so, save # Check that we now have a complete list, and only if so, save
# the order loaded from file. Otherwise, we keep the default. # the order loaded from file. Otherwise, we keep the default.
@@ -168,22 +210,31 @@ class GuiProjectOutline(QTreeWidget):
logger.error("Failed to extract outline column order from previous session") logger.error("Failed to extract outline column order from previous session")
logger.error("Column count doesn't match %d != %d" % (len(treeOrder), self.treeNCols)) logger.error("Column count doesn't match %d != %d" % (len(treeOrder), self.treeNCols))
# The columns widths and hidden state we just fill with whatever # We load the column widths and hidden state we find in the
# we've got, and append the rest with defaults, and truncate to # file, and leave the rest in their default state.
# desired length. tmpWidth = self.optState.getValue("GuiProjectOutline", "columnWidth", {})
tmpWidth = self.optState.getValue("GuiProjectOutline", "columnWidth", []) for hName in tmpWidth:
colWidth = [int(w) for w in tmpWidth] try:
self.colWidth = (colWidth + self.colWidth)[0:self.treeNCols] self.colWidth[nwOutline[hName]] = tmpWidth[hName]
except:
logger.warning("Ignored unknown outline column '%s'" % str(hName))
tmpHidden = self.optState.getValue("GuiProjectOutline", "columnHidden", []) tmpHidden = self.optState.getValue("GuiProjectOutline", "columnHidden", {})
colHidden = [int(w) for w in tmpHidden] for hName in tmpHidden:
self.colHidden = (colHidden + self.colHidden)[0:self.treeNCols] try:
self.colHidden[nwOutline[hName]] = tmpHidden[hName]
except:
logger.warning("Ignored unknown outline column '%s'" % str(hName))
self.headerMenu.setHiddenState(self.colHidden)
return return
def _saveHeaderState(self): def _saveHeaderState(self):
"""Save the state of the main tree header, that is, column order """Save the state of the main tree header, that is, column
and column width. order, column width and column hidden state. We don't want to
save the current width of hidden columns though. This preserves
the last known width in case they're unhidden again.
""" """
# If we haven't built the tree, there is nothing to save. # If we haven't built the tree, there is nothing to save.
@@ -191,13 +242,24 @@ class GuiProjectOutline(QTreeWidget):
return return
treeOrder = [] treeOrder = []
colWidth = [] colWidth = {}
colHidden = [] colHidden = {}
for hItem in nwOutline:
colWidth[hItem.name] = self.colWidth[hItem]
colHidden[hItem.name] = self.colHidden[hItem]
for iCol in range(self.columnCount()): for iCol in range(self.columnCount()):
treeOrder.append(self.treeOrder[iCol].name) hName = self.treeOrder[iCol].name
treeOrder.append(hName)
iLog = self.treeHead.logicalIndex(iCol) iLog = self.treeHead.logicalIndex(iCol)
colWidth.append(self.columnWidth(iLog)) logWidth = self.columnWidth(iLog)
colHidden.append(self.isColumnHidden(iLog)) logHidden = self.isColumnHidden(iLog)
colHidden[hName] = logHidden
if not logHidden and logWidth > 0:
colWidth[hName] = logWidth
self.optState.setValue("GuiProjectOutline", "headerOrder", treeOrder) self.optState.setValue("GuiProjectOutline", "headerOrder", treeOrder)
self.optState.setValue("GuiProjectOutline", "columnWidth", colWidth) self.optState.setValue("GuiProjectOutline", "columnWidth", colWidth)
@@ -212,13 +274,14 @@ class GuiProjectOutline(QTreeWidget):
theLabels = [] theLabels = []
for i, hItem in enumerate(self.treeOrder): for i, hItem in enumerate(self.treeOrder):
theLabels.append(self.COL_DEF[hItem][2]) theLabels.append(nwLabels.OUTLINE_COLS[hItem])
self.colIndex[hItem] = i self.colIndex[hItem] = i
self.clear() self.clear()
self.setHeaderLabels(theLabels) self.setHeaderLabels(theLabels)
for n, colW in enumerate(self.colWidth): for hItem in self.treeOrder:
self.setColumnWidth(n,colW) self.setColumnWidth(self.colIndex[hItem], self.colWidth[hItem])
self.setColumnHidden(self.colIndex[hItem], self.colHidden[hItem])
headItem = self.headerItem() headItem = self.headerItem()
headItem.setTextAlignment(self.colIndex[nwOutline.CCOUNT], Qt.AlignRight) headItem.setTextAlignment(self.colIndex[nwOutline.CCOUNT], Qt.AlignRight)
@@ -320,7 +383,7 @@ class GuiProjectOutline(QTreeWidget):
class GuiOutlineHeaderMenu(QMenu): class GuiOutlineHeaderMenu(QMenu):
def __init__(self, theParent, colDefault, skipCol): def __init__(self, theParent):
QMenu.__init__(self, theParent) QMenu.__init__(self, theParent)
mnuHead = QAction("Select Columns", self) mnuHead = QAction("Select Columns", self)
@@ -328,24 +391,48 @@ class GuiOutlineHeaderMenu(QMenu):
self.addSeparator() self.addSeparator()
self.actionMap = {} self.actionMap = {}
for hItem in nwOutline: for hItem in nwOutline:
if hItem == skipCol: if hItem == nwOutline.TITLE:
continue continue
if hItem not in colDefault: self.actionMap[hItem] = QAction(nwLabels.OUTLINE_COLS[hItem], self)
continue
self.actionMap[hItem] = QAction(colDefault[hItem][2], self)
self.actionMap[hItem].setCheckable(True) self.actionMap[hItem].setCheckable(True)
self.actionMap[hItem].setChecked(colDefault[hItem][1])
self.actionMap[hItem].toggled.connect( self.actionMap[hItem].toggled.connect(
lambda isChecked, tItem=hItem : self._columnToggled(isChecked, tItem) lambda isChecked, tItem=hItem : self._columnToggled(isChecked, tItem)
) )
self.addAction(self.actionMap[hItem]) self.addAction(self.actionMap[hItem])
self.ignoreToggle = False
self.toggledItem = None
self.toggleState = None
return
def setHiddenState(self, hiddenState):
"""Overwrite the checked state of the columns as the inverse of
the hidden state. Skip the TITLE column as it cannot be hidden.
"""
self.ignoreToggle = True
for hItem in nwOutline:
if hItem == nwOutline.TITLE or hItem not in hiddenState:
continue
self.actionMap[hItem].setChecked(not hiddenState[hItem])
self.ignoreToggle = False
return return
def _columnToggled(self, isChecked, theItem): def _columnToggled(self, isChecked, theItem):
print(isChecked, theItem.name) """The user has toggled the visibility of a column. Record the
change, but do nothing more.
"""
if self.ignoreToggle:
return
logger.verbose("User toggled Outline column '%s'" % theItem.name)
self.toggledItem = theItem
self.toggleState = isChecked
return return
# END Class GuiOutlineHeaderMenu # END Class GuiOutlineHeaderMenu