Simplify the status class
This commit is contained in:
@@ -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
@@ -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
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user