Checkpoint: basic mechanics of settings implemented

This commit is contained in:
Olivier Keshavjee 2017-11-07 11:25:19 +01:00
parent 340fceeda3
commit 221c7a181d
17 changed files with 552 additions and 258 deletions

View file

@ -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,
]

View file

@ -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 "<<folder>>"
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

View file

@ -0,0 +1,12 @@
#!/usr/bin/env python
# --!-- coding: utf8 --!--
from manuskript.importer.abstractImporter import abstractImporter
class folderImporter(abstractImporter):
name = "Folder"
description = ""
fileFormat = "<<folder>>"
icon = "folder"

View file

@ -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"

View file

@ -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

View file

@ -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

View file

@ -14,7 +14,6 @@ from manuskript.ui import style
from manuskript.ui.editors.editorWidget import editorWidget from manuskript.ui.editors.editorWidget import editorWidget
from manuskript.ui.editors.fullScreenEditor import fullScreenEditor from manuskript.ui.editors.fullScreenEditor import fullScreenEditor
from manuskript.ui.editors.mainEditor_ui import Ui_mainEditor from manuskript.ui.editors.mainEditor_ui import Ui_mainEditor
from manuskript.importer import opml as opmlInputExport
locale.setlocale(locale.LC_ALL, '') locale.setlocale(locale.LC_ALL, '')
@ -84,10 +83,6 @@ class mainEditor(QWidget, Ui_mainEditor):
self.btnRedacFullscreen.clicked.connect( self.btnRedacFullscreen.clicked.connect(
self.showFullScreen, AUC) self.showFullScreen, AUC)
self.btnImport.clicked.connect(
lambda v: self.importOPML()
)
# self.tab.setDocumentMode(False) # self.tab.setDocumentMode(False)
# Bug in Qt < 5.5: doesn't always load icons from custom theme. # 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.btnRedacFolderText.setVisible(visible)
self.btnRedacFolderCork.setVisible(visible) self.btnRedacFolderCork.setVisible(visible)
self.btnRedacFolderOutline.setVisible(visible) self.btnRedacFolderOutline.setVisible(visible)
self.btnImport.setVisible(visible)
self.sldCorkSizeFactor.setVisible(visible and self.btnRedacFolderCork.isChecked()) self.sldCorkSizeFactor.setVisible(visible and self.btnRedacFolderCork.isChecked())
self.btnRedacFullscreen.setVisible(not visible) self.btnRedacFullscreen.setVisible(not visible)
@ -344,20 +338,6 @@ class mainEditor(QWidget, Ui_mainEditor):
if self.currentEditor(): if self.currentEditor():
self._fullScreen = fullScreenEditor(self.currentEditor().currentIndex) 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 # DICT AND STUFF LIKE THAT
############################################################################### ###############################################################################

View file

