From ee881bdb173f24c7dd8872a608c78752848240dd Mon Sep 17 00:00:00 2001 From: TheJackiMonster Date: Sun, 9 May 2021 17:07:30 +0200 Subject: [PATCH] Added data model for world and its items Signed-off-by: TheJackiMonster --- bin/test_io.py | 10 ++++ manuskript/data/project.py | 4 ++ manuskript/data/world.py | 116 +++++++++++++++++++++++++++++++++++++ manuskript/io/opmlFile.py | 46 ++++++++++----- 4 files changed, 160 insertions(+), 16 deletions(-) create mode 100644 manuskript/data/world.py diff --git a/bin/test_io.py b/bin/test_io.py index 94ce9981..808c83c9 100644 --- a/bin/test_io.py +++ b/bin/test_io.py @@ -9,10 +9,20 @@ realpath = os.path.realpath(__file__) sys.path.insert(1, os.path.join(os.path.dirname(realpath), '..')) import manuskript.data as data +import manuskript.load_save.version_1 as v1 path = os.path.join(sys.path[1], "sample-projects/book-of-acts") +import time + +start = time.time() + project = data.Project(path + ".msk") project.load() +end = time.time() +duration = end - start + +print(duration) + project.save() diff --git a/manuskript/data/project.py b/manuskript/data/project.py index c3be32bd..cbc063e6 100644 --- a/manuskript/data/project.py +++ b/manuskript/data/project.py @@ -9,6 +9,7 @@ from manuskript.data.status import StatusHost from manuskript.data.settings import Settings from manuskript.data.characters import Characters from manuskript.data.plots import Plots +from manuskript.data.world import World from manuskript.data.outline import Outline from manuskript.data.revisions import Revisions from manuskript.io.mskFile import MskFile @@ -26,6 +27,7 @@ class Project: self.settings = Settings(self.file.dir_path) self.characters = Characters(self.file.dir_path) self.plots = Plots(self.file.dir_path) + self.world = World(self.file.dir_path) self.outline = Outline(self.file.dir_path) self.revisions = Revisions(self.file.dir_path) @@ -47,6 +49,7 @@ class Project: self.settings.load() self.characters.load() self.plots.load() + self.world.load() self.outline.load() self.revisions.load() @@ -63,6 +66,7 @@ class Project: self.settings.save() self.characters.save() self.plots.save() + self.world.save() self.outline.save() #self.revisions.save() diff --git a/manuskript/data/world.py b/manuskript/data/world.py new file mode 100644 index 00000000..49d6e28b --- /dev/null +++ b/manuskript/data/world.py @@ -0,0 +1,116 @@ +#!/usr/bin/env python +# --!-- coding: utf8 --!-- + +import os + +from manuskript.data.unique_id import UniqueIDHost, UniqueID +from manuskript.io.opmlFile import OpmlFile, OpmlOutlineItem + + +class WorldItem: + + def __init__(self, world, UID: UniqueID, name: str): + self.world = world + + self.UID = UID + self.name = name + self.description = None + self.passion = None + self.conflict = None + self.children = list() + + def __iter__(self): + return self.children.__iter__() + + def load(self): + self.world.load() + + +class World: + + def __init__(self, path): + self.file = OpmlFile(os.path.join(path, "world.opml")) + self.host = UniqueIDHost() + self.items = dict() + self.top = list() + + def addItem(self, name: str) -> WorldItem: + item = WorldItem(self, self.host.newID(), name) + self.items[item.UID.value] = item + return item + + def loadItem(self, ID: int, name: str) -> WorldItem: + item = WorldItem(self, self.host.loadID(ID), name) + self.items[item.UID.value] = item + return item + + def removeItem(self, item: WorldItem): + self.host.removeID(item.UID) + self.items.pop(item.UID.value) + + def __iter__(self): + return self.items.values().__iter__() + + @classmethod + def loadWorldItem(cls, world, outline: OpmlOutlineItem): + ID = outline.attributes.get("ID", None) + + if ID is None: + return None + + item = world.loadItem(int(ID), outline.attributes.get("name", None)) + + item.description = outline.attributes.get("description", None) + item.passion = outline.attributes.get("passion", None) + item.conflict = outline.attributes.get("conflict", None) + + for child in outline.children: + childItem = cls.loadWorldItem(world, child) + + if childItem is None: + continue + + item.children.append(childItem) + + return item + + def load(self): + try: + outlines = self.file.load() + + self.items.clear() + self.top.clear() + + for outline in outlines: + item = World.loadWorldItem(self, outline) + + if item is None: + continue + + self.top.append(item) + except FileNotFoundError: + self.items.clear() + self.top.clear() + + @classmethod + def saveWorldItem(cls, item: WorldItem): + outline = OpmlOutlineItem() + + outline.attributes["name"] = item.name + outline.attributes["ID"] = str(item.UID.value) + outline.attributes["description"] = item.description + outline.attributes["passion"] = item.passion + outline.attributes["conflict"] = item.conflict + + for childItem in item.children: + outline.children.append(cls.saveWorldItem(childItem)) + + return outline + + def save(self): + outlines = list() + + for item in self.top: + outlines.append(World.saveWorldItem(item)) + + self.file.save(outlines) diff --git a/manuskript/io/opmlFile.py b/manuskript/io/opmlFile.py index f5675f49..3a86095a 100644 --- a/manuskript/io/opmlFile.py +++ b/manuskript/io/opmlFile.py @@ -7,10 +7,12 @@ from manuskript.io.xmlFile import XmlFile class OpmlOutlineItem: - def __init__(self, tag="outline"): - self.tag = tag + def __init__(self): self.attributes = dict() - self.children = [] + self.children = list() + + def __iter__(self): + return self.children.__iter__() def keys(self): return self.attributes.keys() @@ -23,7 +25,7 @@ class OpmlFile(XmlFile): @classmethod def loadOutline(cls, element): - outline = OpmlOutlineItem(element.tag) + outline = OpmlOutlineItem() for key in element.keys(): outline.attributes[key] = element.get(key) @@ -37,25 +39,37 @@ class OpmlFile(XmlFile): tree = XmlFile.load(self) root = tree.getroot() - return OpmlFile.loadOutline(root) + if root.tag != "opml": + raise IOError("No valid OPML!") + + body = root.find("body") + + if body is None: + return [] + + return [OpmlFile.loadOutline(element) for element in body.getchildren()] @classmethod - def saveOutline(cls, outline, parent=None): - if parent is None: - element = etree.Element(outline.tag) - else: - element = etree.SubElement(parent, outline.tag) + def saveOutline(cls, outline, parent): + element = etree.SubElement(parent, "outline") - for key in outline.keys(): - element.attrib[key] = outline.attributes[key] + for (key, value) in outline.attributes.items(): + if value is None: + continue + + element.attrib[key] = value for child in outline.children: cls.saveOutline(child, element) - return element - def save(self, content): - root = OpmlFile.saveOutline(content) - tree = etree.ElementTree(root) + root = etree.Element("opml") + root.set("version", "1.0") + body = etree.SubElement(root, "body") + + for outline in content: + OpmlFile.saveOutline(outline, body) + + tree = etree.ElementTree(root) XmlFile.save(self, tree)