Complete the needed GUI class changes for the new NWStatus class

This commit is contained in:
Veronica Berglyd Olsen
2022-04-05 23:13:39 +02:00
parent 40e7055f16
commit ddd8b60816
6 changed files with 135 additions and 83 deletions
+1 -1
View File
@@ -184,7 +184,7 @@ def checkIntRange(value, first, last, default):
return default return default
def getMinMax(value, minVal, maxVal): def minmax(value, minVal, maxVal):
"""Make sure an integer is between min and max value (inclusive). """Make sure an integer is between min and max value (inclusive).
""" """
return min(maxVal, max(minVal, value)) return min(maxVal, max(minVal, value))
+34 -11
View File
@@ -687,6 +687,8 @@ class NWProject():
if len(aKey) > 0: if len(aKey) > 0:
self._packProjectValue(xTitleFmt, aKey, aValue) self._packProjectValue(xTitleFmt, aKey, aValue)
# Save Status/Importance
self.countStatus()
xStatus = etree.SubElement(xSettings, "status") xStatus = etree.SubElement(xSettings, "status")
self.statusItems.packXML(xStatus) self.statusItems.packXML(xStatus)
xStatus = etree.SubElement(xSettings, "importance") xStatus = etree.SubElement(xSettings, "importance")
@@ -1018,7 +1020,8 @@ class NWProject():
if self.projSpell != theLang: if self.projSpell != theLang:
self.projSpell = theLang self.projSpell = theLang
self.setProjectChanged(True) self.setProjectChanged(True)
return True return True
return False
def setProjectLang(self, theLang): def setProjectLang(self, theLang):
"""Set the project-specific language. """Set the project-specific language.
@@ -1065,26 +1068,46 @@ class NWProject():
self.setProjectChanged(True) self.setProjectChanged(True)
return True return True
def setStatusColours(self, newCols): def setStatusColours(self, newCols, delCols):
"""Update the list of novel file status flags. Also iterate """Update the list of novel file status flags. Also iterate
through the project and replace keys that have been renamed. through the project and replace keys that have been renamed.
""" """
replaceMap = self.statusItems.setNewEntries(newCols) if not (newCols or delCols):
for nwItem in self.projTree: return False
if nwItem.itemStatus in replaceMap:
nwItem.setStatus(replaceMap[nwItem.itemStatus]) for entry in newCols:
key = entry.get("key", None)
name = entry.get("name", "")
cols = entry.get("cols", (100, 100, 100))
if name:
self.statusItems.write(key, name, cols)
for key in delCols:
self.statusItems.remove(key)
self.setProjectChanged(True) self.setProjectChanged(True)
return True return True
def setImportColours(self, newCols): def setImportColours(self, newCols, delCols):
"""Update the list of note file importance flags. Also iterate """Update the list of note file importance flags. Also iterate
through the project and replace keys that have been renamed. through the project and replace keys that have been renamed.
""" """
replaceMap = self.importItems.setNewEntries(newCols) if not (newCols or delCols):
for nwItem in self.projTree: return False
if nwItem.itemImport in replaceMap:
nwItem.setImport(replaceMap[nwItem.itemImport]) for entry in newCols:
key = entry.get("key", None)
name = entry.get("name", "")
cols = entry.get("cols", (100, 100, 100))
if name:
self.importItems.write(key, name, cols)
for key in delCols:
self.importItems.remove(key)
self.setProjectChanged(True) self.setProjectChanged(True)
return True return True
def setAutoReplace(self, autoReplace): def setAutoReplace(self, autoReplace):
+28 -16
View File
@@ -4,7 +4,8 @@ novelWriter Project Item Status Class
Data class for the status/importance settings of a project item Data class for the status/importance settings of a project item
File History: File History:
Created: 2019-05-19 [0.1.3] Created: 2019-05-19 [0.1.3]
Rewritten: 2022-04-05 [1.7a0]
This file is a part of novelWriter This file is a part of novelWriter
Copyright 20182022, Veronica Berglyd Olsen Copyright 20182022, Veronica Berglyd Olsen
@@ -31,7 +32,7 @@ from lxml import etree
from PyQt5.QtGui import QIcon, QPixmap, QColor from PyQt5.QtGui import QIcon, QPixmap, QColor
from novelwriter.common import checkInt, getMinMax, simplified from novelwriter.common import checkInt, minmax, simplified
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -52,7 +53,7 @@ class NWStatus():
return return
def write(self, key, name, cols): def write(self, key, name, cols, count=None):
"""Add or update a status entry. If the key is invalid, a new """Add or update a status entry. If the key is invalid, a new
key is generated. key is generated.
""" """
@@ -67,7 +68,8 @@ class NWStatus():
pixmap.fill(QColor(*cols)) pixmap.fill(QColor(*cols))
name = simplified(name) name = simplified(name)
count = self._store[key]["count"] if key in self._store else 0 if count is None:
count = self._store[key]["count"] if key in self._store else 0
self._store[key] = { self._store[key] = {
"name": name, "name": name,
@@ -82,6 +84,20 @@ class NWStatus():
return key return key
def remove(self, key):
"""Remove an entry in the list, but not if the count is larger
than 0.
"""
if key not in self._store:
return False
if self._store[key]["count"] > 0:
return False
del self._reverse[self._store[key]["name"]]
del self._store[key]
return True
def check(self, value): def check(self, value):
"""Check the key against the stored status names. """Check the key against the stored status names.
""" """
@@ -134,12 +150,6 @@ class NWStatus():
else: else:
return self._defaultIcon return self._defaultIcon
def setNewEntries(self, newList):
"""Update the list of entries after they have been modified by
the GUI tool.
"""
return {}
def resetCounts(self): def resetCounts(self):
"""Clear the counts of references to the status entries. """Clear the counts of references to the status entries.
""" """
@@ -161,6 +171,7 @@ class NWStatus():
for key, data in self._store.items(): for key, data in self._store.items():
xSub = etree.SubElement(xParent, "entry", attrib={ xSub = etree.SubElement(xParent, "entry", attrib={
"key": key, "key": key,
"count": str(data["count"]),
"red": str(data["cols"][0]), "red": str(data["cols"][0]),
"green": str(data["cols"][1]), "green": str(data["cols"][1]),
"blue": str(data["cols"][2]), "blue": str(data["cols"][2]),
@@ -177,12 +188,13 @@ class NWStatus():
self._default = None self._default = None
for xChild in xParent: for xChild in xParent:
name = xChild.text.strip() key = xChild.attrib.get("key", None)
key = xChild.attrib.get("key", None) name = xChild.text.strip()
cR = getMinMax(checkInt(xChild.attrib.get("red", 100), 100), 0, 255) count = max(checkInt(xChild.attrib.get("count", 0), 0), 0)
cG = getMinMax(checkInt(xChild.attrib.get("green", 100), 100), 0, 255) red = minmax(checkInt(xChild.attrib.get("red", 100), 100), 0, 255)
cB = getMinMax(checkInt(xChild.attrib.get("blue", 100), 100), 0, 255) green = minmax(checkInt(xChild.attrib.get("green", 100), 100), 0, 255)
self.write(key, name, (cR, cG, cB)) blue = minmax(checkInt(xChild.attrib.get("blue", 100), 100), 0, 255)
self.write(key, name, (red, green, blue), count)
return True return True
+64 -54
View File
@@ -35,6 +35,7 @@ from PyQt5.QtWidgets import (
) )
from novelwriter.enum import nwAlert from novelwriter.enum import nwAlert
from novelwriter.common import simplified
from novelwriter.gui.custom import QSwitch, PagedDialog, QConfigLayout from novelwriter.gui.custom import QSwitch, PagedDialog, QConfigLayout
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@@ -81,6 +82,9 @@ class GuiProjectSettings(PagedDialog):
self.buttonBox.rejected.connect(self._doClose) self.buttonBox.rejected.connect(self._doClose)
self.addControls(self.buttonBox) self.addControls(self.buttonBox)
# Flags
self.spellChanged = False
logger.debug("GuiProjectSettings initialisation complete") logger.debug("GuiProjectSettings initialisation complete")
return return
@@ -103,16 +107,18 @@ class GuiProjectSettings(PagedDialog):
self.theProject.setProjectName(projName) self.theProject.setProjectName(projName)
self.theProject.setBookTitle(bookTitle) self.theProject.setBookTitle(bookTitle)
self.theProject.setBookAuthors(bookAuthors) self.theProject.setBookAuthors(bookAuthors)
self.theProject.setSpellLang(spellLang)
self.theProject.setProjBackup(doBackup) self.theProject.setProjBackup(doBackup)
# Remember this as updating spell dictionary can be expensive
self.spellChanged = self.theProject.setSpellLang(spellLang)
if self.tabStatus.colChanged: if self.tabStatus.colChanged:
statusCol = self.tabStatus.getNewList() newList, delList = self.tabStatus.getNewList()
self.theProject.setStatusColours(statusCol) self.theProject.setStatusColours(newList, delList)
if self.tabImport.colChanged: if self.tabImport.colChanged:
importCol = self.tabImport.getNewList() newList, delList = self.tabImport.getNewList()
self.theProject.setImportColours(importCol) self.theProject.setImportColours(newList, delList)
if self.tabStatus.colChanged or self.tabImport.colChanged: if self.tabStatus.colChanged or self.tabImport.colChanged:
self.theParent.rebuildTrees() self.theParent.rebuildTrees()
@@ -245,6 +251,10 @@ class GuiProjectEditStatus(QWidget):
COL_LABEL = 0 COL_LABEL = 0
COL_USAGE = 1 COL_USAGE = 1
KEY_ROLE = Qt.UserRole
COL_ROLE = Qt.UserRole + 1
NUM_ROLE = Qt.UserRole + 2
def __init__(self, theParent, theProject, isStatus): def __init__(self, theParent, theProject, isStatus):
QWidget.__init__(self, theParent) QWidget.__init__(self, theParent)
@@ -267,10 +277,9 @@ class GuiProjectEditStatus(QWidget):
self.optState.getInt("GuiProjectSettings", colSetting, 130) self.optState.getInt("GuiProjectSettings", colSetting, 130)
) )
self.colData = [] self.colDeleted = []
self.colCounts = []
self.colChanged = False self.colChanged = False
self.selColour = None self.selColour = QColor(100, 100, 100)
self.iPx = self.theTheme.baseIconSize self.iPx = self.theTheme.baseIconSize
@@ -285,8 +294,8 @@ class GuiProjectEditStatus(QWidget):
self.listBox.setColumnWidth(self.COL_LABEL, wCol0) self.listBox.setColumnWidth(self.COL_LABEL, wCol0)
self.listBox.setIndentation(0) self.listBox.setIndentation(0)
for iName, iCol, nUse, _ in self.theStatus: for key, data in self.theStatus.items():
self._addItem(iName, iCol, iName, nUse) self._addItem(key, data["name"], data["cols"], data["count"])
# List Controls # List Controls
# ============= # =============
@@ -349,12 +358,15 @@ class GuiProjectEditStatus(QWidget):
if self.colChanged: if self.colChanged:
newList = [] newList = []
for n in range(self.listBox.topLevelItemCount()): for n in range(self.listBox.topLevelItemCount()):
nItem = self.listBox.topLevelItem(n) item = self.listBox.topLevelItem(n)
nIdx = nItem.data(self.COL_LABEL, Qt.UserRole) newList.append({
newList.append(self.colData[nIdx]) "key": item.data(self.COL_LABEL, self.KEY_ROLE),
return newList "name": item.text(self.COL_LABEL),
"cols": item.data(self.COL_LABEL, self.COL_ROLE),
})
return newList, self.colDeleted
return None return [], []
## ##
# User Actions # User Actions
@@ -369,16 +381,16 @@ class GuiProjectEditStatus(QWidget):
) )
if newCol.isValid(): if newCol.isValid():
self.selColour = newCol self.selColour = newCol
colPixmap = QPixmap(self.iPx, self.iPx) pixmap = QPixmap(self.iPx, self.iPx)
colPixmap.fill(newCol) pixmap.fill(newCol)
self.colButton.setIcon(QIcon(colPixmap)) self.colButton.setIcon(QIcon(pixmap))
self.colButton.setIconSize(colPixmap.rect().size()) self.colButton.setIconSize(pixmap.rect().size())
return return
def _newItem(self): def _newItem(self):
"""Create a new status item. """Create a new status item.
""" """
newItem = self._addItem(self.tr("New Item"), (0, 0, 0), None, 0) newItem = self._addItem(None, self.tr("New Item"), (0, 0, 0), 0)
newItem.setBackground(self.COL_LABEL, QBrush(QColor(0, 255, 0, 70))) newItem.setBackground(self.COL_LABEL, QBrush(QColor(0, 255, 0, 70)))
newItem.setBackground(self.COL_USAGE, QBrush(QColor(0, 255, 0, 70))) newItem.setBackground(self.COL_USAGE, QBrush(QColor(0, 255, 0, 70)))
self.colChanged = True self.colChanged = True
@@ -390,14 +402,14 @@ class GuiProjectEditStatus(QWidget):
selItem = self._getSelectedItem() selItem = self._getSelectedItem()
if selItem is not None: if selItem is not None:
iRow = self.listBox.indexOfTopLevelItem(selItem) iRow = self.listBox.indexOfTopLevelItem(selItem)
selIdx = selItem.data(self.COL_LABEL, Qt.UserRole) if selItem.data(self.COL_LABEL, self.NUM_ROLE) > 0:
if self.colCounts[selIdx] == 0:
self.listBox.takeTopLevelItem(iRow)
self.colChanged = True
else:
self.theParent.makeAlert(self.tr( self.theParent.makeAlert(self.tr(
"Cannot delete a status item that is in use." "Cannot delete a status item that is in use."
), nwAlert.ERROR) ), nwAlert.ERROR)
else:
self.listBox.takeTopLevelItem(iRow)
self.colDeleted.append(selItem.data(self.COL_LABEL, self.KEY_ROLE))
self.colChanged = True
return return
def _saveItem(self): def _saveItem(self):
@@ -405,36 +417,33 @@ class GuiProjectEditStatus(QWidget):
""" """
selItem = self._getSelectedItem() selItem = self._getSelectedItem()
if selItem is not None: if selItem is not None:
selIdx = selItem.data(self.COL_LABEL, Qt.UserRole) selItem.setText(self.COL_LABEL, simplified(self.editName.text()))
self.colData[selIdx] = (
self.editName.text().strip(),
self.selColour.red(),
self.selColour.green(),
self.selColour.blue(),
self.colData[selIdx][4]
)
selItem.setText(self.COL_LABEL, self.colData[selIdx][0])
selItem.setText(self.COL_USAGE, self._usageString(self.colCounts[selIdx]))
selItem.setIcon(self.COL_LABEL, self.colButton.icon()) selItem.setIcon(self.COL_LABEL, self.colButton.icon())
selItem.setData(self.COL_LABEL, self.COL_ROLE, (
self.selColour.red(), self.selColour.green(), self.selColour.blue()
))
self.editName.setEnabled(False) self.editName.setEnabled(False)
self.colChanged = True self.colChanged = True
return return
def _addItem(self, iName, iCol, oName, nUse): def _addItem(self, key, name, cols, count):
"""Add a status item to the list. """Add a status item to the list.
""" """
newIcon = QPixmap(self.iPx, self.iPx) pixmap = QPixmap(self.iPx, self.iPx)
newIcon.fill(QColor(*iCol)) pixmap.fill(QColor(*cols))
newItem = QTreeWidgetItem()
newItem.setText(self.COL_LABEL, iName) item = QTreeWidgetItem()
newItem.setText(self.COL_USAGE, self._usageString(nUse)) item.setText(self.COL_LABEL, name)
newItem.setIcon(self.COL_LABEL, QIcon(newIcon)) item.setIcon(self.COL_LABEL, QIcon(pixmap))
newItem.setData(self.COL_LABEL, Qt.UserRole, len(self.colData)) item.setData(self.COL_LABEL, self.KEY_ROLE, key)
self.listBox.addTopLevelItem(newItem) item.setData(self.COL_LABEL, self.COL_ROLE, cols)
self.colData.append((iName, iCol[0], iCol[1], iCol[2], oName)) item.setData(self.COL_LABEL, self.NUM_ROLE, count)
self.colCounts.append(nUse) item.setText(self.COL_USAGE, self._usageString(count))
return newItem
self.listBox.addTopLevelItem(item)
return item
def _selectedItem(self): def _selectedItem(self):
"""Extract the info of a selected item and populate the settings """Extract the info of a selected item and populate the settings
@@ -442,13 +451,14 @@ class GuiProjectEditStatus(QWidget):
""" """
selItem = self._getSelectedItem() selItem = self._getSelectedItem()
if selItem is not None: if selItem is not None:
selIdx = selItem.data(self.COL_LABEL, Qt.UserRole) cols = selItem.data(self.COL_LABEL, self.COL_ROLE)
selVal = self.colData[selIdx] name = selItem.text(self.COL_LABEL)
self.selColour = QColor(selVal[1], selVal[2], selVal[3])
newIcon = QPixmap(self.iPx, self.iPx) pixmap = QPixmap(self.iPx, self.iPx)
newIcon.fill(self.selColour) pixmap.fill(QColor(*cols))
self.editName.setText(selVal[0]) self.selColour = QColor(*cols)
self.colButton.setIcon(QIcon(newIcon)) self.editName.setText(name)
self.colButton.setIcon(QIcon(pixmap))
self.editName.setEnabled(True) self.editName.setEnabled(True)
self.editName.selectAll() self.editName.selectAll()
self.editName.setFocus() self.editName.setFocus()
+5
View File
@@ -214,6 +214,11 @@ class GuiItemDetails(QWidget):
return return
def refreshDetails(self):
"""Reload the content of the details panel.
"""
self.updateViewBox(self._itemHandle)
def updateViewBox(self, tHandle): def updateViewBox(self, tHandle):
"""Populate the details box from a given handle. """Populate the details box from a given handle.
""" """
+3 -1
View File
@@ -1002,7 +1002,9 @@ class GuiMain(QMainWindow):
if dlgProj.result() == QDialog.Accepted: if dlgProj.result() == QDialog.Accepted:
logger.debug("Applying new project settings") logger.debug("Applying new project settings")
self.docEditor.setDictionaries() if dlgProj.spellChanged:
self.docEditor.setDictionaries()
self.treeMeta.refreshDetails()
self._updateWindowTitle(self.theProject.projName) self._updateWindowTitle(self.theProject.projName)
return True return True