From 02a81996a9dcb806c1daa89bfaba9f9bbf42c5a1 Mon Sep 17 00:00:00 2001 From: Olivier Keshavjee Date: Wed, 17 Jun 2015 13:25:46 +0200 Subject: [PATCH] Saves to single zipfile. --- .gitignore | 3 ++ README.md | 3 +- src/loadSave.py | 53 +++++++++++++++++++++----- src/mainWindow.py | 51 ++++++++++++++++--------- src/models/outlineModel.py | 22 +++++++---- src/settings.py | 34 ++++++++++------- test_project/flatModel.xml | 60 ----------------------------- test_project/labels.xml | 36 ------------------ test_project/outline.xml | 63 ------------------------------- test_project/perso.xml | 71 ----------------------------------- test_project/persoInfos.xml | 36 ------------------ test_project/settings.pickle | Bin 472 -> 0 bytes test_project/status.xml | 36 ------------------ 13 files changed, 118 insertions(+), 350 deletions(-) delete mode 100644 test_project/flatModel.xml delete mode 100644 test_project/labels.xml delete mode 100644 test_project/outline.xml delete mode 100644 test_project/perso.xml delete mode 100644 test_project/persoInfos.xml delete mode 100644 test_project/settings.pickle delete mode 100644 test_project/status.xml 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 69b20beaf16467ffcc8c3a735e356b0136941e2b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 472 zcmY*V%T5A85M1SrJjD0=b>ielfFU6mQ6Xe*X4q}n&5k?tFoS5aiAVfvduKVgx31}` z>YDn=#ptwI-f - -
- - - - -
- - - - - - TODO - - - Premier brouillon - - - Second brouillon - - - Final - - - Nouveau status - - -