diff --git a/.gitignore b/.gitignore
index 25b1c20..fe8374b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,6 @@ snowflake*
*.pyc
*.lprof
.directory
+test_project.zip
+test_project_
+Notes.t2t
\ No newline at end of file
diff --git a/README.md b/README.md
index 7dcf003..567285e 100644
--- a/README.md
+++ b/README.md
@@ -6,4 +6,5 @@ Dépendances:
- lxml
Optional:
-- pyenchant
\ No newline at end of file
+- pyenchant
+- zlib
\ No newline at end of file
diff --git a/src/loadSave.py b/src/loadSave.py
index 3838ba2..be0ca16 100644
--- a/src/loadSave.py
+++ b/src/loadSave.py
@@ -4,8 +4,35 @@
from qt import *
from functions import *
from lxml import etree as ET
+import zipfile
+try:
+ import zlib # Used with zipfile for compression
+ compression = zipfile.ZIP_DEFLATED
+except:
+ compression = zipfile.ZIP_STORED
-def saveStandardItemModelXML(mdl, xml):
+def saveFilesToZip(files, zipname):
+ """Saves given files to zipname.
+ files is actually a list of (content, filename)."""
+
+ zf = zipfile.ZipFile(zipname, mode="w")
+
+ for content, filename in files:
+ zf.writestr(filename, content, compress_type=compression)
+
+ zf.close()
+
+def loadFilesFromZip(zipname):
+ """Returns the content of zipfile as a dict of filename:content."""
+ zf = zipfile.ZipFile(zipname)
+ files = {}
+ for f in zf.namelist():
+ files[f] = zf.read(f)
+ return files
+
+def saveStandardItemModelXML(mdl, xml=None):
+ """Saves the given QStandardItemModel to XML.
+ If xml (filename) is given, saves to xml. Otherwise returns as string."""
root = ET.Element("model")
root.attrib["version"] = qApp.applicationVersion()
@@ -41,20 +68,28 @@ def saveStandardItemModelXML(mdl, xml):
col.text = mdl.data(mdl.index(x, y))
#print(qApp.tr("Saving to {}.").format(xml))
- ET.ElementTree(root).write(xml, encoding="UTF-8", xml_declaration=True, pretty_print=True)
+ if xml:
+ ET.ElementTree(root).write(xml, encoding="UTF-8", xml_declaration=True, pretty_print=True)
+ else:
+ return ET.tostring(root, encoding="UTF-8", xml_declaration=True, pretty_print=True)
-def loadStandardItemModelXML(mdl, xml):
+def loadStandardItemModelXML(mdl, xml, fromString=False):
+ """Load data to a QStandardItemModel mdl from xml.
+ By default xml is a filename. If fromString=True, xml is a string containg the data."""
#print(qApp.tr("Loading {}... ").format(xml), end="")
- try:
- tree = ET.parse(xml)
- except:
- print("Failed.")
- return
+ if not fromString:
+ try:
+ tree = ET.parse(xml)
+ except:
+ print("Failed.")
+ return
+ else:
+ root = ET.fromstring(xml)
- root = tree.getroot()
+ #root = tree.getroot()
#Header
hLabels = []
diff --git a/src/mainWindow.py b/src/mainWindow.py
index a0dcef6..4a997c9 100644
--- a/src/mainWindow.py
+++ b/src/mainWindow.py
@@ -226,7 +226,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.lstDebugLabels.setModel(self.mdlLabels)
self.lstDebugStatus.setModel(self.mdlStatus)
- self.loadProject("test_project")
+ self.loadProject("test_project.zip")
####################################################################################################
# OUTLINE #
@@ -375,7 +375,6 @@ class MainWindow(QMainWindow, Ui_MainWindow):
self.loadDatas()
# Load settings
- settings.load("{}/settings.pickle".format(project))
self.generateViewMenu()
self.sldCorkSizeFactor.setValue(settings.corkSizeFactor)
self.actSpellcheck.setChecked(settings.spellcheck)
@@ -435,29 +434,47 @@ class MainWindow(QMainWindow, Ui_MainWindow):
if settings.saveOnQuit:
self.saveDatas()
- # Save settings
- settings.save("{}/settings.pickle".format(self.currentProject))
-
# closeEvent
QMainWindow.closeEvent(self, event)
def saveDatas(self):
- saveStandardItemModelXML(self.mdlFlatData, "{}/flatModel.xml".format(self.currentProject))
- saveStandardItemModelXML(self.mdlPersos, "{}/perso.xml".format(self.currentProject))
- saveStandardItemModelXML(self.mdlPersosInfos, "{}/persoInfos.xml".format(self.currentProject))
- saveStandardItemModelXML(self.mdlLabels, "{}/labels.xml".format(self.currentProject))
- saveStandardItemModelXML(self.mdlStatus, "{}/status.xml".format(self.currentProject))
- self.mdlOutline.saveToXML("{}/outline.xml".format(self.currentProject))
+ # Saving
+ files = []
+
+ files.append((saveStandardItemModelXML(self.mdlFlatData), "flatModel.xml"))
+ files.append((saveStandardItemModelXML(self.mdlPersos), "perso.xml"))
+ files.append((saveStandardItemModelXML(self.mdlPersosInfos), "persoInfos.xml"))
+ files.append((saveStandardItemModelXML(self.mdlLabels), "labels.xml"))
+ files.append((saveStandardItemModelXML(self.mdlStatus), "status.xml"))
+ files.append((self.mdlOutline.saveToXML(), "outline.xml"))
+ files.append((settings.save(),"settings.pickle"))
+
+ saveFilesToZip(files, self.currentProject)
+
+ # Giving some feedback
print(self.tr("Project {} saved.").format(self.currentProject))
self.statusBar().showMessage(self.tr("Project {} saved.").format(self.currentProject), 5000)
def loadDatas(self):
- loadStandardItemModelXML(self.mdlFlatData, "{}/flatModel.xml".format(self.currentProject))
- loadStandardItemModelXML(self.mdlPersos, "{}/perso.xml".format(self.currentProject))
- loadStandardItemModelXML(self.mdlPersosInfos, "{}/persoInfos.xml".format(self.currentProject))
- loadStandardItemModelXML(self.mdlLabels, "{}/labels.xml".format(self.currentProject))
- loadStandardItemModelXML(self.mdlStatus, "{}/status.xml".format(self.currentProject))
- self.mdlOutline.loadFromXML("{}/outline.xml".format(self.currentProject))
+ # Loading
+ files = loadFilesFromZip(self.currentProject)
+
+ if "flatModel.xml" in files:
+ loadStandardItemModelXML(self.mdlFlatData, files["flatModel.xml"], fromString=True)
+ if "perso.xml" in files:
+ loadStandardItemModelXML(self.mdlPersos, files["perso.xml"], fromString=True)
+ if "persoInfos.xml" in files:
+ loadStandardItemModelXML(self.mdlPersosInfos, files["persoInfos.xml"], fromString=True)
+ if "labels.xml" in files:
+ loadStandardItemModelXML(self.mdlLabels, files["labels.xml"], fromString=True)
+ if "status.xml" in files:
+ loadStandardItemModelXML(self.mdlStatus, files["status.xml"], fromString=True)
+ if "outline.xml" in files:
+ self.mdlOutline.loadFromXML(files["outline.xml"], fromString=True)
+ if "settings.pickle" in files:
+ settings.load(files["settings.pickle"], fromString=True)
+
+ # Giving some feedback
print(self.tr("Project {} loaded.").format(self.currentProject))
self.statusBar().showMessage(self.tr("Project {} loaded.").format(self.currentProject), 5000)
diff --git a/src/models/outlineModel.py b/src/models/outlineModel.py
index 37456b8..a217408 100644
--- a/src/models/outlineModel.py
+++ b/src/models/outlineModel.py
@@ -296,17 +296,23 @@ class outlineModel(QAbstractItemModel):
################# XML / saving / loading #################
- def saveToXML(self, xml):
+ def saveToXML(self, xml=None):
+ "If xml (filename) is given, saves the items to xml. Otherwise returns as string."
root = ET.XML(self.rootItem.toXML())
- ET.ElementTree(root).write(xml, encoding="UTF-8", xml_declaration=True, pretty_print=True)
+ if xml:
+ ET.ElementTree(root).write(xml, encoding="UTF-8", xml_declaration=True, pretty_print=True)
+ else:
+ return ET.tostring(root, encoding="UTF-8", xml_declaration=True, pretty_print=True)
- def loadFromXML(self, xml):
- #try:
+ def loadFromXML(self, xml, fromString=False):
+ "Load from xml. Assume that xml is a filename. If fromString=True, xml is the content."
+ if not fromString:
root = ET.parse(xml)
- self.rootItem = outlineItem(self, xml=ET.tostring(root))
- #except:
- #print("N'arrive pas à ouvrir {}".format(xml))
- #return
+ else:
+ root = ET.fromstring(xml)
+
+ self.rootItem = outlineItem(self, xml=ET.tostring(root))
+
def pathToIndex(self, index, path=""):
if not index.isValid():
diff --git a/src/settings.py b/src/settings.py
index b69ab15..5e12f11 100644
--- a/src/settings.py
+++ b/src/settings.py
@@ -33,7 +33,7 @@ autoSave = True
autoSaveDelay = 5
saveOnQuit = True
-def save(filename):
+def save(filename=None):
global spellcheck, dict, corkSliderFactor, viewSettings, corkSizeFactor, folderView, lastTab, lastIndex, \
autoSave, autoSaveDelay, saveOnQuit
@@ -55,19 +55,27 @@ def save(filename):
#print("Saving:")
#pp.pprint(allSettings)
- f = open(filename, "wb")
- pickle.dump(allSettings, f)
+ if filename:
+ f = open(filename, "wb")
+ pickle.dump(allSettings, f)
+ else:
+ return pickle.dumps(allSettings)
-def load(filename):
- try:
- global allSettings
-
- f = open(filename, "rb")
- allSettings = pickle.load(f)
-
- except:
- print("{} doesn't exist, cannot load settings.".format(filename))
- return
+def load(string, fromString=False):
+ """Load settings from 'string'. 'string' is the filename of the pickle dump.
+ If fromString=True, string is the data of the pickle dumps."""
+ global allSettings
+
+ if not fromString:
+ try:
+ f = open(string, "rb")
+ allSettings = pickle.load(f)
+
+ except:
+ print("{} doesn't exist, cannot load settings.".format(string))
+ return
+ else:
+ allSettings = pickle.loads(string)
#pp=pprint.PrettyPrinter(indent=4, compact=False)
#print("Loading:")
diff --git a/test_project/flatModel.xml b/test_project/flatModel.xml
deleted file mode 100644
index 30041cf..0000000
--- a/test_project/flatModel.xml
+++ /dev/null
@@ -1,60 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Titre du livre
- Sous-titre
-
-
- Fantasy
- CC-BY-SA
- Auteur Cool
- auteur@cool.com
-
-
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
-<html><head><meta name="qrichtext" content="1" /><style type="text/css">
-p, li { white-space: pre-wrap; }
-</style></head><body style=" font-family:'Oxygen-Sans'; font-size:10pt; font-weight:400; font-style:normal;">
-<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Bonjour asdasd</p></body></html>
- Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir
- Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir
-
-Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir
-
-Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir
-
-Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir
- Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir
-
-Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir
-
-Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir
-
-Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir
-Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir
-
-Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir Bonsoir
-
-
-
-
-
-
-
diff --git a/test_project/labels.xml b/test_project/labels.xml
deleted file mode 100644
index 1873061..0000000
--- a/test_project/labels.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
-
-
-
-
-
-
- Idée
-
-
- Note
-
-
- Chapitre
-
-
- Scène
-
-
- Nouveau label
-
-
-
diff --git a/test_project/outline.xml b/test_project/outline.xml
deleted file mode 100644
index 2047bc7..0000000
--- a/test_project/outline.xml
+++ /dev/null
@@ -1,63 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/test_project/perso.xml b/test_project/perso.xml
deleted file mode 100644
index a6a2287..0000000
--- a/test_project/perso.xml
+++ /dev/null
@@ -1,71 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Albert le vert
- 0
- 2
-
-
-
-
-
-
-
- Quelques notes
-
-
-Pour voir.
-
-
-
- Ginette La Barbette
- 1
- 1
-
-
-
-
-
-
-
-
-
-
-
- Nouveau perso avec un nom très très long pour voir comment ça fait
- 2
- 0
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/test_project/persoInfos.xml b/test_project/persoInfos.xml
deleted file mode 100644
index 3feecb7..0000000
--- a/test_project/persoInfos.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
-
-
-
- 1
- 2
- 4
- 5
-
-
- 12
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/test_project/settings.pickle b/test_project/settings.pickle
deleted file mode 100644
index 69b20be..0000000
Binary files a/test_project/settings.pickle and /dev/null differ
diff --git a/test_project/status.xml b/test_project/status.xml
deleted file mode 100644
index 60fb05f..0000000
--- a/test_project/status.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-
-
-
-
-
-
-
-
- TODO
-
-
- Premier brouillon
-
-
- Second brouillon
-
-
- Final
-
-
- Nouveau status
-
-
-