diff --git a/manuskript/importer/__init__.py b/manuskript/importer/__init__.py
index 196784c..d5a0aef 100644
--- a/manuskript/importer/__init__.py
+++ b/manuskript/importer/__init__.py
@@ -10,9 +10,9 @@ from manuskript.importer.pandocImporters import markdownPandocImporter, \
importers = [
# Internal
- opmlImporter,
- folderImporter,
markdownImporter,
+ folderImporter,
+ opmlImporter,
# Pandoc
markdownPandocImporter,
diff --git a/manuskript/importer/markdownImporter.py b/manuskript/importer/markdownImporter.py
index 2e60f85..a57b6be 100644
--- a/manuskript/importer/markdownImporter.py
+++ b/manuskript/importer/markdownImporter.py
@@ -88,8 +88,8 @@ class markdownImporter(abstractImporter):
return child
ATXHeader = re.compile(r"(\#+)\s*(.+?)\s*\#*$")
- setextHeader1 = re.compile(r"(.+)\n===+$", re.MULTILINE)
- setextHeader2 = re.compile(r"(.+)\n---+$", re.MULTILINE)
+ setextHeader1 = re.compile(r"([^\#-=].+)\n(===+)$", re.MULTILINE)
+ setextHeader2 = re.compile(r"([^\#-=].+)\n(---+)$", re.MULTILINE)
# We store the level of each item in a temporary var
parent.__miLevel = 0 # markdown importer header level
@@ -117,14 +117,15 @@ class markdownImporter(abstractImporter):
# Check setext header
m = setextHeader1.match(l2)
- if not header and m:
+
+ if not header and m and len(m.group(1)) == len(m.group(2)):
header = True
level = 1
name = m.group(1)
skipNextLine = True
m = setextHeader2.match(l2)
- if not header and m:
+ if not header and m and len(m.group(1)) == len(m.group(2)):
header = True
level = 2
name = m.group(1)
@@ -160,7 +161,8 @@ class markdownImporter(abstractImporter):
# So we make it a text item
i._data[Outline.type] = "md"
i._data[Outline.text] = i.children()[0].text()
- i.removeChild(0)
+ c = i.removeChild(0)
+ items.remove(c)
return items
diff --git a/manuskript/importer/opmlImporter.py b/manuskript/importer/opmlImporter.py
index 2fce7bc..b7b8b99 100644
--- a/manuskript/importer/opmlImporter.py
+++ b/manuskript/importer/opmlImporter.py
@@ -57,7 +57,7 @@ class opmlImporter(abstractImporter):
if outlineEls is not None:
for element in outlineEls:
- items.append(cls.parseItems(element, parentItem))
+ items.extend(cls.parseItems(element, parentItem))
ret = True
if not ret:
@@ -72,10 +72,12 @@ class opmlImporter(abstractImporter):
@classmethod
def parseItems(cls, underElement, parentItem=None):
+ items = []
title = underElement.get('text')
if title is not None:
card = outlineItem(parent=parentItem, title=title)
+ items.append(card)
body = ""
note = underElement.get('_note')
@@ -86,12 +88,12 @@ class opmlImporter(abstractImporter):
children = underElement.findall('outline')
if children is not None and len(children) > 0:
for el in children:
- cls.parseItems(el, card)
+ items.extend(cls.parseItems(el, card))
else:
card.setData(Outline.type.value, 'md')
card.setData(Outline.text.value, body)
- return card
+ return items
@classmethod
def saveNewlines(cls, inString):
diff --git a/manuskript/importer/pandocImporters.py b/manuskript/importer/pandocImporters.py
index bbdfa9c..023a4b0 100644
--- a/manuskript/importer/pandocImporters.py
+++ b/manuskript/importer/pandocImporters.py
@@ -12,6 +12,7 @@ class pandocImporter(abstractImporter):
formatFrom = ""
engine = "Pandoc"
+ extraArgs = []
@classmethod
def isValid(cls):
@@ -27,10 +28,14 @@ class pandocImporter(abstractImporter):
"--from={}".format(self.formatFrom),
filePath,
"--to={}".format(formatTo),
- "--standalone",
"--wrap={}".format(wrap),
]
+ if formatTo == "opml":
+ args.append("--standalone")
+
+ args += self.extraArgs
+
r = pandocExporter().run(args)
if formatTo == "opml":
@@ -149,4 +154,3 @@ class OPMLPandocImporter(pandocImporter):
-
diff --git a/manuskript/models/outlineModel.py b/manuskript/models/outlineModel.py
index ca9eaec..a20c2e0 100644
--- a/manuskript/models/outlineModel.py
+++ b/manuskript/models/outlineModel.py
@@ -816,10 +816,56 @@ class outlineItem():
return qApp.translate("outlineModel", "{} words").format(
locale.format("%d", wc, grouping=True))
+ def copy(self):
+ """
+ Returns a copy of item, with no parent, and no ID.
+ """
+ item = outlineItem(xml=self.toXML())
+ item.setData(Outline.ID.value, None)
+ return item
- ###############################################################################
- # XML
- ###############################################################################
+ def split(self, splitMark, recursive=True):
+ """
+ Split scene at splitMark. If multiple splitMark, multiple splits.
+
+ If called on a folder and recursive is True, then it is recursively
+ applied to every children.
+ """
+ if self.isFolder() and recursive:
+ for c in self.children():
+ c.split(splitMark)
+
+ else:
+ txt = self.text().split(splitMark)
+
+ if len(txt) == 1:
+ # Mark not found
+ return False
+
+ else:
+
+ # Stores the new text
+ self.setData(Outline.text.value, txt[0])
+
+ k = 1
+ for subTxt in txt[1:]:
+ # Create a copy
+ item = self.copy()
+
+ # Change title adding _k
+ item.setData(Outline.title.value,
+ "{}_{}".format(item.title(), k+1))
+
+ # Set text
+ item.setData(Outline.text.value, subTxt)
+
+ # Inserting item
+ self.parent().insertChild(self.row()+k, item)
+ k += 1
+
+ ###############################################################################
+ # XML
+ ###############################################################################
def toXML(self):
item = ET.Element("outlineItem")
@@ -879,10 +925,9 @@ class outlineItem():
elif child.tag == "revision":
self.appendRevision(child.attrib["timestamp"], child.attrib["text"])
-
- ###############################################################################
- # IDS
- ###############################################################################
+ ###############################################################################
+ # IDS
+ ###############################################################################
def getUniqueID(self):
self.setData(Outline.ID.value, self._model.rootItem.findUniqueID())
diff --git a/manuskript/ui/importers/generalSettings.py b/manuskript/ui/importers/generalSettings.py
index 874a3fc..3940aab 100644
--- a/manuskript/ui/importers/generalSettings.py
+++ b/manuskript/ui/importers/generalSettings.py
@@ -69,3 +69,22 @@ class generalSettings(QWidget, Ui_generalSettings):
def trimLongTitles(self):
return self.chkGeneralTrimTitles.isChecked()
+ def splitScenes(self):
+ """
+ Return wheter the user wants to split scenes.
+ If unchecked, returns False.
+ If checked, returns the escaped split mark, or default (in placeholderText).
+ """
+ if self.chkGeneralSplitScenes.isChecked():
+ split = self.txtGeneralSplitScenes.text()
+
+ if not split:
+ split = self.txtGeneralSplitScenes.placeholderText()
+
+ split = split.replace("\\n", "\n")
+ split = split.replace("\\t", "\t")
+ return split
+
+ else:
+ return False
+
diff --git a/manuskript/ui/importers/generalSettings_ui.py b/manuskript/ui/importers/generalSettings_ui.py
index 0c4d36b..6ca528a 100644
--- a/manuskript/ui/importers/generalSettings_ui.py
+++ b/manuskript/ui/importers/generalSettings_ui.py
@@ -37,11 +37,10 @@ class Ui_generalSettings(object):
self.formLayout_4.setRowWrapPolicy(QtWidgets.QFormLayout.WrapLongRows)
self.formLayout_4.setObjectName("formLayout_4")
self.chkGeneralSplitScenes = QtWidgets.QCheckBox(self.general)
- self.chkGeneralSplitScenes.setEnabled(False)
self.chkGeneralSplitScenes.setObjectName("chkGeneralSplitScenes")
self.formLayout_4.setWidget(3, QtWidgets.QFormLayout.LabelRole, self.chkGeneralSplitScenes)
self.txtGeneralSplitScenes = QtWidgets.QLineEdit(self.general)
- self.txtGeneralSplitScenes.setEnabled(False)
+ self.txtGeneralSplitScenes.setText("")
self.txtGeneralSplitScenes.setObjectName("txtGeneralSplitScenes")
self.formLayout_4.setWidget(3, QtWidgets.QFormLayout.FieldRole, self.txtGeneralSplitScenes)
self.chkGeneralTrimTitles = QtWidgets.QCheckBox(self.general)
@@ -56,7 +55,7 @@ class Ui_generalSettings(object):
self.formLayout_4.setWidget(0, QtWidgets.QFormLayout.SpanningRole, self.chkGeneralParent)
self.chkGeneralTopLevel = QtWidgets.QCheckBox(self.general)
self.chkGeneralTopLevel.setObjectName("chkGeneralTopLevel")
- self.formLayout_4.setWidget(2, QtWidgets.QFormLayout.LabelRole, self.chkGeneralTopLevel)
+ self.formLayout_4.setWidget(2, QtWidgets.QFormLayout.SpanningRole, self.chkGeneralTopLevel)
self.verticalLayout_5.addLayout(self.formLayout_4)
self.toolBox.addItem(self.general, "")
self.verticalLayout_2.addWidget(self.toolBox)
@@ -70,6 +69,7 @@ class Ui_generalSettings(object):
_translate = QtCore.QCoreApplication.translate
generalSettings.setWindowTitle(_translate("generalSettings", "Form"))
self.chkGeneralSplitScenes.setText(_translate("generalSettings", "Split scenes at:"))
+ self.txtGeneralSplitScenes.setPlaceholderText(_translate("generalSettings", "\\n---\\n"))
self.chkGeneralTrimTitles.setText(_translate("generalSettings", "Trim long titles (> 32 chars)"))
self.chkGeneralParent.setText(_translate("generalSettings", "Import under:"))
self.chkGeneralTopLevel.setText(_translate("generalSettings", "Import in a top-level folder"))
diff --git a/manuskript/ui/importers/generalSettings_ui.ui b/manuskript/ui/importers/generalSettings_ui.ui
index a1ea203..955fc21 100644
--- a/manuskript/ui/importers/generalSettings_ui.ui
+++ b/manuskript/ui/importers/generalSettings_ui.ui
@@ -80,9 +80,6 @@ QToolBox::tab:selected, QToolBox::tab:hover{
-
-
- false
-
Split scenes at:
@@ -90,8 +87,11 @@ QToolBox::tab:selected, QToolBox::tab:hover{
-
-
- false
+
+
+
+
+ \n---\n
@@ -116,7 +116,7 @@ QToolBox::tab:selected, QToolBox::tab:hover{
- -
+
-
Import in a top-level folder
diff --git a/manuskript/ui/importers/importer.py b/manuskript/ui/importers/importer.py
index fff1b6f..f09ae44 100644
--- a/manuskript/ui/importers/importer.py
+++ b/manuskript/ui/importers/importer.py
@@ -64,8 +64,10 @@ class importerDialog(QWidget, Ui_importer):
def populateImportList(self):
- def addFormat(name, icon):
- self.cmbImporters.addItem(QIcon.fromTheme(icon), name)
+ def addFormat(name, icon, identifier):
+ # Identifier serves to distingues 2 importers that would have the
+ # same name.
+ self.cmbImporters.addItem(QIcon.fromTheme(icon), name, identifier)
def addHeader(name):
self.cmbImporters.addItem(name, "header")
@@ -82,7 +84,7 @@ class importerDialog(QWidget, Ui_importer):
addHeader(f.engine)
lastEngine = f.engine
- addFormat(f.name, f.icon)
+ addFormat(f.name, f.icon, "{}:{}".format(f.engine, f.name))
if not f.isValid():
item = self.cmbImporters.model().item(self.cmbImporters.count() - 1)
item.setFlags(Qt.NoItemFlags)
@@ -96,12 +98,13 @@ class importerDialog(QWidget, Ui_importer):
self.cmbImporters.setCurrentIndex(1)
def currentFormat(self):
- formatName = self.cmbImporters.currentText()
+ formatIdentifier = self.cmbImporters.currentData()
- if self.cmbImporters.currentData() == "header":
+ if formatIdentifier == "header":
return None
- F = [F for F in self.importers if F.name == formatName][0]
+ F = [F for F in self.importers
+ if formatIdentifier == "{}:{}".format(F.engine, F.name)][0]
# We instantiate the class
return F()
@@ -303,15 +306,14 @@ class importerDialog(QWidget, Ui_importer):
# Trim long titles
if self.settingsWidget.trimLongTitles():
- def trim(item):
+ for item in items:
if len(item.title()) > 32:
item.setData(Outline.title.value, item.title()[:32])
- # I think it's overkill to do it recursively, since items
- # is supposed to contain every imported items.
- for c in item.children():
- trim(c)
- for i in items:
- trim(i)
+
+ # Split at
+ if self.settingsWidget.splitScenes():
+ for item in items:
+ item.split(self.settingsWidget.splitScenes(), recursive=False)
return items