Simplify the status class

This commit is contained in:
Veronica Berglyd Olsen
2024-04-10 17:57:39 +02:00
parent 478db63b30
commit 63d2f5c57d
9 changed files with 123 additions and 174 deletions
+5 -15
View File
@@ -25,7 +25,7 @@ from __future__ import annotations
import logging
from typing import TYPE_CHECKING, Any, Literal, overload
from typing import TYPE_CHECKING, Any
from PyQt5.QtGui import QIcon
@@ -308,25 +308,15 @@ class NWItem:
return trConst(nwLabels.ITEM_DESCRIPTION.get(descKey, ""))
@overload # pragma: no cover
def getImportStatus(self, incIcon: Literal[True] = True) -> tuple[str, QIcon]:
pass
@overload # pragma: no cover
def getImportStatus(self, incIcon: Literal[False]) -> tuple[str, None]:
pass
def getImportStatus(self, incIcon=True):
def getImportStatus(self) -> tuple[str, QIcon]:
"""Return the relevant importance or status label and icon for
the current item based on its class.
"""
if self.isNovelLike():
stName = self._project.data.itemStatus.name(self._status)
stIcon = self._project.data.itemStatus.icon(self._status) if incIcon else None
entry = self._project.data.itemStatus[self._status]
else:
stName = self._project.data.itemImport.name(self._import)
stIcon = self._project.data.itemImport.icon(self._import) if incIcon else None
return stName, stIcon
entry = self._project.data.itemImport[self._import]
return entry.name, entry.icon
##
# Checker Methods
+22 -33
View File
@@ -36,7 +36,8 @@ from collections.abc import Iterable
from PyQt5.QtCore import QCoreApplication
from novelwriter import CONFIG, SHARED, __version__, __hexversion__
from novelwriter.enum import nwItemType, nwItemClass, nwItemLayout, nwStatusShape
from novelwriter.core.status import StatusEntry
from novelwriter.enum import nwItemType, nwItemClass, nwItemLayout
from novelwriter.error import logException
from novelwriter.constants import trConst, nwLabels
from novelwriter.core.tree import NWTree
@@ -461,15 +462,14 @@ class NWProject:
def setDefaultStatusImport(self) -> None:
"""Set the default status and importance values."""
square = nwStatusShape.SQUARE
self._data.itemStatus.write(None, self.tr("New"), (100, 100, 100), square)
self._data.itemStatus.write(None, self.tr("Note"), (200, 50, 0), square)
self._data.itemStatus.write(None, self.tr("Draft"), (200, 150, 0), square)
self._data.itemStatus.write(None, self.tr("Finished"), (50, 200, 0), square)
self._data.itemImport.write(None, self.tr("New"), (100, 100, 100), square)
self._data.itemImport.write(None, self.tr("Minor"), (200, 50, 0), square)
self._data.itemImport.write(None, self.tr("Major"), (200, 150, 0), square)
self._data.itemImport.write(None, self.tr("Main"), (50, 200, 0), square)
self._data.itemStatus.write(None, self.tr("New"), (100, 100, 100), "SQUARE")
self._data.itemStatus.write(None, self.tr("Note"), (200, 50, 0), "SQUARE")
self._data.itemStatus.write(None, self.tr("Draft"), (200, 150, 0), "SQUARE")
self._data.itemStatus.write(None, self.tr("Finished"), (50, 200, 0), "SQUARE")
self._data.itemImport.write(None, self.tr("New"), (100, 100, 100), "SQUARE")
self._data.itemImport.write(None, self.tr("Minor"), (200, 50, 0), "SQUARE")
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
def setProjectLang(self, language: str | None) -> None:
@@ -492,13 +492,13 @@ class NWProject:
self.setProjectChanged(True)
return
def setStatusColours(self, new: list[dict], deleted: list[str]) -> bool:
def setStatus(self, update: list[tuple[str | None, StatusEntry]], remove: list[str]) -> None:
"""Update the list of novel file status flags."""
return self._setStatusImport(new, deleted, self._data.itemStatus)
return self._setStatusImport(update, remove, self._data.itemStatus)
def setImportColours(self, new: list[dict], deleted: list[str]) -> bool:
def setImport(self, update: list[tuple[str | None, StatusEntry]], remove: list[str]) -> None:
"""Update the list of note file importance flags."""
return self._setStatusImport(new, deleted, self._data.itemImport)
return self._setStatusImport(update, remove, self._data.itemImport)
def setProjectChanged(self, status: bool) -> bool:
"""Toggle the project changed flag, and propagate the
@@ -585,28 +585,17 @@ class NWProject:
# Internal Functions
##
def _setStatusImport(self, new: list[dict], delete: list[str], target: NWStatus) -> bool:
def _setStatusImport(self, update: list[tuple[str | None, StatusEntry]],
remove: list[str], target: NWStatus) -> None:
"""Update the list of novel file status or importance flags, and
delete those that have been requested deleted.
"""
if not (new or delete):
return False
order = []
for entry in new:
key = entry.get("key", None)
name = entry.get("name", "")
cols = entry.get("cols", (100, 100, 100))
shape = entry.get("shape", nwStatusShape.SQUARE)
if name:
order.append(target.write(key, name, cols, shape))
for key in delete:
target.remove(key)
target.reorder(order)
return True
if update or remove:
order = [target.write(k, e.name, e.color, e.shape) for k, e in update]
for key in remove:
target.remove(key)
target.reorder(order)
return
def _loadProjectLocalisation(self) -> bool:
"""Load the language data for the current project language."""
+37 -57
View File
@@ -24,11 +24,11 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
"""
from __future__ import annotations
import dataclasses
import logging
import random
from collections.abc import Iterable
from dataclasses import dataclass
from math import cos, pi, sin
from typing import TYPE_CHECKING, Literal
@@ -46,18 +46,26 @@ if TYPE_CHECKING: # pragma: no cover
logger = logging.getLogger(__name__)
@dataclass
@dataclasses.dataclass
class StatusEntry:
name: str
colour: QColor
color: QColor
shape: nwStatusShape
icon: QIcon
count: int = 0
@classmethod
def duplicate(cls, source: StatusEntry) -> StatusEntry:
"""Create a shallow copy of the source object."""
return dataclasses.replace(source)
# END Class StatusEntry
NO_ENTRY = StatusEntry("", QColor(0, 0, 0), nwStatusShape.SQUARE, QIcon(), 0)
class NWStatus:
STATUS = 1
@@ -70,9 +78,6 @@ class NWStatus:
self._default = None
self._iPX = CONFIG.pxInt(24)
self._defaultIcon = self.createIcon(
self._iPX, QColor(100, 100, 100), nwStatusShape.SQUARE
)
if self._type == self.STATUS:
self._prefix = "s"
@@ -86,44 +91,51 @@ class NWStatus:
def __len__(self) -> int:
return len(self._store)
def __getitem__(self, key: str) -> StatusEntry:
return self._store[key]
def __getitem__(self, key: str | None) -> StatusEntry:
"""Return the entry associated with a given key."""
if key and key in self._store:
return self._store[key]
elif self._default is not None:
return self._store[self._default]
return NO_ENTRY
##
# Methods
##
def write(self, key: str | None, name: str, col: tuple[int, int, int],
shape: nwStatusShape | str, count: int | None = None) -> str:
def write(self, key: str | None, name: str, color: tuple[int, int, int] | QColor,
shape: nwStatusShape | str, count: int = 0) -> str:
"""Add or update a status entry. If the key is invalid, a new
key is generated.
"""
if not self._isKey(key):
key = self._newKey()
if not isinstance(col, tuple):
col = (100, 100, 100)
if len(col) != 3:
col = (100, 100, 100)
name = simplified(name)
colour = QColor(*col)
if isinstance(color, QColor):
qColor = color
elif isinstance(color, tuple) and len(color) == 3:
qColor = QColor(*color)
else:
qColor = QColor(100, 100, 100)
if not isinstance(shape, nwStatusShape):
if shape in nwStatusShape.__members__:
try:
shape = nwStatusShape[shape]
else:
except KeyError:
shape = nwStatusShape.SQUARE
icon = self.createIcon(self._iPX, colour, shape)
name = simplified(name)
icon = self.createIcon(self._iPX, qColor, shape)
if key and key in self._store:
entry = self._store[key]
entry.name = name
entry.colour = colour
entry.color = qColor
entry.shape = shape
entry.icon = icon
entry.count = count or 0
entry.count = count
else:
self._store[key] = StatusEntry(name, colour, shape, icon, count or 0)
self._store[key] = StatusEntry(name, qColor, shape, icon, count)
if self._default is None:
self._default = key
@@ -156,38 +168,6 @@ class NWStatus:
return self._default
return ""
def name(self, key: str | None) -> str:
"""Return the name associated with a given key."""
if key and key in self._store:
return self._store[key].name
elif self._default is not None:
return self._store[self._default].name
return ""
def cols(self, key: str | None) -> QColor:
"""Return the colours associated with a given key."""
if key and key in self._store:
return self._store[key].colour
elif self._default is not None:
return self._store[self._default].colour
return QColor(100, 100, 100)
def count(self, key: str | None) -> int:
"""Return the count associated with a given key."""
if key and key in self._store:
return self._store[key].count
elif self._default is not None:
return self._store[self._default].count
return 0
def icon(self, key: str | None) -> QIcon:
"""Return the icon associated with a given key."""
if key and key in self._store:
return self._store[key].icon
elif self._default is not None:
return self._store[self._default].icon
return self._defaultIcon
def reorder(self, order: list[str]) -> bool:
"""Reorder the items according to list."""
if len(order) != len(self._store):
@@ -227,9 +207,9 @@ class NWStatus:
yield (entry.name, {
"key": key,
"count": str(entry.count),
"red": str(entry.colour.red()),
"green": str(entry.colour.green()),
"blue": str(entry.colour.blue()),
"red": str(entry.color.red()),
"green": str(entry.color.green()),
"blue": str(entry.color.blue()),
"shape": entry.shape.name,
})
return