From cf4e4bc7940046957c5bc868992d0bda3f5442eb Mon Sep 17 00:00:00 2001 From: TheJackiMonster Date: Sat, 29 Oct 2022 19:30:53 +0200 Subject: [PATCH] Improve linking data changes Signed-off-by: TheJackiMonster --- manuskript/data/__init__.py | 1 + manuskript/data/characters.py | 16 ++++------- manuskript/data/links.py | 32 ++++++++++++++++++++++ manuskript/data/plots.py | 48 +++++++++++++++++++++------------ manuskript/ui/views/plotView.py | 22 ++++++++++++--- 5 files changed, 88 insertions(+), 31 deletions(-) create mode 100644 manuskript/data/links.py diff --git a/manuskript/data/__init__.py b/manuskript/data/__init__.py index aabfa7b1..45dd6be5 100644 --- a/manuskript/data/__init__.py +++ b/manuskript/data/__init__.py @@ -7,6 +7,7 @@ from manuskript.data.goal import GoalKind, Goal from manuskript.data.importance import Importance from manuskript.data.info import Info from manuskript.data.labels import LabelHost, Label +from manuskript.data.links import LinkAction, Links from manuskript.data.outline import Outline, OutlineFolder, OutlineText from manuskript.data.plots import Plots, PlotLine, PlotStep from manuskript.data.project import Project diff --git a/manuskript/data/characters.py b/manuskript/data/characters.py index 9b4bdf3a..494b6ae0 100644 --- a/manuskript/data/characters.py +++ b/manuskript/data/characters.py @@ -8,6 +8,7 @@ from collections.abc import Callable from manuskript.data.color import Color from manuskript.data.importance import Importance +from manuskript.data.links import LinkAction, Links from manuskript.data.unique_id import UniqueIDHost from manuskript.io.mmdFile import MmdFile from manuskript.util import safeFilename @@ -18,7 +19,7 @@ class Character: def __init__(self, path, characters): self.file = MmdFile(path, 21) self.characters = characters - self.links = list() + self.links = Links() self.UID = None self.name = None @@ -35,20 +36,11 @@ class Character: self.color = None self.details = dict() - def link(self, callback: Callable[[int], None]): - self.links.append(callback) - - def unlink(self, callback: Callable[[int], None]): - self.links.remove(callback) - def allowPOV(self) -> bool: return True if self.POV is None else self.POV def remove(self): - for link in self.links: - link(self.UID.value) - - self.links.clear() + self.links.call(LinkAction.DELETE, self.UID, self) self.characters.remove(self) @classmethod @@ -87,6 +79,8 @@ class Character: for (key, value) in metadata.items(): self.details[key] = value + self.links.call(LinkAction.RELOAD, self.UID, self) + def save(self): metadata = OrderedDict() diff --git a/manuskript/data/links.py b/manuskript/data/links.py new file mode 100644 index 00000000..2b6c1e35 --- /dev/null +++ b/manuskript/data/links.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python +# --!-- coding: utf8 --!-- +from collections.abc import Callable +from enum import Enum, unique + +from manuskript.data.unique_id import UniqueID + + +@unique +class LinkAction(Enum): + DELETE = 0 + UPDATE = 1 + RELOAD = 2 + + +class Links: + + def __init__(self): + self.callbacks = list() + + def add(self, callback: Callable[[LinkAction, UniqueID, any], None]): + self.callbacks.append(callback) + + def remove(self, callback: Callable[[LinkAction, UniqueID, any], None]): + self.callbacks.remove(callback) + + def call(self, action: LinkAction, UID: UniqueID, host: any): + for callback in self.callbacks: + callback(action, UID, host) + + if action == LinkAction.DELETE: + self.callbacks.clear() diff --git a/manuskript/data/plots.py b/manuskript/data/plots.py index 8de9684c..2e1175f0 100644 --- a/manuskript/data/plots.py +++ b/manuskript/data/plots.py @@ -4,8 +4,9 @@ import os from lxml import etree -from manuskript.data.characters import Characters +from manuskript.data.characters import Characters, Character from manuskript.data.importance import Importance +from manuskript.data.links import LinkAction, Links from manuskript.data.unique_id import UniqueIDHost, UniqueID from manuskript.io.xmlFile import XmlFile @@ -29,6 +30,7 @@ class PlotLine: def __init__(self, plots, UID: UniqueID, name: str = None, importance: Importance = Importance.MINOR): self.plots = plots self.host = UniqueIDHost() + self.links = Links() if name is None: name = "New plot" @@ -41,38 +43,51 @@ class PlotLine: self.result = "" self.steps = list() - def addCharacterByID(self, ID: int): - character = self.plots.characters.getByID(ID) + def __linkActionCharacter(self, action: LinkAction, UID: UniqueID, character): + if action == LinkAction.DELETE: + self.removeCharacter(character, False) + self.links.call(LinkAction.UPDATE, self.UID, self) + + def addCharacter(self, character: Character): if character is None: return - character.link(self.removeCharacterByID) + character.links.add(self.__linkActionCharacter) + self.characters.append(character.UID.value) + self.links.call(LinkAction.UPDATE, self.UID, self) - def removeCharacterByID(self, ID: int): - character = self.plots.characters.getByID(ID) - + def removeCharacter(self, character: Character, unlink: bool = True): if character is None: - self.characters.remove(ID) - else: - character.unlink(self.removeCharacterByID) - self.characters.remove(character.UID.value) + return + + if unlink: + character.links.remove(self.__linkActionCharacter) + + self.characters.remove(character.UID.value) + self.links.call(LinkAction.UPDATE, self.UID, self) def addStep(self, name: str, meta: str = "", summary: str = ""): step = PlotStep(self, self.host.newID(), name, meta, summary) self.steps.append(step) + + self.links.call(LinkAction.UPDATE, self.UID, self) return step def loadStep(self, ID: int, name: str, meta: str = "", summary: str = ""): step = PlotStep(self, self.host.loadID(ID), name, meta, summary) self.steps.append(step) + + self.links.call(LinkAction.UPDATE, self.UID, self) return step def removeStep(self, step: PlotStep): self.host.removeID(step.UID) self.steps.remove(step) + self.links.call(LinkAction.UPDATE, self.UID, self) + def __iter__(self): return self.steps.__iter__() @@ -96,9 +111,13 @@ class Plots: def loadLine(self, ID: int, name: str = None, importance: Importance = Importance.MINOR): line = PlotLine(self, self.host.loadID(ID), name, importance) self.lines[line.UID.value] = line + + line.links.call(LinkAction.RELOAD, line.UID, line) return line def removeLine(self, line: PlotLine): + line.links.call(LinkAction.DELETE, line.UID, line) + self.host.removeID(line.UID) self.lines.pop(line.UID.value) @@ -136,12 +155,7 @@ class Plots: for characterID in element.get("characters", "").split(','): try: - character = plots.characters.getByID(int(characterID)) - - if character is None: - continue - - line.addCharacterByID(character.UID.value) + line.addCharacter(plots.characters.getByID(int(characterID))) except ValueError: continue diff --git a/manuskript/ui/views/plotView.py b/manuskript/ui/views/plotView.py index 9337acf7..dfff650a 100644 --- a/manuskript/ui/views/plotView.py +++ b/manuskript/ui/views/plotView.py @@ -6,7 +6,7 @@ import gi gi.require_version("Gtk", "3.0") from gi.repository import Gtk -from manuskript.data import Plots, PlotLine, PlotStep, Importance +from manuskript.data import Plots, PlotLine, PlotStep, Importance, LinkAction from manuskript.ui.util import rgbaFromColor, pixbufFromColor from manuskript.util import validString, invalidString, validInt, invalidInt @@ -27,7 +27,7 @@ class PlotView: self.refreshPlotsStore() self.charactersStore = builder.get_object("characters_store") - self.refreshCharacterStore() + self.refreshCharactersStore() self.filteredPlotsStore = builder.get_object("filtered_plots_store") self.mainPlotsStore = builder.get_object("main_plots_store") @@ -100,7 +100,7 @@ class PlotView: self.plotsStore.set_value(tree_iter, 1, validString(plotLine.name)) self.plotsStore.set_value(tree_iter, 2, Importance.asValue(plotLine.importance)) - def refreshCharacterStore(self): + def refreshCharactersStore(self): self.charactersStore.clear() for character in self.plots.characters: @@ -113,7 +113,16 @@ class PlotView: self.charactersStore.set_value(tree_iter, 1, validString(character.name)) self.charactersStore.set_value(tree_iter, 2, pixbufFromColor(character.color)) + def __linkActionPlotLine(self, action, UID, plotLine): + if action == LinkAction.DELETE: + return + + self.plotCharactersStore.refilter() + def loadPlotData(self, plotLine: PlotLine): + if self.plotLine is not None: + self.plotLine.links.remove(self.__linkActionPlotLine) + self.plotLine = None self.importanceCombo.set_active(Importance.asValue(plotLine.importance)) @@ -124,9 +133,16 @@ class PlotView: self.plotLine = plotLine + if self.plotLine is not None: + self.plotLine.links.add(self.__linkActionPlotLine) + + self.refreshCharactersStore() self.plotCharactersStore.refilter() def unloadPlotData(self): + if self.plotLine is not None: + self.plotLine.links.remove(self.__linkActionPlotLine) + self.plotLine = None self.nameBuffer.set_text("", -1)