The menu for selecting columsn and storing column width now works
This commit is contained in:
+156
-69
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user