@ -2,8 +2,7 @@
# Form implementation generated from reading ui file 'manuskript/ui/editors/mainEditor_ui.ui' # Form implementation generated from reading ui file 'manuskript/ui/editors/mainEditor_ui.ui'
# #
# Created: Sat Oct 14 21:30:36 2017 # Created by: PyQt5 UI code generator 5.9
# by: PyQt5 UI code generator 5.2.1
# #
# WARNING! All changes made in this file will be lost! # WARNING! All changes made in this file will be lost!
@ -14,8 +13,8 @@ class Ui_mainEditor(object):
mainEditor.setObjectName("mainEditor") mainEditor.setObjectName("mainEditor")
mainEditor.resize(791, 319) mainEditor.resize(791, 319)
self.verticalLayout = QtWidgets.QVBoxLayout(mainEditor) self.verticalLayout = QtWidgets.QVBoxLayout(mainEditor)
self.verticalLayout.setSpacing(0)
self.verticalLayout.setContentsMargins(0, 0, 0, 0) self.verticalLayout.setContentsMargins(0, 0, 0, 0)
self.verticalLayout.setSpacing(0)
self.verticalLayout.setObjectName("verticalLayout") self.verticalLayout.setObjectName("verticalLayout")
self.tabSplitter = tabSplitter(mainEditor) self.tabSplitter = tabSplitter(mainEditor)
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding)
@ -55,14 +54,6 @@ class Ui_mainEditor(object):
self.btnRedacFolderOutline.setObjectName("btnRedacFolderOutline") self.btnRedacFolderOutline.setObjectName("btnRedacFolderOutline")
self.buttonGroup.addButton(self.btnRedacFolderOutline) self.buttonGroup.addButton(self.btnRedacFolderOutline)
self.horizontalLayout_19.addWidget(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 = QtWidgets.QSlider(mainEditor)
self.sldCorkSizeFactor.setMinimumSize(QtCore.QSize(100, 0)) self.sldCorkSizeFactor.setMinimumSize(QtCore.QSize(100, 0))
self.sldCorkSizeFactor.setMaximumSize(QtCore.QSize(200, 16777215)) self.sldCorkSizeFactor.setMaximumSize(QtCore.QSize(200, 16777215))
@ -117,8 +108,6 @@ class Ui_mainEditor(object):
self.btnRedacFolderCork.setText(_translate("mainEditor", "Index cards")) self.btnRedacFolderCork.setText(_translate("mainEditor", "Index cards"))
self.btnRedacFolderOutline.setText(_translate("mainEditor", "Outline")) self.btnRedacFolderOutline.setText(_translate("mainEditor", "Outline"))
self.btnRedacFullscreen.setShortcut(_translate("mainEditor", "F11")) 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.tabSplitter import tabSplitter
from manuskript.ui.editors.textFormat import textFormat from manuskript.ui.editors.textFormat import textFormat

View file

@ -50,7 +50,9 @@
<string/> <string/>
</property> </property>
<property name="icon"> <property name="icon">
<iconset theme="go-up"/> <iconset theme="go-up">
<normaloff/>
</iconset>
</property> </property>
<property name="shortcut"> <property name="shortcut">
<string>Alt+Up</string> <string>Alt+Up</string>
@ -111,23 +113,6 @@
</attribute> </attribute>
</widget> </widget>
</item> </item>
<item>
<widget class="QPushButton" name="btnImport">
<property name="toolTip">
<!-- TODO: Translation -->
<string>Import items from an OPML file into the current folder</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset theme="document-open"/>
</property>
<property name="flat">
<bool>true</bool>
</property>
</widget>
</item>
<item> <item>
<widget class="QSlider" name="sldCorkSizeFactor"> <widget class="QSlider" name="sldCorkSizeFactor">
<property name="minimumSize"> <property name="minimumSize">

View file

@ -2,7 +2,7 @@
# Form implementation generated from reading ui file 'manuskript/ui/exporters/manuskript/plainTextSettings_ui.ui' # 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! # WARNING! All changes made in this file will be lost!
@ -28,9 +28,10 @@ class Ui_exporterSettings(object):
"}") "}")
self.toolBox.setObjectName("toolBox") self.toolBox.setObjectName("toolBox")
self.content = QtWidgets.QWidget() 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.content.setObjectName("content")
self.verticalLayout_5 = QtWidgets.QVBoxLayout(self.content) self.verticalLayout_5 = QtWidgets.QVBoxLayout(self.content)
self.verticalLayout_5.setContentsMargins(0, 0, 0, 0)
self.verticalLayout_5.setObjectName("verticalLayout_5") self.verticalLayout_5.setObjectName("verticalLayout_5")
self.label = QtWidgets.QLabel(self.content) self.label = QtWidgets.QLabel(self.content)
self.label.setObjectName("label") self.label.setObjectName("label")
@ -111,9 +112,10 @@ class Ui_exporterSettings(object):
self.verticalLayout_5.addItem(spacerItem1) self.verticalLayout_5.addItem(spacerItem1)
self.toolBox.addItem(self.content, "") self.toolBox.addItem(self.content, "")
self.separations = QtWidgets.QWidget() 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.separations.setObjectName("separations")
self.verticalLayout_8 = QtWidgets.QVBoxLayout(self.separations) self.verticalLayout_8 = QtWidgets.QVBoxLayout(self.separations)
self.verticalLayout_8.setContentsMargins(0, 0, 0, 0)
self.verticalLayout_8.setObjectName("verticalLayout_8") self.verticalLayout_8.setObjectName("verticalLayout_8")
self.label_3 = QtWidgets.QLabel(self.separations) self.label_3 = QtWidgets.QLabel(self.separations)
font = QtGui.QFont() font = QtGui.QFont()
@ -319,10 +321,11 @@ class Ui_exporterSettings(object):
self.verticalLayout_8.addItem(spacerItem6) self.verticalLayout_8.addItem(spacerItem6)
self.toolBox.addItem(self.separations, "") self.toolBox.addItem(self.separations, "")
self.transformations = QtWidgets.QWidget() 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.setStyleSheet("QGroupBox{font-weight:bold;}")
self.transformations.setObjectName("transformations") self.transformations.setObjectName("transformations")
self.verticalLayout_6 = QtWidgets.QVBoxLayout(self.transformations) self.verticalLayout_6 = QtWidgets.QVBoxLayout(self.transformations)
self.verticalLayout_6.setContentsMargins(0, 0, 0, 0)
self.verticalLayout_6.setObjectName("verticalLayout_6") self.verticalLayout_6.setObjectName("verticalLayout_6")
self.grpTransTypo = collapsibleGroupBox2(self.transformations) self.grpTransTypo = collapsibleGroupBox2(self.transformations)
self.grpTransTypo.setStyleSheet("") self.grpTransTypo.setStyleSheet("")
@ -481,10 +484,11 @@ class Ui_exporterSettings(object):
self.verticalLayout_6.addItem(spacerItem10) self.verticalLayout_6.addItem(spacerItem10)
self.toolBox.addItem(self.transformations, "") self.toolBox.addItem(self.transformations, "")
self.preview = QtWidgets.QWidget() 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.setStyleSheet("QGroupBox{font-weight:bold;}")
self.preview.setObjectName("preview") self.preview.setObjectName("preview")
self.verticalLayout_11 = QtWidgets.QVBoxLayout(self.preview) self.verticalLayout_11 = QtWidgets.QVBoxLayout(self.preview)
self.verticalLayout_11.setContentsMargins(0, 0, 0, 0)
self.verticalLayout_11.setObjectName("verticalLayout_11") self.verticalLayout_11.setObjectName("verticalLayout_11")
self.groupBox = QtWidgets.QGroupBox(self.preview) self.groupBox = QtWidgets.QGroupBox(self.preview)
self.groupBox.setObjectName("groupBox") self.groupBox.setObjectName("groupBox")

