Checkpoint: opml import can be previewed in tree view

This commit is contained in:
Olivier Keshavjee 2017-11-07 12:50:40 +01:00
parent d51233ebba
commit 316651245c
7 changed files with 117 additions and 47 deletions

View file

@ -22,10 +22,11 @@ class abstractImporter:
# For folder, use "<<folder>>" # For folder, use "<<folder>>"
icon = "" icon = ""
@classmethod def startImport(self, filePath, settingsWidget):
def startImport(cls, filePath):
""" """
Takes a str path to the file/folder to import, and return `outlineItem`s. Takes a str path to the file/folder to import, and the settingsWidget
returnend by `self.settingsWidget()` containing the user set settings,
and return `outlineItem`s.
""" """
pass pass

View file

@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
# --!-- coding: utf8 --!-- # --!-- coding: utf8 --!--
from PyQt5.QtWidgets import QMessageBox from PyQt5.QtWidgets import qApp, QMessageBox
from manuskript.models.outlineModel import outlineItem from manuskript.models.outlineModel import outlineItem
from manuskript.enums import Outline from manuskript.enums import Outline
from lxml import etree as ET from lxml import etree as ET
@ -15,9 +15,56 @@ class opmlImporter(abstractImporter):
fileFormat = "OPML Files (*.opml)" fileFormat = "OPML Files (*.opml)"
icon = "text-x-opml+xml" icon = "text-x-opml+xml"
@classmethod
def startImport(cls, filePath, parentItem, settingsWidget):
"""
Import/export outline cards in OPML format.
"""
ret = False
try:
with open(filePath, 'r') as opmlFile:
opmlContent = cls.saveNewlines(opmlFile.read())
except:
QMessageBox.critical(settingsWidget,
qApp.translate("Import", "OPML Import"),
qApp.translate("Import", "File open failed."))
return None
parsed = ET.fromstring(bytes(opmlContent, 'utf-8'))
opmlNode = parsed
bodyNode = opmlNode.find("body")
items = []
if bodyNode is not None:
outlineEls = bodyNode.findall("outline")
if outlineEls is not None:
for element in outlineEls:
items.append(cls.parseItems(element, parentItem))
ret = True
if ret:
#QMessageBox.information(
#settingsWidget,
#qApp.translate("Import", "OPML Import"),
#qApp.translate("Import", "Import Complete."))
pass
else:
QMessageBox.critical(
settingsWidget,
qApp.translate("Import", "OPML Import"),
qApp.translate("Import", "This does not appear to be a valid OPML file."))
return None
return items
def importOpml(opmlFilePath, idx): def importOpml(opmlFilePath, idx):
""" """
Import/export outline cards in OPML format. Import/export outline cards in OPML format.
#FIXME: delete me when done with startImport
""" """
ret = False ret = False
mw = mainWindow() mw = mainWindow()
@ -26,7 +73,6 @@ class opmlImporter(abstractImporter):
with open(opmlFilePath, 'r') as opmlFile: with open(opmlFilePath, 'r') as opmlFile:
opmlContent = saveNewlines(opmlFile.read()) opmlContent = saveNewlines(opmlFile.read())
except: except:
# TODO: Translation
QMessageBox.critical(mw, mw.tr("OPML Import"), QMessageBox.critical(mw, mw.tr("OPML Import"),
mw.tr("File open failed.")) mw.tr("File open failed."))
return False return False
@ -67,48 +113,30 @@ class opmlImporter(abstractImporter):
return ret return ret
@classmethod
def parseItems(underElement, parentItem): def parseItems(cls, underElement, parentItem=None):
text = underElement.get('text') title = underElement.get('text')
if text is not None: if title is not None:
# In the case where the title is exceptionally long, trim it so it isn't
# distracting in the tab label
title = text[0:32]
if len(title) < len(text):
title += '...'
card = outlineItem(parent=parentItem, title=title) card = outlineItem(parent=parentItem, title=title)
body = "" body = ""
summary = ""
note = underElement.get('_note') note = underElement.get('_note')
if note is not None and not isWhitespaceOnly(note): if note is not None and not cls.isWhitespaceOnly(note):
body = restoreNewLines(note) body = cls.restoreNewLines(note)
summary = body[0:128]
else:
# There's no note (body), but there is a title. Fill the
# body with the title to support cards that consist only
# of a title.
body = text
card.setData(Outline.summaryFull.value, summary)
children = underElement.findall('outline') children = underElement.findall('outline')
if children is not None and len(children) > 0: if children is not None and len(children) > 0:
for el in children: for el in children:
parseItems(el, card) cls.parseItems(el, card)
else: else:
card.setData(Outline.type.value, 'md') card.setData(Outline.type.value, 'md')
card.setData(Outline.text.value, body) card.setData(Outline.text.value, body)
# I assume I don't have to do the following return card
# parentItem.appendChild(card)
return @classmethod
def saveNewlines(cls, inString):
def saveNewlines(inString):
""" """
Since XML parsers are notorious for stripping out significant newlines, Since XML parsers are notorious for stripping out significant newlines,
save them in a form we can restore after the parse. save them in a form we can restore after the parse.
@ -118,17 +146,19 @@ class opmlImporter(abstractImporter):
return inString return inString
def restoreNewLines(inString): @classmethod
def restoreNewLines(cls, inString):
""" """
Restore any significant newlines Restore any significant newlines
""" """
return inString.replace("{{lf}}", "\n") return inString.replace("{{lf}}", "\n")
def isWhitespaceOnly(inString): @classmethod
def isWhitespaceOnly(cls, inString):
""" """
Determine whether or not a string only contains whitespace. Determine whether or not a string only contains whitespace.
""" """
str = restoreNewLines(inString) s = cls.restoreNewLines(inString)
str = ''.join(str.split()) s = ''.join(s.split())
return len(str) is 0 return len(s) is 0

