Add status icon shape to project XML

This commit is contained in:
Veronica Berglyd Olsen
2024-04-09 22:39:46 +02:00
parent af44646a77
commit ff3cae9db4
3 changed files with 31 additions and 30 deletions
+12 -10
View File
@@ -36,7 +36,7 @@ from collections.abc import Iterable
from PyQt5.QtCore import QCoreApplication from PyQt5.QtCore import QCoreApplication
from novelwriter import CONFIG, SHARED, __version__, __hexversion__ from novelwriter import CONFIG, SHARED, __version__, __hexversion__
from novelwriter.enum import nwItemType, nwItemClass, nwItemLayout from novelwriter.enum import nwItemType, nwItemClass, nwItemLayout, nwStatusShape
from novelwriter.error import logException from novelwriter.error import logException
from novelwriter.constants import trConst, nwLabels from novelwriter.constants import trConst, nwLabels
from novelwriter.core.tree import NWTree from novelwriter.core.tree import NWTree
@@ -461,14 +461,15 @@ class NWProject:
def setDefaultStatusImport(self) -> None: def setDefaultStatusImport(self) -> None:
"""Set the default status and importance values.""" """Set the default status and importance values."""
self._data.itemStatus.write(None, self.tr("New"), (100, 100, 100)) square = nwStatusShape.SQUARE
self._data.itemStatus.write(None, self.tr("Note"), (200, 50, 0)) self._data.itemStatus.write(None, self.tr("New"), (100, 100, 100), square)
self._data.itemStatus.write(None, self.tr("Draft"), (200, 150, 0)) self._data.itemStatus.write(None, self.tr("Note"), (200, 50, 0), square)
self._data.itemStatus.write(None, self.tr("Finished"), (50, 200, 0)) self._data.itemStatus.write(None, self.tr("Draft"), (200, 150, 0), square)
self._data.itemImport.write(None, self.tr("New"), (100, 100, 100)) self._data.itemStatus.write(None, self.tr("Finished"), (50, 200, 0), square)
self._data.itemImport.write(None, self.tr("Minor"), (200, 50, 0)) self._data.itemImport.write(None, self.tr("New"), (100, 100, 100), square)
self._data.itemImport.write(None, self.tr("Major"), (200, 150, 0)) self._data.itemImport.write(None, self.tr("Minor"), (200, 50, 0), square)
self._data.itemImport.write(None, self.tr("Main"), (50, 200, 0)) self._data.itemImport.write(None, self.tr("Major"), (200, 150, 0), square)
self._data.itemImport.write(None, self.tr("Main"), (50, 200, 0), square)
return return
def setProjectLang(self, language: str | None) -> None: def setProjectLang(self, language: str | None) -> None:
@@ -596,8 +597,9 @@ class NWProject:
key = entry.get("key", None) key = entry.get("key", None)
name = entry.get("name", "") name = entry.get("name", "")
cols = entry.get("cols", (100, 100, 100)) cols = entry.get("cols", (100, 100, 100))
shape = entry.get("shape", nwStatusShape.SQUARE)
if name: if name:
order.append(target.write(key, name, cols)) order.append(target.write(key, name, cols, shape))
for key in delete: for key in delete:
target.remove(key) target.remove(key)
+5 -2
View File
@@ -46,7 +46,7 @@ if TYPE_CHECKING: # pragma: no cover
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
FILE_VERSION = "1.5" # The current project file format version FILE_VERSION = "1.5" # The current project file format version
FILE_REVISION = "3" # The current project file format revision FILE_REVISION = "4" # The current project file format revision
HEX_VERSION = 0x0105 HEX_VERSION = 0x0105
NUM_VERSION = { NUM_VERSION = {
@@ -109,6 +109,8 @@ class ProjectXMLReader:
Rev 2: Drops the title node from project and adds the TEMPLATE Rev 2: Drops the title node from project and adds the TEMPLATE
class for items. 2.3 Beta 1. class for items. 2.3 Beta 1.
Rev 3: Added TEMPLATE class. 2.3. Rev 3: Added TEMPLATE class. 2.3.
Rev 4: Added shape attribute to status and importance entry
nodes. 2.5.
""" """
def __init__(self, path: str | Path) -> None: def __init__(self, path: str | Path) -> None:
@@ -436,7 +438,8 @@ class ProjectXMLReader:
green = checkInt(xEntry.attrib.get("green", 0), 0) green = checkInt(xEntry.attrib.get("green", 0), 0)
blue = checkInt(xEntry.attrib.get("blue", 0), 0) blue = checkInt(xEntry.attrib.get("blue", 0), 0)
count = checkInt(xEntry.attrib.get("count", 0), 0) count = checkInt(xEntry.attrib.get("count", 0), 0)
sObject.write(key, xEntry.text or "", (red, green, blue), count) shape = xEntry.attrib.get("shape", "")
sObject.write(key, xEntry.text or "", (red, green, blue), shape, count)
return return
def _parseDictKeyText(self, xItem: ET.Element) -> dict: def _parseDictKeyText(self, xItem: ET.Element) -> dict:
+14 -18
View File
@@ -57,7 +57,7 @@ class NWStatus:
self._default = None self._default = None
self._iPX = CONFIG.pxInt(24) self._iPX = CONFIG.pxInt(24)
self._defaultIcon = self._createIcon(100, 100, 100) self._defaultIcon = self._createIcon(100, 100, 100, nwStatusShape.SQUARE)
if self._type == self.STATUS: if self._type == self.STATUS:
self._prefix = "s" self._prefix = "s"
@@ -68,7 +68,8 @@ class NWStatus:
return return
def write(self, key: str | None, name: str, col: tuple, count: int | None = None) -> str: def write(self, key: str | None, name: str, col: tuple, shape: nwStatusShape | str,
count: int | None = None) -> str:
"""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.
""" """
@@ -83,14 +84,21 @@ class NWStatus:
cG = minmax(col[1], 0, 255) cG = minmax(col[1], 0, 255)
cB = minmax(col[2], 0, 255) cB = minmax(col[2], 0, 255)
name = simplified(name) name = simplified(name)
if not isinstance(shape, nwStatusShape):
if shape in nwStatusShape.__members__:
shape = nwStatusShape[shape]
else:
shape = nwStatusShape.SQUARE
if count is None: if count is None:
count = self._store.get(key, {}).get("count", 0) count = self._store.get(key, {}).get("count", 0)
self._store[key] = { self._store[key] = {
"name": name, "name": name,
"icon": self._createIcon(cR, cG, cB), "icon": self._createIcon(cR, cG, cB, shape),
"cols": (cR, cG, cB), "cols": (cR, cG, cB),
"count": count, "count": count,
"shape": shape,
} }
if self._default is None: if self._default is None:
@@ -198,20 +206,10 @@ class NWStatus:
"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]),
"shape": data["shape"].name,
}) })
return return
def unpack(self, data: dict) -> None:
"""Unpack a data dictionary and set the class values."""
self._store = {}
self._default = None
for key, entry in data.items():
label = entry.get("label", "")
colour = entry.get("colour", (100, 100, 100))
count = entry.get("count", 0)
self.write(key, label, colour, count)
return
## ##
# Internal Functions # Internal Functions
## ##
@@ -241,16 +239,14 @@ class NWStatus:
return False return False
return True return True
def _createIcon(self, red: int, green: int, blue: int) -> QIcon: def _createIcon(self, red: int, green: int, blue: int, shape: nwStatusShape) -> QIcon:
"""Generate an icon for a status label.""" """Generate an icon for a status label."""
pixmap = QPixmap(48, 48) pixmap = QPixmap(48, 48)
pixmap.fill(QtTransparent) pixmap.fill(QtTransparent)
path = _SHAPES.getShape(nwStatusShape.DIAMOND)
painter = QPainter(pixmap) painter = QPainter(pixmap)
painter.setRenderHint(QtPaintAnitAlias) painter.setRenderHint(QtPaintAnitAlias)
painter.fillPath(path, QColor(red, green, blue)) painter.fillPath(_SHAPES.getShape(shape), QColor(red, green, blue))
painter.end() painter.end()
return QIcon(pixmap.scaled( return QIcon(pixmap.scaled(