View file

@ -53,8 +53,8 @@ QToolBox::tab:selected, QToolBox::tab:hover{
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>491</width> <width>497</width>
<height>842</height> <height>834</height>
</rect> </rect>
</property> </property>
<attribute name="label"> <attribute name="label">
@ -233,7 +233,7 @@ QToolBox::tab:selected, QToolBox::tab:hover{
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>511</width> <width>511</width>
<height>522</height> <height>534</height>
</rect> </rect>
</property> </property>
<attribute name="label"> <attribute name="label">
@ -773,7 +773,7 @@ QToolBox::tab:selected, QToolBox::tab:hover{
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>511</width> <width>511</width>
<height>522</height> <height>534</height>
</rect> </rect>
</property> </property>
<property name="styleSheet"> <property name="styleSheet">
@ -1162,7 +1162,7 @@ QToolBox::tab:selected, QToolBox::tab:hover{
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>511</width> <width>511</width>
<height>522</height> <height>534</height>
</rect> </rect>
</property> </property>
<property name="styleSheet"> <property name="styleSheet">

View file

@ -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

View file

@ -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"))

View file

@ -0,0 +1,103 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>generalSettings</class>
<widget class="QWidget" name="generalSettings">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>289</width>
<height>396</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<property name="spacing">
<number>10</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QToolBox" name="toolBox">
<property name="styleSheet">
<string notr="true">QToolBox::tab{
background-color: #BBB;
padding: 2px;
border: none;
}
QToolBox::tab:selected, QToolBox::tab:hover{
background-color:skyblue;
}</string>
</property>
<property name="currentIndex">
<number>0</number>
</property>
<property name="tabSpacing">
<number>0</number>
</property>
<widget class="QWidget" name="general">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>289</width>
<height>373</height>
</rect>
</property>
<attribute name="label">
<string>General</string>
</attribute>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<layout class="QFormLayout" name="formLayout_4">
<property name="rowWrapPolicy">
<enum>QFormLayout::WrapLongRows</enum>
</property>
<item row="0" column="0">
<widget class="QCheckBox" name="chkGeneralParent">
<property name="text">
<string>Import under:</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QCheckBox" name="chkGeneralSplitScenes">
<property name="text">
<string>Split scenes at:</string>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="txtGeneralSplitScenes"/>
</item>
<item row="0" column="1">
<widget class="QTreeView" name="treeGeneralParent">
<property name="headerHidden">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View file

@ -7,15 +7,11 @@ from PyQt5.QtCore import Qt
from PyQt5.QtGui import QBrush, QColor, QIcon from PyQt5.QtGui import QBrush, QColor, QIcon
from PyQt5.QtWidgets import QWidget, QFileDialog from PyQt5.QtWidgets import QWidget, QFileDialog
from manuskript import exporter
from manuskript.functions import lightBlue, writablePath, appPath from manuskript.functions import lightBlue, writablePath, appPath
from manuskript.ui.importers.importer_ui import Ui_importer from manuskript.ui.importers.importer_ui import Ui_importer
from manuskript.ui.importers.generalSettings import generalSettings
class importFormat: from manuskript.ui import style
def __init__(self, name, icon, fileFormat): from manuskript import importer
self.name = name
self.icon = icon
self.fileFormat = fileFormat
class importerDialog(QWidget, Ui_importer): class importerDialog(QWidget, Ui_importer):
@ -37,15 +33,10 @@ class importerDialog(QWidget, Ui_importer):
# Var # Var
self.mw = mw self.mw = mw
self.fileName = "" self.fileName = ""
self.setStyleSheet(style.mainWindowSS())
# Register importFormats: # Register importFormats:
self.formats = [] self.importers = importer.importers
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",
"<<folder>>"))
# Populate combo box with formats # Populate combo box with formats
self.populateImportList() self.populateImportList()
@ -54,7 +45,10 @@ class importerDialog(QWidget, Ui_importer):
self.btnChoseFile.clicked.connect(self.selectFile) self.btnChoseFile.clicked.connect(self.selectFile)
self.btnClearFileName.clicked.connect(self.setFileName) self.btnClearFileName.clicked.connect(self.setFileName)
self.btnPreview.clicked.connect(self.preview) 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 # Combobox / Formats
@ -65,18 +59,25 @@ class importerDialog(QWidget, Ui_importer):
def addFormat(name, icon): def addFormat(name, icon):
self.cmbImporters.addItem(QIcon.fromTheme(icon), name) self.cmbImporters.addItem(QIcon.fromTheme(icon), name)
for f in self.formats: for f in self.importers:
addFormat(f.name, f.icon) 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 # Import file
############################################################################ ############################################################################
def selectFile(self): def selectFile(self):
"""
Called to select a file in the file system. Uses QFileDialog.
"""
# We find the current selected format # We find the current selected format
formatName = self.cmbImporters.currentText() F = self.currentFormat()
F = [F for F in self.formats if F.name == formatName][0]
options = QFileDialog.Options() options = QFileDialog.Options()
options |= QFileDialog.DontUseNativeDialog options |= QFileDialog.DontUseNativeDialog
@ -90,47 +91,70 @@ class importerDialog(QWidget, Ui_importer):
self.setFileName(fileName) self.setFileName(fileName)
def setFileName(self, fileName): def setFileName(self, fileName):
"""
Updates Ui with given filename. Filename can be empty.
"""
if fileName: if fileName:
self.fileName = fileName self.fileName = fileName
self.btnPreview.setEnabled(True)
self.lblFileName.setText(os.path.basename(fileName)) self.lblFileName.setText(os.path.basename(fileName))
self.lblFileName.setToolTip(fileName) self.lblFileName.setToolTip(fileName)
self.btnClearFileName.setVisible(True)
ext = os.path.splitext(fileName)[1] ext = os.path.splitext(fileName)[1]
if ext and ext in self.formatsIcon: if ext and ext in self.formatsIcon:
self.lblIcon.setVisible(True) icon = QIcon.fromTheme(self.formatsIcon[ext])
h = self.lblFileName.height()
self.lblIcon.setPixmap(
QIcon.fromTheme(self.formatsIcon[ext]).pixmap(h, h)
)
elif os.path.isdir(fileName): elif os.path.isdir(fileName):
self.lblIcon.setVisible(True) icon = QIcon.fromTheme("folder")
h = self.lblFileName.height()
self.lblIcon.setPixmap(QIcon.fromTheme("folder").pixmap(h, h)) #self.lblIcon.setVisible(True)
h = self.lblFileName.height()
self.lblIcon.setPixmap(icon.pixmap(h, h))
else: else:
self.fileName = None self.fileName = None
self.btnPreview.setEnabled(False)
self.lblFileName.setText("") 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): def preview(self):
# TODO # TODO
pass pass
############################################################################
#
############################################################################
def getParentIndex(self):
if len(self.mw.treeRedacOutline.selectionModel().
selection().indexes()) == 0:
idx = QModelIndex()
else:
idx = self.mw.treeRedacOutline.currentIndex()
return idx

View file

@ -22,12 +22,6 @@ class Ui_importer(object):
self.cmbImporters = QtWidgets.QComboBox(importer) self.cmbImporters = QtWidgets.QComboBox(importer)
self.cmbImporters.setObjectName("cmbImporters") self.cmbImporters.setObjectName("cmbImporters")
self.horizontalLayout.addWidget(self.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) spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
self.horizontalLayout.addItem(spacerItem) self.horizontalLayout.addItem(spacerItem)
self.btnChoseFile = QtWidgets.QPushButton(importer) self.btnChoseFile = QtWidgets.QPushButton(importer)
@ -59,8 +53,14 @@ class Ui_importer(object):
self.btnPreview = QtWidgets.QPushButton(importer) self.btnPreview = QtWidgets.QPushButton(importer)
icon = QtGui.QIcon.fromTheme("document-print-preview") icon = QtGui.QIcon.fromTheme("document-print-preview")
self.btnPreview.setIcon(icon) self.btnPreview.setIcon(icon)
self.btnPreview.setFlat(True)
self.btnPreview.setObjectName("btnPreview") self.btnPreview.setObjectName("btnPreview")
self.horizontalLayout.addWidget(self.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.verticalLayout.addLayout(self.horizontalLayout)
self.splitter = QtWidgets.QSplitter(importer) self.splitter = QtWidgets.QSplitter(importer)
self.splitter.setOrientation(QtCore.Qt.Horizontal) 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.setContentsMargins(0, 0, 0, 0)
self.verticalLayout_2.setSpacing(0) self.verticalLayout_2.setSpacing(0)
self.verticalLayout_2.setObjectName("verticalLayout_2") 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.verticalLayout.addWidget(self.splitter)
self.retranslateUi(importer) self.retranslateUi(importer)
@ -86,9 +90,10 @@ class Ui_importer(object):
_translate = QtCore.QCoreApplication.translate _translate = QtCore.QCoreApplication.translate
importer.setWindowTitle(_translate("importer", "Import")) importer.setWindowTitle(_translate("importer", "Import"))
self.label.setText(_translate("importer", "Format:")) self.label.setText(_translate("importer", "Format:"))
self.btnManageImporters.setToolTip(_translate("importer", "Manage importers"))
self.btnChoseFile.setText(_translate("importer", "Chose file")) self.btnChoseFile.setText(_translate("importer", "Chose file"))
self.btnClearFileName.setToolTip(_translate("importer", "Clear file"))
self.btnPreview.setText(_translate("importer", "Preview")) self.btnPreview.setText(_translate("importer", "Preview"))
self.btnImport.setText(_translate("importer", "Import"))
self.grpSettings.setTitle(_translate("importer", "Settings")) self.grpSettings.setTitle(_translate("importer", "Settings"))
self.grpPreview.setTitle(_translate("importer", "Preview")) self.grpPreview.setTitle(_translate("importer", "Preview"))

View file

@ -26,21 +26,6 @@
<item> <item>
<widget class="QComboBox" name="cmbImporters"/> <widget class="QComboBox" name="cmbImporters"/>
</item> </item>
<item>
<widget class="QPushButton" name="btnManageImporters">
<property name="toolTip">
<string>Manage importers</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset theme="preferences-system">
<normaloff/>
</iconset>
</property>
</widget>
</item>
<item> <item>
<spacer name="horizontalSpacer_2"> <spacer name="horizontalSpacer_2">
<property name="orientation"> <property name="orientation">
@ -60,7 +45,8 @@
<string>Chose file</string> <string>Chose file</string>
</property> </property>
<property name="icon"> <property name="icon">
<iconset theme="document-import"/> <iconset theme="document-import">
<normaloff>../../../../../../../../../../.designer/backup</normaloff>../../../../../../../../../../.designer/backup</iconset>
</property> </property>
</widget> </widget>
</item> </item>
@ -86,11 +72,15 @@
</item> </item>
<item> <item>
<widget class="QPushButton" name="btnClearFileName"> <widget class="QPushButton" name="btnClearFileName">
<property name="toolTip">
<string>Clear file</string>
</property>
<property name="text"> <property name="text">
<string/> <string/>
</property> </property>
<property name="icon"> <property name="icon">
<iconset theme="edit-clear"/> <iconset theme="edit-clear">
<normaloff>../../../../../../../../../../.designer/backup</normaloff>../../../../../../../../../../.designer/backup</iconset>
</property> </property>
<property name="flat"> <property name="flat">
<bool>true</bool> <bool>true</bool>
@ -117,8 +107,20 @@
</property> </property>
<property name="icon"> <property name="icon">
<iconset theme="document-print-preview"> <iconset theme="document-print-preview">
<normaloff/> <normaloff>../../../../../../../../../../.designer/backup</normaloff>../../../../../../../../../../.designer/backup</iconset>
</iconset> </property>
<property name="flat">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="btnImport">
<property name="text">
<string>Import</string>
</property>
<property name="icon">
<iconset theme="document-import"/>
</property> </property>
</widget> </widget>
</item> </item>
@ -171,6 +173,13 @@
<property name="bottomMargin"> <property name="bottomMargin">
<number>0</number> <number>0</number>
</property> </property>
<item>
<widget class="QSplitter" name="splitter_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
</widget> </widget>