Saves World Model. Still work in progress, but a step closer.

This commit is contained in:
Olivier Keshavjee 2016-03-05 17:46:02 +01:00
parent 3fd446dd1e
commit b45a32cfde
3 changed files with 117 additions and 24 deletions

View file

@ -14,7 +14,7 @@ from lxml import etree as ET
from manuskript import settings
from manuskript.functions import iconColor, iconFromColorString, mainWindow
from manuskript.models.characterModel import Character
from manuskript.models.characterModel import Character, CharacterInfo
try:
import zlib # Used with zipfile for compression
@ -250,18 +250,40 @@ def loadItem(root, mdl, parent=QModelIndex()):
def loadStandardItemModelXMLForCharacters(mdl, xml):
"""
Loads a standardItemModel saved to XML by version 0, but for the new characterModel.
@param mdl: characterModel
@param xml: the content of the xml
@return: nothing
"""
mdl = mainWindow().mdlCharacter
root = ET.fromstring(xml)
data = root.find("data")
for row in data:
char = Character(mdl)
for col in row:
c = int(col.attrib["col"])
# Value
if col.text:
char._data[c] = col.text
# Color
if "color" in col.attrib:
char.setColor(QColor(col.attrib["color"]))
# TODO: infos
# Infos
if len(col) != 0:
for rrow in col:
info = CharacterInfo(char)
for ccol in rrow:
cc = int(ccol.attrib["col"])
if cc == 11 and ccol.text:
info.description = ccol.text
if cc == 12 and ccol.text:
info.value = ccol.text
char.infos.append(info)
mdl.characters.append(char)

View file

@ -6,14 +6,17 @@
# (except for some elements), allowing collaborative work
# versioning and third-partty editing.
import os
import string
import zipfile
from PyQt5.QtCore import Qt
from PyQt5.QtCore import Qt, QModelIndex
from PyQt5.QtGui import QColor
from manuskript import settings
from manuskript.enums import Character
from manuskript.enums import Character, World
from manuskript.functions import mainWindow, iconColor
from lxml import etree as ET
try:
import zlib # Used with zipfile for compression
@ -28,7 +31,17 @@ cache = {}
def formatMetaData(name, value, tabLength=10):
# TODO: escape ":" in name
# Multiline formatting
if len(value.split("\n")) > 1:
value = "\n".join([" " * (tabLength + 1) + l for l in value.split("\n")])[tabLength + 1:]
# Avoid empty description (don't know how much MMD loves that)
if name == "":
name = "None"
# Escapes ":" in name
name = name.replace(":", "_.._")
return "{name}:{spaces}{value}\n".format(
name=name,
spaces=" " * (tabLength - len(name)),
@ -36,6 +49,23 @@ def formatMetaData(name, value, tabLength=10):
)
def slugify(name):
"""
A basic slug function, that escapes all spaces to "_" and all non letters/digits to "-".
@param name: name to slugify (str)
@return: str
"""
valid = string.ascii_letters + string.digits
newName = ""
for c in name:
if c in valid:
newName += c
elif c in string.whitespace:
newName += "_"
else:
newName += "-"
return newName
def saveProject(zip=None):
"""
Saves the project. If zip is False, the project is saved as a multitude of plain-text files for the most parts
@ -50,8 +80,11 @@ def saveProject(zip=None):
zip = False
# Fixme
# List of files to be written
files = []
# List of files to be removed
removes = []
mw = mainWindow()
# General infos (book and author)
@ -91,13 +124,9 @@ def saveProject(zip=None):
("Full", 4),
]:
val = mw.mdlFlatData.item(1, col).text().strip()
val = "\n".join([" " * 13 + l for l in val.split("\n")])[13:]
if val:
content += "{name}:{spaces}{value}\n".format(
name=name,
spaces=" " * (12 - len(name)),
value=val
)
content += formatMetaData(name, val, 12)
files.append((path, content))
# Label & Status
@ -146,25 +175,23 @@ def saveProject(zip=None):
mdl = mw.mdlCharacter
for c in mdl.characters:
content = ""
LENGTH = 20
for m, name in _map:
val = mdl.data(c.index(m.value)).strip()
if val:
# Multiline formatting
if len(val.split("\n")) > 1:
val = "\n".join([" " * (LENGTH + 1) + l for l in val.split("\n")])[LENGTH + 1:]
content += formatMetaData(name, val, LENGTH)
content += formatMetaData(name, val, 20)
for info in c.infos:
content += formatMetaData(info.description, info.value, LENGTH)
content += formatMetaData(info.description, info.value, 20)
name = "{ID}-{slugName}".format(
cpath = path.format(name="{ID}-{slugName}".format(
ID=c.ID(),
slugName="FIXME"
)
slugName=slugify(c.name())
))
if c.lastPath and cpath != c.lastPath:
removes.append(c.lastPath)
c.lastPath = cpath
files.append((
path.format(name=name),
cpath,
content))
# Texts
@ -176,7 +203,15 @@ def saveProject(zip=None):
# Either in an XML file, or in lots of plain texts?
# More probably text, since there might be writing done in third-party.
# TODO
path = "world.opml"
mdl = mw.mdlWorld
root = ET.Element("opml")
root.attrib["version"] = "1.0"
body = ET.SubElement(root, "body")
addWorldItem(body, mdl)
content = ET.tostring(root, encoding="UTF-8", xml_declaration=True, pretty_print=True)
files.append((path, content))
# Plots (mw.mdlPlots)
# Either in XML or lots of plain texts?
@ -212,6 +247,13 @@ def saveProject(zip=None):
folder = os.path.splitext(os.path.basename(project))[0]
print("Saving to folder", folder)
for path in removes:
if path not in [p for p,c in files]:
filename = os.path.join(dir, folder, path)
print("* Removing", filename)
os.remove(filename)
cache.pop(path)
for path, content in files:
filename = os.path.join(dir, folder, path)
os.makedirs(os.path.dirname(filename), exist_ok=True)
@ -230,6 +272,34 @@ def saveProject(zip=None):
else:
print(" In cache, and identical. Do nothing.")
def addWorldItem(root, mdl, parent=QModelIndex()):
"""
Lists elements in a world model and create an OPML xml file.
@param root: an Etree element
@param mdl: a worldModel
@param parent: the parent index in the world model
@return: root, to which sub element have been added
"""
# List every row (every world item)
for x in range(mdl.rowCount(parent)):
# For each row, create an outline item.
outline = ET.SubElement(root, "outline")
for y in range(mdl.columnCount(parent)):
val = mdl.data(mdl.index(x, y, parent))
if not val:
continue
for w in World:
if y == w.value:
outline.attrib[w.name] = val
if mdl.hasChildren(mdl.index(x, y, parent)):
addWorldItem(outline, mdl, mdl.index(x, y, parent))
return root
def loadProject(project):
"""

View file

@ -215,6 +215,7 @@ class characterModel(QAbstractItemModel):
class Character():
def __init__(self, model, name="No name"):
self._model = model
self.lastPath = ""
self._data = {}
self._data[C.name.value] = name