View file

@ -49,6 +49,9 @@ class Ui_generalSettings(object):
self.treeGeneralParent.setHeaderHidden(True) self.treeGeneralParent.setHeaderHidden(True)
self.treeGeneralParent.setObjectName("treeGeneralParent") self.treeGeneralParent.setObjectName("treeGeneralParent")
self.formLayout_4.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.treeGeneralParent) self.formLayout_4.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.treeGeneralParent)
self.chkGeneralTrimTitles = QtWidgets.QCheckBox(self.general)
self.chkGeneralTrimTitles.setObjectName("chkGeneralTrimTitles")
self.formLayout_4.setWidget(2, QtWidgets.QFormLayout.SpanningRole, self.chkGeneralTrimTitles)
self.verticalLayout_5.addLayout(self.formLayout_4) self.verticalLayout_5.addLayout(self.formLayout_4)
self.toolBox.addItem(self.general, "") self.toolBox.addItem(self.general, "")
self.verticalLayout_2.addWidget(self.toolBox) self.verticalLayout_2.addWidget(self.toolBox)
@ -63,5 +66,6 @@ class Ui_generalSettings(object):
generalSettings.setWindowTitle(_translate("generalSettings", "Form")) generalSettings.setWindowTitle(_translate("generalSettings", "Form"))
self.chkGeneralParent.setText(_translate("generalSettings", "Import under:")) self.chkGeneralParent.setText(_translate("generalSettings", "Import under:"))
self.chkGeneralSplitScenes.setText(_translate("generalSettings", "Split scenes at:")) self.chkGeneralSplitScenes.setText(_translate("generalSettings", "Split scenes at:"))
self.chkGeneralTrimTitles.setText(_translate("generalSettings", "Trim long titles (> 32 chars)"))
self.toolBox.setItemText(self.toolBox.indexOf(self.general), _translate("generalSettings", "General")) self.toolBox.setItemText(self.toolBox.indexOf(self.general), _translate("generalSettings", "General"))

View file

@ -90,6 +90,13 @@ QToolBox::tab:selected, QToolBox::tab:hover{
</property> </property>
</widget> </widget>
</item> </item>
<item row="2" column="0" colspan="2">
<widget class="QCheckBox" name="chkGeneralTrimTitles">
<property name="text">
<string>Trim long titles (&gt; 32 chars)</string>
</property>
</widget>
</item>
</layout> </layout>
</item> </item>
</layout> </layout>

View file

@ -157,5 +157,30 @@ class importerDialog(QWidget, Ui_importer):
############################################################################ ############################################################################
def preview(self): def preview(self):
# TODO
# We find the current selected format
F = self.currentFormat()
# Temporary outlineModel
previewModel = outlineModel(self) previewModel = outlineModel(self)
# Calling the importer in a temporary model
items = F.startImport(self.fileName,
previewModel.rootItem,
self.settingsWidget)
# Do transformations
# TODO
if items:
self.tree.setModel(previewModel)
for i in range(1, previewModel.columnCount()):
self.tree.hideColumn(i)
def startImport(self):
pass
# Note: dont forget to emit: mdl.layoutChanged.emit()
# Maybe: mw.treeRedacOutline.viewport().update()

View file

@ -80,7 +80,9 @@ class Ui_importer(object):
self.splitter_2 = QtWidgets.QSplitter(self.grpPreview) self.splitter_2 = QtWidgets.QSplitter(self.grpPreview)
self.splitter_2.setOrientation(QtCore.Qt.Horizontal) self.splitter_2.setOrientation(QtCore.Qt.Horizontal)
self.splitter_2.setObjectName("splitter_2") self.splitter_2.setObjectName("splitter_2")
self.tree = treeView(self.splitter_2) self.tree = QtWidgets.QTreeView(self.splitter_2)
self.tree.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
self.tree.setHeaderHidden(True)
self.tree.setObjectName("tree") self.tree.setObjectName("tree")
self.editor = mainEditor(self.splitter_2) self.editor = mainEditor(self.splitter_2)
self.editor.setObjectName("editor") self.editor.setObjectName("editor")
@ -102,4 +104,3 @@ class Ui_importer(object):
self.grpPreview.setTitle(_translate("importer", "Preview")) self.grpPreview.setTitle(_translate("importer", "Preview"))
from manuskript.ui.editors.mainEditor import mainEditor from manuskript.ui.editors.mainEditor import mainEditor
from manuskript.ui.views.treeView import treeView

View file

@ -178,7 +178,14 @@
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
<widget class="treeView" name="tree"/> <widget class="QTreeView" name="tree">
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
<property name="headerHidden">
<bool>true</bool>
</property>
</widget>
<widget class="mainEditor" name="editor" native="true"/> <widget class="mainEditor" name="editor" native="true"/>
</widget> </widget>
</item> </item>
@ -189,11 +196,6 @@
</layout> </layout>
</widget> </widget>
<customwidgets> <customwidgets>
<customwidget>
<class>treeView</class>
<extends>QTreeView</extends>
<header>manuskript.ui.views.treeView.h</header>
</customwidget>
<customwidget> <customwidget>
<class>mainEditor</class> <class>mainEditor</class>
<extends>QWidget</extends> <extends>QWidget</extends>