mirror of
https://github.com/olivierkes/manuskript.git
synced 2024-06-10 15:04:34 +12:00
Plain text file format in progress
This commit is contained in:
parent
240700ca17
commit
af089e8a6a
|
@ -8,8 +8,11 @@
|
|||
import os
|
||||
import zipfile
|
||||
|
||||
from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtGui import QColor
|
||||
|
||||
from manuskript import settings
|
||||
from manuskript.functions import mainWindow
|
||||
from manuskript.functions import mainWindow, iconColor
|
||||
|
||||
try:
|
||||
import zlib # Used with zipfile for compression
|
||||
|
@ -19,6 +22,8 @@ except:
|
|||
compression = zipfile.ZIP_STORED
|
||||
|
||||
|
||||
cache = {}
|
||||
|
||||
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
|
||||
|
@ -30,46 +35,153 @@ def saveProject(zip=None):
|
|||
@return: Nothing
|
||||
"""
|
||||
if zip is None:
|
||||
zip = False
|
||||
zip = True
|
||||
# Fixme
|
||||
|
||||
|
||||
files = []
|
||||
mw = mainWindow()
|
||||
|
||||
# files.append((saveStandardItemModelXML(mw.mdlFlatData),
|
||||
# "flatModel.xml"))
|
||||
# # files.append((saveStandardItemModelXML(self.mdlCharacter),
|
||||
# # "perso.xml"))
|
||||
# files.append((saveStandardItemModelXML(mw.mdlWorld),
|
||||
# "world.xml"))
|
||||
# files.append((saveStandardItemModelXML(mw.mdlLabels),
|
||||
# "labels.xml"))
|
||||
# files.append((saveStandardItemModelXML(mw.mdlStatus),
|
||||
# "status.xml"))
|
||||
# files.append((saveStandardItemModelXML(mw.mdlPlots),
|
||||
# "plots.xml"))
|
||||
# files.append((mw.mdlOutline.saveToXML(),
|
||||
# "outline.xml"))
|
||||
# files.append((settings.save(),
|
||||
# "settings.pickle"))
|
||||
# General infos (book and author)
|
||||
# Saved in plain text, in infos.txt
|
||||
|
||||
files.append(("blabla", "test/machin.txt"))
|
||||
files.append(("youpi", "encore/truc.txt"))
|
||||
path = "infos.txt"
|
||||
content = ""
|
||||
for name, col in [
|
||||
("Title", 0),
|
||||
("Subtitle", 1),
|
||||
("Serie", 2),
|
||||
("Volume", 3),
|
||||
("Genre", 4),
|
||||
("License", 5),
|
||||
("Author", 6),
|
||||
("Email", 7),
|
||||
]:
|
||||
val = mw.mdlFlatData.item(0, col).text().strip()
|
||||
if val:
|
||||
content += "{name}:{spaces}{value}\n".format(
|
||||
name=name,
|
||||
spaces=" " * (15 - len(name)),
|
||||
value=val
|
||||
)
|
||||
files.append((path, content))
|
||||
|
||||
# Summary
|
||||
# In plain text, in summary.txt
|
||||
|
||||
path = "summary.txt"
|
||||
content = ""
|
||||
for name, col in [
|
||||
("Situation", 0),
|
||||
("Sentence", 1),
|
||||
("Paragraph", 2),
|
||||
("Page", 3),
|
||||
("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
|
||||
)
|
||||
files.append((path, content))
|
||||
|
||||
# Label & Status
|
||||
# In plain text
|
||||
|
||||
for mdl, path in [
|
||||
(mw.mdlStatus, "status.txt"),
|
||||
(mw.mdlLabels, "labels.txt")
|
||||
]:
|
||||
|
||||
content = ""
|
||||
|
||||
# We skip the first row, which is empty and transparent
|
||||
for i in range(1, mdl.rowCount()):
|
||||
color = ""
|
||||
if mdl.data(mdl.index(i, 0), Qt.DecorationRole) is not None:
|
||||
color = iconColor(mdl.data(mdl.index(i, 0), Qt.DecorationRole)).name(QColor.HexRgb)
|
||||
color = color if color != "#ff000000" else "#00000000"
|
||||
|
||||
text = mdl.data(mdl.index(i, 0))
|
||||
|
||||
if text:
|
||||
content += "{name}{color}\n".format(
|
||||
name=text,
|
||||
color= "" if color == "" else ":" + " " * (20 - len(text)) + color
|
||||
)
|
||||
|
||||
files.append((path, content))
|
||||
|
||||
# Characters (self.mdlCharacter)
|
||||
# In a character folder
|
||||
|
||||
# TODO
|
||||
|
||||
# Texts
|
||||
# In an outline folder
|
||||
|
||||
# TODO
|
||||
|
||||
# World (mw.mdlWorld)
|
||||
# Either in an XML file, or in lots of plain texts?
|
||||
# More probably text, since there might be writing done in third-party.
|
||||
|
||||
# TODO
|
||||
|
||||
# Plots (mw.mdlPlots)
|
||||
# Either in XML or lots of plain texts?
|
||||
# More probably XML since there is not really a lot if writing to do (third-party)
|
||||
|
||||
# TODO
|
||||
|
||||
# Settings
|
||||
# Saved in readable text (json) for easier versionning. But they mustn't be shared, it seems.
|
||||
# Maybe include them only if zipped?
|
||||
# Well, for now, we keep them here...
|
||||
files.append(("settings.txt", settings.save(protocol=0)))
|
||||
|
||||
project = mw.currentProject
|
||||
|
||||
project = os.path.join(
|
||||
os.path.dirname(project),
|
||||
"_" + os.path.basename(project)
|
||||
)
|
||||
# Save to zip
|
||||
if zip:
|
||||
project = os.path.join(
|
||||
os.path.dirname(project),
|
||||
"_" + os.path.basename(project)
|
||||
)
|
||||
|
||||
zf = zipfile.ZipFile(project, mode="w")
|
||||
zf = zipfile.ZipFile(project, mode="w")
|
||||
|
||||
for content, filename in files:
|
||||
zf.writestr(filename, content, compress_type=compression)
|
||||
for filename, content in files:
|
||||
zf.writestr(filename, content, compress_type=compression)
|
||||
|
||||
zf.close()
|
||||
zf.close()
|
||||
|
||||
# Save to plain text
|
||||
else:
|
||||
dir = os.path.dirname(project)
|
||||
folder = os.path.splitext(os.path.basename(project))[0]
|
||||
print("Saving to folder", folder)
|
||||
|
||||
for path, content in files:
|
||||
filename = os.path.join(dir, folder, path)
|
||||
os.makedirs(os.path.dirname(filename), exist_ok=True)
|
||||
print("* Saving file", filename)
|
||||
|
||||
# TODO: the first time it saves, it will overwrite everything, since it's not yet in cache.
|
||||
# Or we have to cache while loading.
|
||||
|
||||
if not path in cache or cache[path] != content:
|
||||
print(" Not in cache or changed: we write")
|
||||
mode = "w"+ ("b" if type(content) == bytes else "")
|
||||
with open(filename, mode) as f:
|
||||
f.write(content)
|
||||
cache[path] = content
|
||||
|
||||
else:
|
||||
print(" In cache, and identical. Do nothing.")
|
||||
|
||||
|
||||
def loadProject(project):
|
||||
|
@ -78,4 +190,8 @@ def loadProject(project):
|
|||
@param project: the filename of the project to open.
|
||||
@return: an array of errors, empty if None.
|
||||
"""
|
||||
|
||||
# Don't forget to cache everything that is loaded
|
||||
# In order to save only what has changed.
|
||||
|
||||
pass
|
|
@ -460,7 +460,7 @@ class MainWindow(QMainWindow, Ui_MainWindow):
|
|||
self.currentProject = projectName
|
||||
QSettings().setValue("lastProject", projectName)
|
||||
|
||||
saveProject(version=0)
|
||||
saveProject() # version=0
|
||||
|
||||
# Giving some feedback
|
||||
print(self.tr("Project {} saved.").format(self.currentProject))
|
||||
|
|
|
@ -1,12 +1,16 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
import collections
|
||||
import json
|
||||
import pickle
|
||||
|
||||
from PyQt5.QtWidgets import qApp
|
||||
|
||||
from manuskript.enums import Outline
|
||||
|
||||
# TODO: move some/all of those settings to application settings and not project settings
|
||||
# in order to allow a shared project between several writers
|
||||
|
||||
viewSettings = {
|
||||
"Tree": {
|
||||
"Icon": "Nothing",
|
||||
|
@ -28,7 +32,8 @@ viewSettings = {
|
|||
"Background": "Nothing",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
# Application
|
||||
spellcheck = False
|
||||
dict = None
|
||||
corkSizeFactor = 100
|
||||
|
@ -81,7 +86,7 @@ frequencyAnalyzer = {
|
|||
"phraseMax": 5
|
||||
}
|
||||
|
||||
def save(filename=None):
|
||||
def save(filename=None, protocol=None):
|
||||
|
||||
global spellcheck, dict, corkSliderFactor, viewSettings, corkSizeFactor, folderView, lastTab, openIndexes, \
|
||||
autoSave, autoSaveDelay, saveOnQuit, autoSaveNoChanges, autoSaveNoChangesDelay, outlineViewColumns, \
|
||||
|
@ -107,7 +112,7 @@ def save(filename=None):
|
|||
"textEditor":textEditor,
|
||||
"revisions":revisions,
|
||||
"frequencyAnalyzer": frequencyAnalyzer
|
||||
}
|
||||
}
|
||||
|
||||
#pp=pprint.PrettyPrinter(indent=4, compact=False)
|
||||
#print("Saving:")
|
||||
|
@ -117,8 +122,15 @@ def save(filename=None):
|
|||
f = open(filename, "wb")
|
||||
pickle.dump(allSettings, f)
|
||||
else:
|
||||
return pickle.dumps(allSettings)
|
||||
|
||||
if protocol == 0:
|
||||
# This looks stupid
|
||||
# But a simple json.dumps with sort_keys will throw a TypeError
|
||||
# because of unorderable types.
|
||||
return json.dumps(json.loads(json.dumps(allSettings)), indent=4, sort_keys=True)
|
||||
else:
|
||||
return pickle.dumps(allSettings)
|
||||
|
||||
|
||||
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."""
|
||||
|
|
Loading…
Reference in a new issue