diff --git a/manuskript/importer/__init__.py b/manuskript/importer/__init__.py index e69de29..d2f0bc1 100644 --- a/manuskript/importer/__init__.py +++ b/manuskript/importer/__init__.py @@ -0,0 +1,12 @@ +#!/usr/bin/env python +# --!-- coding: utf8 --!-- + +from manuskript.importer.folderImporter import folderImporter +from manuskript.importer.markdownImporter import markdownImporter +from manuskript.importer.opmlImporter import opmlImporter + +importers = [ + markdownImporter, + opmlImporter, + folderImporter, + ] diff --git a/manuskript/importer/abstractImporter.py b/manuskript/importer/abstractImporter.py new file mode 100644 index 0000000..822ebe5 --- /dev/null +++ b/manuskript/importer/abstractImporter.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python +# --!-- coding: utf8 --!-- +import os +import shutil +import subprocess + +from PyQt5.QtCore import QSettings +from PyQt5.QtWidgets import QWidget + + +class abstractImporter: + """ + abstractImporter is used to import documents into manuskript. + + The startImport function must be subclassed. It takes a filePath (str to + the document to import), and must return `outlineItem`s. + """ + + name = "" + description = "" + fileFormat = "" # File format accepted. For example: "OPML Files (*.opml)" + # For folder, use "<>" + icon = "" + + @classmethod + def startImport(cls, filePath): + """ + Takes a str path to the file/folder to import, and return `outlineItem`s. + """ + pass + + @classmethod + def settingsWidget(cls): + """ + Returns a QWidget if needed for settings. + """ + return None + + diff --git a/manuskript/importer/folderImporter.py b/manuskript/importer/folderImporter.py new file mode 100644 index 0000000..a961888 --- /dev/null +++ b/manuskript/importer/folderImporter.py @@ -0,0 +1,12 @@ +#!/usr/bin/env python +# --!-- coding: utf8 --!-- + +from manuskript.importer.abstractImporter import abstractImporter + + +class folderImporter(abstractImporter): + + name = "Folder" + description = "" + fileFormat = "<>" + icon = "folder" diff --git a/manuskript/importer/markdownImporter.py b/manuskript/importer/markdownImporter.py new file mode 100644 index 0000000..0a3a5cd --- /dev/null +++ b/manuskript/importer/markdownImporter.py @@ -0,0 +1,12 @@ +#!/usr/bin/env python +# --!-- coding: utf8 --!-- + +from manuskript.importer.abstractImporter import abstractImporter + + +class markdownImporter(abstractImporter): + + name = "Markdown" + description = "" + fileFormat = "Markdown files (*.md; *.txt; *)" + icon = "text-x-markdown" diff --git a/manuskript/importer/opml.py b/manuskript/importer/opml.py deleted file mode 100644 index 51ff936..0000000 --- a/manuskript/importer/opml.py +++ /dev/null @@ -1,127 +0,0 @@ -#!/usr/bin/env python -# --!-- coding: utf8 --!-- - -from PyQt5.QtWidgets import QMessageBox -from manuskript.models.outlineModel import outlineItem -from manuskript.enums import Outline -from lxml import etree as ET -from manuskript.functions import mainWindow - - -def importOpml(opmlFilePath, idx): - """ - Import/export outline cards in OPML format. - """ - ret = False - mw = mainWindow() - - try: - with open(opmlFilePath, 'r') as opmlFile: - opmlContent = saveNewlines(opmlFile.read()) - except: - # TODO: Translation - QMessageBox.critical(mw, mw.tr("OPML Import"), - mw.tr("File open failed.")) - return False - - mdl = mw.mdlOutline - - if idx.internalPointer() is not None: - parentItem = idx.internalPointer() - else: - parentItem = mdl.rootItem - - try: - parsed = ET.fromstring(bytes(opmlContent, 'utf-8')) - - opmlNode = parsed - bodyNode = opmlNode.find("body") - - if bodyNode is not None: - outlineEls = bodyNode.findall("outline") - - if outlineEls is not None: - for element in outlineEls: - parseItems(element, parentItem) - - mdl.layoutChanged.emit() - mw.treeRedacOutline.viewport().update() - ret = True - except: - pass - - # TODO: Translation - if ret: - QMessageBox.information(mw, mw.tr("OPML Import"), - mw.tr("Import Complete.")) - else: - QMessageBox.critical(mw, mw.tr("OPML Import"), - mw.tr("This does not appear to be a valid OPML file.")) - - return ret - - -def parseItems(underElement, parentItem): - text = underElement.get('text') - if text 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) - - body = "" - summary = "" - note = underElement.get('_note') - if note is not None and not isWhitespaceOnly(note): - body = 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') - if children is not None and len(children) > 0: - for el in children: - parseItems(el, card) - else: - card.setData(Outline.type.value, 'md') - card.setData(Outline.text.value, body) - - # I assume I don't have to do the following - # parentItem.appendChild(card) - - return - -def saveNewlines(inString): - """ - Since XML parsers are notorious for stripping out significant newlines, - save them in a form we can restore after the parse. - """ - inString = inString.replace("\r\n", "\n") - inString = inString.replace("\n", "{{lf}}") - - return inString - -def restoreNewLines(inString): - """ - Restore any significant newlines - """ - return inString.replace("{{lf}}", "\n") - -def isWhitespaceOnly(inString): - """ - Determine whether or not a string only contains whitespace. - """ - str = restoreNewLines(inString) - str = ''.join(str.split()) - - return len(str) is 0 diff --git a/manuskript/importer/opmlImporter.py b/manuskript/importer/opmlImporter.py new file mode 100644 index 0000000..636d7b4 --- /dev/null +++ b/manuskript/importer/opmlImporter.py @@ -0,0 +1,134 @@ +#!/usr/bin/env python +# --!-- coding: utf8 --!-- + +from PyQt5.QtWidgets import QMessageBox +from manuskript.models.outlineModel import outlineItem +from manuskript.enums import Outline +from lxml import etree as ET +from manuskript.functions import mainWindow +from manuskript.importer.abstractImporter import abstractImporter + +class opmlImporter(abstractImporter): + + name = "OPML" + description = "" + fileFormat = "OPML Files (*.opml)" + icon = "text-x-opml+xml" + + def importOpml(opmlFilePath, idx): + """ + Import/export outline cards in OPML format. + """ + ret = False + mw = mainWindow() + + try: + with open(opmlFilePath, 'r') as opmlFile: + opmlContent = saveNewlines(opmlFile.read()) + except: + # TODO: Translation + QMessageBox.critical(mw, mw.tr("OPML Import"), + mw.tr("File open failed.")) + return False + + mdl = mw.mdlOutline + + if idx.internalPointer() is not None: + parentItem = idx.internalPointer() + else: + parentItem = mdl.rootItem + + try: + parsed = ET.fromstring(bytes(opmlContent, 'utf-8')) + + opmlNode = parsed + bodyNode = opmlNode.find("body") + + if bodyNode is not None: + outlineEls = bodyNode.findall("outline") + + if outlineEls is not None: + for element in outlineEls: + parseItems(element, parentItem) + + mdl.layoutChanged.emit() + mw.treeRedacOutline.viewport().update() + ret = True + except: + pass + + # TODO: Translation + if ret: + QMessageBox.information(mw, mw.tr("OPML Import"), + mw.tr("Import Complete.")) + else: + QMessageBox.critical(mw, mw.tr("OPML Import"), + mw.tr("This does not appear to be a valid OPML file.")) + + return ret + + + def parseItems(underElement, parentItem): + text = underElement.get('text') + if text 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) + + body = "" + summary = "" + note = underElement.get('_note') + if note is not None and not isWhitespaceOnly(note): + body = 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') + if children is not None and len(children) > 0: + for el in children: + parseItems(el, card) + else: + card.setData(Outline.type.value, 'md') + card.setData(Outline.text.value, body) + + # I assume I don't have to do the following + # parentItem.appendChild(card) + + return + + def saveNewlines(inString): + """ + Since XML parsers are notorious for stripping out significant newlines, + save them in a form we can restore after the parse. + """ + inString = inString.replace("\r\n", "\n") + inString = inString.replace("\n", "{{lf}}") + + return inString + + def restoreNewLines(inString): + """ + Restore any significant newlines + """ + return inString.replace("{{lf}}", "\n") + + def isWhitespaceOnly(inString): + """ + Determine whether or not a string only contains whitespace. + """ + str = restoreNewLines(inString) + str = ''.join(str.split()) + + return len(str) is 0 diff --git a/manuskript/ui/editors/mainEditor.py b/manuskript/ui/editors/mainEditor.py index 8791bfd..16358b0 100644 --- a/manuskript/ui/editors/mainEditor.py +++ b/manuskript/ui/editors/mainEditor.py @@ -14,7 +14,6 @@ from manuskript.ui import style from manuskript.ui.editors.editorWidget import editorWidget from manuskript.ui.editors.fullScreenEditor import fullScreenEditor from manuskript.ui.editors.mainEditor_ui import Ui_mainEditor -from manuskript.importer import opml as opmlInputExport locale.setlocale(locale.LC_ALL, '') @@ -84,10 +83,6 @@ class mainEditor(QWidget, Ui_mainEditor): self.btnRedacFullscreen.clicked.connect( self.showFullScreen, AUC) - self.btnImport.clicked.connect( - lambda v: self.importOPML() - ) - # self.tab.setDocumentMode(False) # Bug in Qt < 5.5: doesn't always load icons from custom theme. @@ -264,7 +259,6 @@ class mainEditor(QWidget, Ui_mainEditor): self.btnRedacFolderText.setVisible(visible) self.btnRedacFolderCork.setVisible(visible) self.btnRedacFolderOutline.setVisible(visible) - self.btnImport.setVisible(visible) self.sldCorkSizeFactor.setVisible(visible and self.btnRedacFolderCork.isChecked()) self.btnRedacFullscreen.setVisible(not visible) @@ -344,20 +338,6 @@ class mainEditor(QWidget, Ui_mainEditor): if self.currentEditor(): self._fullScreen = fullScreenEditor(self.currentEditor().currentIndex) - def importOPML(self): - from PyQt5.QtWidgets import QFileDialog - options = QFileDialog.Options() - options |= QFileDialog.DontUseNativeDialog - fileName, _ = QFileDialog.getOpenFileName(self, "Import OPML", "", - "OPML Files (*.opml)", options=options) - if fileName: - if len(self.mw.treeRedacOutline.selectionModel(). - selection().indexes()) == 0: - idx = QModelIndex() - else: - idx = self.mw.treeRedacOutline.currentIndex() - opmlInputExport.importOpml(fileName, idx) - ############################################################################### # DICT AND STUFF LIKE THAT ############################################################################### diff --git a/manuskript/ui/editors/mainEditor_ui.py b/manuskript/ui/editors/mainEditor_ui.py index 22fd1f0..45c8e6f 100644 --- a/manuskript/ui/editors/mainEditor_ui.py +++ b/manuskript/ui/editors/mainEditor_ui.py @@ -2,8 +2,7 @@ # Form implementation generated from reading ui file 'manuskript/ui/editors/mainEditor_ui.ui' # -# Created: Sat Oct 14 21:30:36 2017 -# by: PyQt5 UI code generator 5.2.1 +# Created by: PyQt5 UI code generator 5.9 # # WARNING! All changes made in this file will be lost! @@ -14,8 +13,8 @@ class Ui_mainEditor(object): mainEditor.setObjectName("mainEditor") mainEditor.resize(791, 319) self.verticalLayout = QtWidgets.QVBoxLayout(mainEditor) - self.verticalLayout.setSpacing(0) self.verticalLayout.setContentsMargins(0, 0, 0, 0) + self.verticalLayout.setSpacing(0) self.verticalLayout.setObjectName("verticalLayout") self.tabSplitter = tabSplitter(mainEditor) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding) @@ -55,14 +54,6 @@ class Ui_mainEditor(object): self.btnRedacFolderOutline.setObjectName("btnRedacFolderOutline") self.buttonGroup.addButton(self.btnRedacFolderOutline) self.horizontalLayout_19.addWidget(self.btnRedacFolderOutline) - self.btnImport = QtWidgets.QPushButton(mainEditor) - self.btnImport.setText("") - icon = QtGui.QIcon.fromTheme("document-open") - self.btnImport.setIcon(icon) - self.btnImport.setFlat(True) - self.btnImport.setObjectName("btnImport") - self.buttonGroup.addButton(self.btnImport) - self.horizontalLayout_19.addWidget(self.btnImport) self.sldCorkSizeFactor = QtWidgets.QSlider(mainEditor) self.sldCorkSizeFactor.setMinimumSize(QtCore.QSize(100, 0)) self.sldCorkSizeFactor.setMaximumSize(QtCore.QSize(200, 16777215)) @@ -117,8 +108,6 @@ class Ui_mainEditor(object): self.btnRedacFolderCork.setText(_translate("mainEditor", "Index cards")) self.btnRedacFolderOutline.setText(_translate("mainEditor", "Outline")) self.btnRedacFullscreen.setShortcut(_translate("mainEditor", "F11")) - # TODO: Translation - self.btnImport.setToolTip(_translate("mainEditor", "Import items from an OPML file into the current folder")) from manuskript.ui.editors.tabSplitter import tabSplitter from manuskript.ui.editors.textFormat import textFormat diff --git a/manuskript/ui/editors/mainEditor_ui.ui b/manuskript/ui/editors/mainEditor_ui.ui index ce73c97..1110a34 100644 --- a/manuskript/ui/editors/mainEditor_ui.ui +++ b/manuskript/ui/editors/mainEditor_ui.ui @@ -50,7 +50,9 @@ - + + + Alt+Up @@ -111,23 +113,6 @@ - - - - - Import items from an OPML file into the current folder - - - - - - - - - true - - - diff --git a/manuskript/ui/exporters/manuskript/plainTextSettings_ui.py b/manuskript/ui/exporters/manuskript/plainTextSettings_ui.py index 77598ba..a6c8f98 100644 --- a/manuskript/ui/exporters/manuskript/plainTextSettings_ui.py +++ b/manuskript/ui/exporters/manuskript/plainTextSettings_ui.py @@ -2,7 +2,7 @@ # Form implementation generated from reading ui file 'manuskript/ui/exporters/manuskript/plainTextSettings_ui.ui' # -# Created by: PyQt5 UI code generator 5.4.2 +# Created by: PyQt5 UI code generator 5.9 # # WARNING! All changes made in this file will be lost! @@ -28,9 +28,10 @@ class Ui_exporterSettings(object): "}") self.toolBox.setObjectName("toolBox") self.content = QtWidgets.QWidget() - self.content.setGeometry(QtCore.QRect(0, 0, 491, 842)) + self.content.setGeometry(QtCore.QRect(0, 0, 497, 834)) self.content.setObjectName("content") self.verticalLayout_5 = QtWidgets.QVBoxLayout(self.content) + self.verticalLayout_5.setContentsMargins(0, 0, 0, 0) self.verticalLayout_5.setObjectName("verticalLayout_5") self.label = QtWidgets.QLabel(self.content) self.label.setObjectName("label") @@ -111,9 +112,10 @@ class Ui_exporterSettings(object): self.verticalLayout_5.addItem(spacerItem1) self.toolBox.addItem(self.content, "") self.separations = QtWidgets.QWidget() - self.separations.setGeometry(QtCore.QRect(0, 0, 511, 522)) + self.separations.setGeometry(QtCore.QRect(0, 0, 511, 534)) self.separations.setObjectName("separations") self.verticalLayout_8 = QtWidgets.QVBoxLayout(self.separations) + self.verticalLayout_8.setContentsMargins(0, 0, 0, 0) self.verticalLayout_8.setObjectName("verticalLayout_8") self.label_3 = QtWidgets.QLabel(self.separations) font = QtGui.QFont() @@ -319,10 +321,11 @@ class Ui_exporterSettings(object): self.verticalLayout_8.addItem(spacerItem6) self.toolBox.addItem(self.separations, "") self.transformations = QtWidgets.QWidget() - self.transformations.setGeometry(QtCore.QRect(0, 0, 511, 522)) + self.transformations.setGeometry(QtCore.QRect(0, 0, 511, 534)) self.transformations.setStyleSheet("QGroupBox{font-weight:bold;}") self.transformations.setObjectName("transformations") self.verticalLayout_6 = QtWidgets.QVBoxLayout(self.transformations) + self.verticalLayout_6.setContentsMargins(0, 0, 0, 0) self.verticalLayout_6.setObjectName("verticalLayout_6") self.grpTransTypo = collapsibleGroupBox2(self.transformations) self.grpTransTypo.setStyleSheet("") @@ -481,10 +484,11 @@ class Ui_exporterSettings(object): self.verticalLayout_6.addItem(spacerItem10) self.toolBox.addItem(self.transformations, "") self.preview = QtWidgets.QWidget() - self.preview.setGeometry(QtCore.QRect(0, 0, 511, 522)) + self.preview.setGeometry(QtCore.QRect(0, 0, 511, 534)) self.preview.setStyleSheet("QGroupBox{font-weight:bold;}") self.preview.setObjectName("preview") self.verticalLayout_11 = QtWidgets.QVBoxLayout(self.preview) + self.verticalLayout_11.setContentsMargins(0, 0, 0, 0) self.verticalLayout_11.setObjectName("verticalLayout_11") self.groupBox = QtWidgets.QGroupBox(self.preview) self.groupBox.setObjectName("groupBox") diff --git a/manuskript/ui/exporters/manuskript/plainTextSettings_ui.ui b/manuskript/ui/exporters/manuskript/plainTextSettings_ui.ui index 8064947..15c1a5e 100644 --- a/manuskript/ui/exporters/manuskript/plainTextSettings_ui.ui +++ b/manuskript/ui/exporters/manuskript/plainTextSettings_ui.ui @@ -53,8 +53,8 @@ QToolBox::tab:selected, QToolBox::tab:hover{ 0 0 - 491 - 842 + 497 + 834 @@ -233,7 +233,7 @@ QToolBox::tab:selected, QToolBox::tab:hover{ 0 0 511 - 522 + 534 @@ -773,7 +773,7 @@ QToolBox::tab:selected, QToolBox::tab:hover{ 0 0 511 - 522 + 534 @@ -1162,7 +1162,7 @@ QToolBox::tab:selected, QToolBox::tab:hover{ 0 0 511 - 522 + 534 diff --git a/manuskript/ui/importers/generalSettings.py b/manuskript/ui/importers/generalSettings.py new file mode 100644 index 0000000..7dd96fc --- /dev/null +++ b/manuskript/ui/importers/generalSettings.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python +# --!-- coding: utf8 --!-- +import json +import os + +from PyQt5.QtCore import Qt, QSize, QSortFilterProxyModel +from PyQt5.QtGui import QIcon, QFontMetrics, QFont +from PyQt5.QtWidgets import QWidget, QTableWidgetItem, QListWidgetItem, QTreeView + +from manuskript.functions import mainWindow, writablePath +from manuskript.ui.importers.generalSettings_ui import Ui_generalSettings +from manuskript.enums import Outline + +class generalSettings(QWidget, Ui_generalSettings): + def __init__(self, parent=None): + QWidget.__init__(self, parent) + self.setupUi(self) + + self.mw = mainWindow() + + # TreeView to select parent + # We use a proxy to display only folders + proxy = QSortFilterProxyModel() + proxy.setFilterKeyColumn(Outline.type.value) + proxy.setFilterFixedString("folder") + proxy.setSourceModel(self.mw.mdlOutline) + self.treeGeneralParent.setModel(proxy) + for i in range(1, self.mw.mdlOutline.columnCount()): + self.treeGeneralParent.hideColumn(i) + self.treeGeneralParent.setCurrentIndex(self.getParentIndex()) + self.chkGeneralParent.toggled.connect(self.treeGeneralParent.setVisible) + self.treeGeneralParent.hide() + self.treeGeneralParent.selectionModel().currentChanged.connect( + lambda: print(self.treeGeneralParent.currentIndex().row())) + + def getParentIndex(self): + """ + Returns the currently selected index in the mainWindow. + """ + if len(self.mw.treeRedacOutline.selectionModel(). + selection().indexes()) == 0: + idx = QModelIndex() + else: + idx = self.mw.treeRedacOutline.currentIndex() + return idx + diff --git a/manuskript/ui/importers/generalSettings_ui.py b/manuskript/ui/importers/generalSettings_ui.py new file mode 100644 index 0000000..078ca2b --- /dev/null +++ b/manuskript/ui/importers/generalSettings_ui.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- + +# Form implementation generated from reading ui file 'manuskript/ui/importers/generalSettings_ui.ui' +# +# Created by: PyQt5 UI code generator 5.9 +# +# WARNING! All changes made in this file will be lost! + +from PyQt5 import QtCore, QtGui, QtWidgets + +class Ui_generalSettings(object): + def setupUi(self, generalSettings): + generalSettings.setObjectName("generalSettings") + generalSettings.resize(289, 396) + self.verticalLayout_2 = QtWidgets.QVBoxLayout(generalSettings) + self.verticalLayout_2.setContentsMargins(0, 0, 0, 0) + self.verticalLayout_2.setSpacing(10) + self.verticalLayout_2.setObjectName("verticalLayout_2") + self.toolBox = QtWidgets.QToolBox(generalSettings) + self.toolBox.setStyleSheet("QToolBox::tab{\n" +" background-color: #BBB;\n" +" padding: 2px;\n" +" border: none;\n" +"}\n" +"\n" +"QToolBox::tab:selected, QToolBox::tab:hover{\n" +" background-color:skyblue;\n" +"}") + self.toolBox.setObjectName("toolBox") + self.general = QtWidgets.QWidget() + self.general.setGeometry(QtCore.QRect(0, 0, 289, 373)) + self.general.setObjectName("general") + self.verticalLayout_5 = QtWidgets.QVBoxLayout(self.general) + self.verticalLayout_5.setContentsMargins(0, 0, 0, 0) + self.verticalLayout_5.setObjectName("verticalLayout_5") + self.formLayout_4 = QtWidgets.QFormLayout() + self.formLayout_4.setRowWrapPolicy(QtWidgets.QFormLayout.WrapLongRows) + self.formLayout_4.setObjectName("formLayout_4") + self.chkGeneralParent = QtWidgets.QCheckBox(self.general) + self.chkGeneralParent.setObjectName("chkGeneralParent") + self.formLayout_4.setWidget(0, QtWidgets.QFormLayout.LabelRole, self.chkGeneralParent) + self.chkGeneralSplitScenes = QtWidgets.QCheckBox(self.general) + self.chkGeneralSplitScenes.setObjectName("chkGeneralSplitScenes") + self.formLayout_4.setWidget(1, QtWidgets.QFormLayout.LabelRole, self.chkGeneralSplitScenes) + self.txtGeneralSplitScenes = QtWidgets.QLineEdit(self.general) + self.txtGeneralSplitScenes.setObjectName("txtGeneralSplitScenes") + self.formLayout_4.setWidget(1, QtWidgets.QFormLayout.FieldRole, self.txtGeneralSplitScenes) + self.treeGeneralParent = QtWidgets.QTreeView(self.general) + self.treeGeneralParent.setHeaderHidden(True) + self.treeGeneralParent.setObjectName("treeGeneralParent") + self.formLayout_4.setWidget(0, QtWidgets.QFormLayout.FieldRole, self.treeGeneralParent) + self.verticalLayout_5.addLayout(self.formLayout_4) + self.toolBox.addItem(self.general, "") + self.verticalLayout_2.addWidget(self.toolBox) + + self.retranslateUi(generalSettings) + self.toolBox.setCurrentIndex(0) + self.toolBox.layout().setSpacing(0) + QtCore.QMetaObject.connectSlotsByName(generalSettings) + + def retranslateUi(self, generalSettings): + _translate = QtCore.QCoreApplication.translate + generalSettings.setWindowTitle(_translate("generalSettings", "Form")) + self.chkGeneralParent.setText(_translate("generalSettings", "Import under:")) + self.chkGeneralSplitScenes.setText(_translate("generalSettings", "Split scenes at:")) + self.toolBox.setItemText(self.toolBox.indexOf(self.general), _translate("generalSettings", "General")) + diff --git a/manuskript/ui/importers/generalSettings_ui.ui b/manuskript/ui/importers/generalSettings_ui.ui new file mode 100644 index 0000000..53446d2 --- /dev/null +++ b/manuskript/ui/importers/generalSettings_ui.ui @@ -0,0 +1,103 @@ + + + generalSettings + + + + 0 + 0 + 289 + 396 + + + + Form + + + + 10 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + QToolBox::tab{ + background-color: #BBB; + padding: 2px; + border: none; +} + +QToolBox::tab:selected, QToolBox::tab:hover{ + background-color:skyblue; +} + + + 0 + + + 0 + + + + + 0 + 0 + 289 + 373 + + + + General + + + + + + QFormLayout::WrapLongRows + + + + + Import under: + + + + + + + Split scenes at: + + + + + + + + + + true + + + + + + + + + + + + + + diff --git a/manuskript/ui/importers/importer.py b/manuskript/ui/importers/importer.py index 3254a92..4aaad99 100644 --- a/manuskript/ui/importers/importer.py +++ b/manuskript/ui/importers/importer.py @@ -7,15 +7,11 @@ from PyQt5.QtCore import Qt from PyQt5.QtGui import QBrush, QColor, QIcon from PyQt5.QtWidgets import QWidget, QFileDialog -from manuskript import exporter from manuskript.functions import lightBlue, writablePath, appPath from manuskript.ui.importers.importer_ui import Ui_importer - -class importFormat: - def __init__(self, name, icon, fileFormat): - self.name = name - self.icon = icon - self.fileFormat = fileFormat +from manuskript.ui.importers.generalSettings import generalSettings +from manuskript.ui import style +from manuskript import importer class importerDialog(QWidget, Ui_importer): @@ -37,15 +33,10 @@ class importerDialog(QWidget, Ui_importer): # Var self.mw = mw self.fileName = "" + self.setStyleSheet(style.mainWindowSS()) # Register importFormats: - self.formats = [] - self.formats.append(importFormat("OPML", "text-x-opml+xml", - "OPML Files (*.opml)")) - self.formats.append(importFormat("Markdown", "text-x-markdown", - "Markdown files (*.md; *.txt; *)")) - self.formats.append(importFormat("Folder", "folder", - "<>")) + self.importers = importer.importers # Populate combo box with formats self.populateImportList() @@ -54,7 +45,10 @@ class importerDialog(QWidget, Ui_importer): self.btnChoseFile.clicked.connect(self.selectFile) self.btnClearFileName.clicked.connect(self.setFileName) self.btnPreview.clicked.connect(self.preview) - self.setFileName("") + self.cmbImporters.currentTextChanged.connect(self.updateSettings) + + #self.setFileName("") + self.setFileName("/home/olivier/Dropbox/Documents/Travail/Geekeries/Python/PyCharmProjects/manuskript/test-projects/IMPORTS/End Plan 2.opml") ############################################################################ # Combobox / Formats @@ -65,18 +59,25 @@ class importerDialog(QWidget, Ui_importer): def addFormat(name, icon): self.cmbImporters.addItem(QIcon.fromTheme(icon), name) - for f in self.formats: + for f in self.importers: addFormat(f.name, f.icon) + def currentFormat(self): + formatName = self.cmbImporters.currentText() + F = [F for F in self.importers if F.name == formatName][0] + return F + ############################################################################ # Import file ############################################################################ def selectFile(self): + """ + Called to select a file in the file system. Uses QFileDialog. + """ # We find the current selected format - formatName = self.cmbImporters.currentText() - F = [F for F in self.formats if F.name == formatName][0] + F = self.currentFormat() options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog @@ -90,47 +91,70 @@ class importerDialog(QWidget, Ui_importer): self.setFileName(fileName) def setFileName(self, fileName): + """ + Updates Ui with given filename. Filename can be empty. + """ if fileName: self.fileName = fileName - self.btnPreview.setEnabled(True) self.lblFileName.setText(os.path.basename(fileName)) self.lblFileName.setToolTip(fileName) - self.btnClearFileName.setVisible(True) ext = os.path.splitext(fileName)[1] if ext and ext in self.formatsIcon: - self.lblIcon.setVisible(True) - h = self.lblFileName.height() - self.lblIcon.setPixmap( - QIcon.fromTheme(self.formatsIcon[ext]).pixmap(h, h) - ) + icon = QIcon.fromTheme(self.formatsIcon[ext]) elif os.path.isdir(fileName): - self.lblIcon.setVisible(True) - h = self.lblFileName.height() - self.lblIcon.setPixmap(QIcon.fromTheme("folder").pixmap(h, h)) + icon = QIcon.fromTheme("folder") + + #self.lblIcon.setVisible(True) + h = self.lblFileName.height() + self.lblIcon.setPixmap(icon.pixmap(h, h)) else: self.fileName = None - self.btnPreview.setEnabled(False) self.lblFileName.setText("") - self.btnClearFileName.setVisible(False) - self.lblIcon.setVisible(False) + + hasFile = True if fileName else False + + self.btnClearFileName.setVisible(hasFile) + self.lblIcon.setVisible(hasFile) + self.btnChoseFile.setVisible(not hasFile) + self.btnPreview.setEnabled(hasFile) + self.btnImport.setEnabled(hasFile) ############################################################################ - # Preview + # UI + ############################################################################ + + def updateSettings(self): + """ + When the current format change (through the combobox), we update the + settings widget using the current format provided settings widget. + """ + + F = self.currentFormat() + self.settingsWidget = generalSettings() + self.setGroupWidget(self.grpSettings, self.settingsWidget) + + #TODO: custom format widget + + def setGroupWidget(self, group, widget): + """ + Sets the given widget as main widget for QGroupBox group. + """ + + # Removes every items from given layout. + l = group.layout() + while l.count(): + item = l.itemAt(0) + l.removeItem(item) + item.widget().deleteLater() + + l.addWidget(widget) + widget.setParent(group) + + ############################################################################ + # Preview / Import ############################################################################ def preview(self): # TODO pass - - ############################################################################ - # - ############################################################################ - - def getParentIndex(self): - if len(self.mw.treeRedacOutline.selectionModel(). - selection().indexes()) == 0: - idx = QModelIndex() - else: - idx = self.mw.treeRedacOutline.currentIndex() - return idx diff --git a/manuskript/ui/importers/importer_ui.py b/manuskript/ui/importers/importer_ui.py index b6730a5..7d39329 100644 --- a/manuskript/ui/importers/importer_ui.py +++ b/manuskript/ui/importers/importer_ui.py @@ -22,12 +22,6 @@ class Ui_importer(object): self.cmbImporters = QtWidgets.QComboBox(importer) self.cmbImporters.setObjectName("cmbImporters") self.horizontalLayout.addWidget(self.cmbImporters) - self.btnManageImporters = QtWidgets.QPushButton(importer) - self.btnManageImporters.setText("") - icon = QtGui.QIcon.fromTheme("preferences-system") - self.btnManageImporters.setIcon(icon) - self.btnManageImporters.setObjectName("btnManageImporters") - self.horizontalLayout.addWidget(self.btnManageImporters) spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.horizontalLayout.addItem(spacerItem) self.btnChoseFile = QtWidgets.QPushButton(importer) @@ -59,8 +53,14 @@ class Ui_importer(object): self.btnPreview = QtWidgets.QPushButton(importer) icon = QtGui.QIcon.fromTheme("document-print-preview") self.btnPreview.setIcon(icon) + self.btnPreview.setFlat(True) self.btnPreview.setObjectName("btnPreview") self.horizontalLayout.addWidget(self.btnPreview) + self.btnImport = QtWidgets.QPushButton(importer) + icon = QtGui.QIcon.fromTheme("document-import") + self.btnImport.setIcon(icon) + self.btnImport.setObjectName("btnImport") + self.horizontalLayout.addWidget(self.btnImport) self.verticalLayout.addLayout(self.horizontalLayout) self.splitter = QtWidgets.QSplitter(importer) self.splitter.setOrientation(QtCore.Qt.Horizontal) @@ -77,6 +77,10 @@ class Ui_importer(object): self.verticalLayout_2.setContentsMargins(0, 0, 0, 0) self.verticalLayout_2.setSpacing(0) self.verticalLayout_2.setObjectName("verticalLayout_2") + self.splitter_2 = QtWidgets.QSplitter(self.grpPreview) + self.splitter_2.setOrientation(QtCore.Qt.Horizontal) + self.splitter_2.setObjectName("splitter_2") + self.verticalLayout_2.addWidget(self.splitter_2) self.verticalLayout.addWidget(self.splitter) self.retranslateUi(importer) @@ -86,9 +90,10 @@ class Ui_importer(object): _translate = QtCore.QCoreApplication.translate importer.setWindowTitle(_translate("importer", "Import")) self.label.setText(_translate("importer", "Format:")) - self.btnManageImporters.setToolTip(_translate("importer", "Manage importers")) self.btnChoseFile.setText(_translate("importer", "Chose file")) + self.btnClearFileName.setToolTip(_translate("importer", "Clear file")) self.btnPreview.setText(_translate("importer", "Preview")) + self.btnImport.setText(_translate("importer", "Import")) self.grpSettings.setTitle(_translate("importer", "Settings")) self.grpPreview.setTitle(_translate("importer", "Preview")) diff --git a/manuskript/ui/importers/importer_ui.ui b/manuskript/ui/importers/importer_ui.ui index c7877ab..404db62 100644 --- a/manuskript/ui/importers/importer_ui.ui +++ b/manuskript/ui/importers/importer_ui.ui @@ -26,21 +26,6 @@ - - - - Manage importers - - - - - - - - - - - @@ -60,7 +45,8 @@ Chose file - + + ../../../../../../../../../../.designer/backup../../../../../../../../../../.designer/backup @@ -86,11 +72,15 @@ + + Clear file + - + + ../../../../../../../../../../.designer/backup../../../../../../../../../../.designer/backup true @@ -117,8 +107,20 @@ - - + ../../../../../../../../../../.designer/backup../../../../../../../../../../.designer/backup + + + true + + + + + + + Import + + + @@ -171,6 +173,13 @@ 0 + + + + Qt::Horizontal + + +