diff --git a/novelwriter/types.py b/novelwriter/types.py index e1b05ead..e06177b7 100644 --- a/novelwriter/types.py +++ b/novelwriter/types.py @@ -23,6 +23,8 @@ along with this program. If not, see . """ from __future__ import annotations +from typing import Any, TypeVar + from PyQt6.QtCore import Qt from PyQt6.QtGui import QColor, QFont, QPainter, QTextCharFormat, QTextCursor, QTextFormat from PyQt6.QtWidgets import QDialog, QDialogButtonBox, QHeaderView, QSizePolicy, QStyle @@ -146,3 +148,30 @@ FONT_STYLE: dict[QFont.Style, str] = { QFont.Style.StyleItalic: "italic", QFont.Style.StyleOblique: "oblique", } + +## +# Decorators and MetaClasses +## + +T_ = TypeVar("T_", bound=object) + + +def nwDataClass(cls: T_) -> T_: + """A simple data class decorator that generates slots automatically + and creates an init function to match. + """ + + def wrap(cls: T_) -> T_: + fields = tuple(a for a in dir(cls) if not a.startswith("__")) + values = {a: getattr(cls, a) for a in fields} + + def init(self: Any) -> None: + nonlocal values + for a, v in values.items(): + self.__setattr__(a, v) + + return type(cls.__class__.__name__, (object,), { # type: ignore + "__slots__": fields, "__init__": init + }) + + return wrap(cls)