diff --git a/src/functions.py b/src/functions.py index 72f1864..8eacdab 100644 --- a/src/functions.py +++ b/src/functions.py @@ -6,6 +6,9 @@ from random import * from enums import * import os +# Used to detect multiple connections +AUC = Qt.AutoConnection | Qt.UniqueConnection + def wordCount(text): return len(text.strip().replace(" ", "\n").split("\n")) if text else 0 diff --git a/src/main.py b/src/main.py index 0417fd6..79c1a74 100644 --- a/src/main.py +++ b/src/main.py @@ -6,7 +6,7 @@ from qt import * _version = "0.1" import faulthandler -faulthandler.enable() +#faulthandler.enable() def run(): diff --git a/src/mainWindow.py b/src/mainWindow.py index f824cd7..074d6f1 100644 --- a/src/mainWindow.py +++ b/src/mainWindow.py @@ -84,10 +84,12 @@ class MainWindow(QMainWindow, Ui_MainWindow): self.actStatus.triggered.connect(self.settingsStatus) self.actSettings.triggered.connect(self.settingsWindow) self.actCloseProject.triggered.connect(self.closeProject) - self.actQuit.triggered.connect(self.close) self.generateViewMenu() + self.makeUIConnections() + + #self.loadProject(os.path.join(appPath(), "test_project.zip")) ############################################################################### @@ -561,6 +563,38 @@ class MainWindow(QMainWindow, Ui_MainWindow): # MAIN CONNECTIONS ############################################################################### + def makeUIConnections(self): + "Connections that have to be made once only, event when new project is loaded." + self.btnAddPerso.clicked.connect(self.createPerso, AUC) + self.btnRmPerso.clicked.connect(self.removePerso, AUC) + self.btnPersoColor.clicked.connect(self.chosePersoColor, AUC) + + self.txtPlotFilter.textChanged.connect(self.lstPlots.setFilter, AUC) + self.lstPlots.currentItemChanged.connect(self.changeCurrentPlot, AUC) + self.txtSubPlotSummary.document().contentsChanged.connect( + self.updateSubPlotSummary, AUC) + self.lstSubPlots.activated.connect(self.changeCurrentSubPlot, AUC) + + self.btnRedacAddFolder.clicked.connect(self.treeRedacOutline.addFolder, AUC) + self.btnPlanAddFolder.clicked.connect(self.treePlanOutline.addFolder, AUC) + self.btnRedacAddText.clicked.connect(self.treeRedacOutline.addText, AUC) + self.btnPlanAddText.clicked.connect(self.treePlanOutline.addText, AUC) + self.btnRedacRemoveItem.clicked.connect(self.outlineRemoveItems, AUC) + self.btnPlanRemoveItem.clicked.connect(self.outlineRemoveItems, AUC) + + self.sldCorkSizeFactor.valueChanged.connect( + self.redacEditor.setCorkSizeFactor, AUC) + self.btnRedacFolderCork.toggled.connect( + self.sldCorkSizeFactor.setVisible, AUC) + self.btnRedacFolderText.clicked.connect( + lambda v: self.redacEditor.setFolderView("text"), AUC) + self.btnRedacFolderCork.clicked.connect( + lambda v: self.redacEditor.setFolderView("cork"), AUC) + self.btnRedacFolderOutline.clicked.connect( + lambda v: self.redacEditor.setFolderView("outline"), AUC) + + + def makeConnections(self): # Flat datas (Summary and general infos) @@ -607,11 +641,8 @@ class MainWindow(QMainWindow, Ui_MainWindow): self.tblPersoInfos.setModel(self.mdlPersosInfos) self.tblPersoInfos.setRowHidden(0, True) - self.btnAddPerso.clicked.connect(self.createPerso) - self.btnRmPerso.clicked.connect(self.removePerso) - self.btnPersoColor.clicked.connect(self.chosePersoColor) self.btnPersoAddInfo.clicked.connect(lambda: - self.mdlPersosInfos.insertRow(self.mdlPersosInfos.rowCount())) + self.mdlPersosInfos.insertRow(self.mdlPersosInfos.rowCount()), AUC) self.mprPersos = QDataWidgetMapper() self.mprPersos.setModel(self.mdlPersos) @@ -630,30 +661,25 @@ class MainWindow(QMainWindow, Ui_MainWindow): self.mprPersos.addMapping(w, i) self.mprPersos.addMapping(self.sldPersoImportance, Perso.importance.value, "importance") - self.sldPersoImportance.importanceChanged.connect(self.mprPersos.submit) - self.tabMain.currentChanged.connect(self.mprPersos.submit) + self.sldPersoImportance.importanceChanged.connect(self.mprPersos.submit, AUC) + self.tabMain.currentChanged.connect(self.mprPersos.submit, AUC) self.mprPersos.setCurrentIndex(0) self.lstPersos.selectionModel().currentChanged.connect( - self.changeCurrentPerso) + self.changeCurrentPerso, AUC) self.tabPersos.currentChanged.connect(self.resizePersosInfos) # Plots self.lstPlots.setPlotModel(self.mdlPlots) - self.txtPlotFilter.textChanged.connect(self.lstPlots.setFilter) - self.lstPlots.currentItemChanged.connect(self.changeCurrentPlot) self.lstPlotPerso.setModel(self.mdlPlots) self.lstSubPlots.setModel(self.mdlPlots) self._updatingSubPlot = False - self.txtSubPlotSummary.document().contentsChanged.connect( - self.updateSubPlotSummary) - self.lstSubPlots.activated.connect(self.changeCurrentSubPlot) - self.btnAddPlot.clicked.connect(self.mdlPlots.addPlot) + self.btnAddPlot.clicked.connect(self.mdlPlots.addPlot, AUC) self.btnRmPlot.clicked.connect(lambda: - self.mdlPlots.removePlot(self.lstPlots.currentPlotIndex())) - self.btnAddSubPlot.clicked.connect(self.mdlPlots.addSubPlot) - self.btnRmSubPlot.clicked.connect(self.mdlPlots.removeSubPlot) - self.btnRmPlotPerso.clicked.connect(self.mdlPlots.removePlotPerso) + self.mdlPlots.removePlot(self.lstPlots.currentPlotIndex()), AUC) + self.btnAddSubPlot.clicked.connect(self.mdlPlots.addSubPlot, AUC) + self.btnRmSubPlot.clicked.connect(self.mdlPlots.removeSubPlot, AUC) + self.btnRmPlotPerso.clicked.connect(self.mdlPlots.removePlotPerso, AUC) for w, c in [ (self.txtPlotName, Plot.name.value), @@ -684,45 +710,27 @@ class MainWindow(QMainWindow, Ui_MainWindow): self.redacEditor.setModel(self.mdlOutline) self.treePlanOutline.selectionModel().selectionChanged.connect(lambda: - self.outlineItemEditor.selectionChanged(self.treePlanOutline)) + self.outlineItemEditor.selectionChanged(self.treePlanOutline), AUC) self.treePlanOutline.clicked.connect(lambda: - self.outlineItemEditor.selectionChanged(self.treePlanOutline)) + self.outlineItemEditor.selectionChanged(self.treePlanOutline), AUC) self.treeRedacOutline.setSelectionModel(self.treePlanOutline .selectionModel()) - self.btnRedacAddFolder.clicked.connect(self.treeRedacOutline.addFolder) - self.btnPlanAddFolder.clicked.connect(self.treePlanOutline.addFolder) - self.btnRedacAddText.clicked.connect(self.treeRedacOutline.addText) - self.btnPlanAddText.clicked.connect(self.treePlanOutline.addText) - self.btnRedacRemoveItem.clicked.connect(self.outlineRemoveItems) - self.btnPlanRemoveItem.clicked.connect(self.outlineRemoveItems) - self.treeRedacOutline.selectionModel().selectionChanged.connect( - lambda: self.redacMetadata.selectionChanged(self.treeRedacOutline)) + lambda: self.redacMetadata.selectionChanged(self.treeRedacOutline), AUC) self.treeRedacOutline.clicked.connect( - lambda: self.redacMetadata.selectionChanged(self.treeRedacOutline)) + lambda: self.redacMetadata.selectionChanged(self.treeRedacOutline), AUC) #self.treeRedacOutline.selectionModel().currentChanged.connect(self.redacEditor.setCurrentModelIndex) - self.treeRedacOutline.selectionModel().selectionChanged.connect(self.redacEditor.setView) - self.treeRedacOutline.selectionModel().currentChanged.connect(self.redacEditor.txtRedacText.setCurrentModelIndex) + self.treeRedacOutline.selectionModel().selectionChanged.connect(self.redacEditor.setView, AUC) + self.treeRedacOutline.selectionModel().currentChanged.connect(self.redacEditor.txtRedacText.setCurrentModelIndex, AUC) - self.treeRedacOutline.selectionModel().selectionChanged.connect(self.outlineSelectionChanged) - self.treeRedacOutline.selectionModel().selectionChanged.connect(self.outlineSelectionChanged) - self.treePlanOutline.selectionModel().selectionChanged.connect(self.outlineSelectionChanged) - self.treePlanOutline.selectionModel().selectionChanged.connect(self.outlineSelectionChanged) + self.treeRedacOutline.selectionModel().selectionChanged.connect(self.outlineSelectionChanged, AUC) + #self.treeRedacOutline.selectionModel().selectionChanged.connect(self.outlineSelectionChanged, AUC) + #self.treePlanOutline.selectionModel().selectionChanged.connect(self.outlineSelectionChanged, AUC) + #self.treePlanOutline.selectionModel().selectionChanged.connect(self.outlineSelectionChanged, AUC) - self.sldCorkSizeFactor.valueChanged.connect( - self.redacEditor.setCorkSizeFactor) - self.btnRedacFolderCork.toggled.connect( - self.sldCorkSizeFactor.setVisible) - self.btnRedacFolderText.clicked.connect( - lambda v: self.redacEditor.setFolderView("text")) - self.btnRedacFolderCork.clicked.connect( - lambda v: self.redacEditor.setFolderView("cork")) - self.btnRedacFolderOutline.clicked.connect( - lambda v: self.redacEditor.setFolderView("outline")) - #Debug self.mdlFlatData.setVerticalHeaderLabels(["Infos générales", "Summary"]) self.tblDebugFlatData.setModel(self.mdlFlatData) @@ -734,16 +742,17 @@ class MainWindow(QMainWindow, Ui_MainWindow): self.tblDebugPlots.selectionModel().currentChanged.connect( lambda: self.tblDebugPlotsPersos.setRootIndex(self.mdlPlots.index( self.tblDebugPlots.selectionModel().currentIndex().row(), - Plot.persos.value))) + Plot.persos.value)), AUC) self.tblDebugPlots.selectionModel().currentChanged.connect( lambda: self.tblDebugSubPlots.setRootIndex(self.mdlPlots.index( self.tblDebugPlots.selectionModel().currentIndex().row(), - Plot.subplots.value))) + Plot.subplots.value)), AUC) self.treeDebugOutline.setModel(self.mdlOutline) self.lstDebugLabels.setModel(self.mdlLabels) self.lstDebugStatus.setModel(self.mdlStatus) self.mdlPersos.setHorizontalHeaderLabels([i.name for i in Perso]) + ############################################################################### # GENERAL AKA UNSORTED ############################################################################### @@ -841,7 +850,7 @@ class MainWindow(QMainWindow, Ui_MainWindow): for widget, text, pos in references: label = helpLabel(text) - self.actShowHelp.toggled.connect(label.setVisible) + self.actShowHelp.toggled.connect(label.setVisible, AUC) widget.layout().insertWidget(pos, label) self.actShowHelp.setChecked(False) @@ -853,22 +862,22 @@ class MainWindow(QMainWindow, Ui_MainWindow): self.updateMenuDict() self.menuTools.addMenu(self.menuDict) - self.actSpellcheck.toggled.connect(self.toggleSpellcheck) - self.dictChanged.connect(self.redacEditor.setDict) - self.dictChanged.connect(self.redacMetadata.setDict) - self.dictChanged.connect(self.outlineItemEditor.setDict) + self.actSpellcheck.toggled.connect(self.toggleSpellcheck, AUC) + self.dictChanged.connect(self.redacEditor.setDict, AUC) + self.dictChanged.connect(self.redacMetadata.setDict, AUC) + self.dictChanged.connect(self.outlineItemEditor.setDict, AUC) else: # No Spell check support self.actSpellcheck.setVisible(False) a = QAction(self.tr("Install PyEnchant to use spellcheck"), self) a.setIcon(self.style().standardIcon(QStyle.SP_MessageBoxWarning)) - a.triggered.connect(self.openPyEnchantWebPage) + a.triggered.connect(self.openPyEnchantWebPage, AUC) self.menuTools.addAction(a) self.btnRedacFullscreen.clicked.connect( lambda: self.redacEditor.showFullscreen( - self.treeRedacOutline.currentIndex())) + self.treeRedacOutline.currentIndex()), AUC) ############################################################################### # SPELLCHECK @@ -883,7 +892,7 @@ class MainWindow(QMainWindow, Ui_MainWindow): for i in enchant.list_dicts(): a = QAction(str(i[0]), self) a.setCheckable(True) - a.triggered.connect(self.setDictionary) + a.triggered.connect(self.setDictionary, AUC) if settings.dict is None: settings.dict = enchant.get_default_language() if str(i[0]) == settings.dict: @@ -996,7 +1005,7 @@ class MainWindow(QMainWindow, Ui_MainWindow): a.setData("{},{},{}".format(mnud, sd, vd)) if settings.viewSettings[mnud][sd] == vd: a.setChecked(True) - a.triggered.connect(self.setViewSettingsAction) + a.triggered.connect(self.setViewSettingsAction, AUC) agp.addAction(a) m2.addAction(a) m.addMenu(m2) diff --git a/src/models/outlineModel.py b/src/models/outlineModel.py index 334bdf7..03fef8c 100644 --- a/src/models/outlineModel.py +++ b/src/models/outlineModel.py @@ -1,9 +1,6 @@ #!/usr/bin/env python #--!-- coding: utf8 --!-- - - - from qt import * from enums import * @@ -18,6 +15,7 @@ class outlineModel(QAbstractItemModel): QAbstractItemModel.__init__(self) self.rootItem = outlineItem(self, title="root") + self._defaultTextType = "t2t" def index(self, row, column, parent): @@ -345,16 +343,20 @@ class outlineModel(QAbstractItemModel): class outlineItem(): - def __init__(self, model=None, title="", type="folder", xml=None): + def __init__(self, model=None, title="", _type="folder", xml=None): self._data = {} self.childItems = [] self._parent = None self._model = model + self.defaultTextType = None - if title: self._data[Outline.title] = title - self._data[Outline.type] = type + if title: + self._data[Outline.title] = title + + self._data[Outline.type] = _type self._data[Outline.compile] = Qt.Checked + if xml is not None: self.setFromXML(xml) @@ -390,6 +392,10 @@ class outlineItem(): return QIcon.fromTheme("folder") elif self.isText(): return QIcon.fromTheme("text-x-generic") + elif self.isT2T(): + return QIcon.fromTheme("text-x-script") + elif self.isHTML(): + return QIcon.fromTheme("text-html") #elif role == Qt.ForegroundRole: #if self.isCompile() in [0, "0"]: @@ -420,15 +426,26 @@ class outlineItem(): if column == Outline.goal.value: self._data[Outline.setGoal] = toInt(data) if toInt(data) > 0 else "" + # Checking if we will have to recount words updateWordCount = False if column in [Outline.wordCount.value, Outline.goal.value, Outline.setGoal.value]: updateWordCount = not Outline(column) in self._data or self._data[Outline(column)] != data + # Setting data self._data[Outline(column)] = data + # Stuff to do afterwards if column == Outline.text.value: wc = wordCount(data) self.setData(Outline.wordCount.value, wc) + + if column == Outline.type.value: + oldType = self._data[Outline.type] + if oldType == "html" and data in ["txt", "t2t"]: + # Resource inneficient way to convert HTML to plain text + e = QTextEdit() + e.setHtml(self._data[Outline.text]) + self._data[Outline.text] = e.toPlainText() if updateWordCount: self.updateWordCount() @@ -508,9 +525,21 @@ class outlineItem(): def parent(self): return self._parent + def type(self): + return self._data[Outline.type] + def isFolder(self): return self._data[Outline.type] == "folder" + def isT2T(self): + return self._data[Outline.type] == "t2t" + + def isHTML(self): + return self._data[Outline.type] == "html" + + def isText(self): + return self._data[Outline.type] == "txt" + def isCompile(self): return Outline.compile in self._data and self._data[Outline.compile] @@ -526,9 +555,6 @@ class outlineItem(): else: return self.title() - def isText(self): - return self._data[Outline.type] == "text" - def level(self): if self.parent(): return self.parent().level() + 1 diff --git a/src/ui/editors/basicHighlighter.py b/src/ui/editors/basicHighlighter.py new file mode 100644 index 0000000..3f32ebc --- /dev/null +++ b/src/ui/editors/basicHighlighter.py @@ -0,0 +1,37 @@ +#!/usr/bin/python +# -*- coding: utf8 -*- + +from qt import * +import re + +class basicHighlighter(QSyntaxHighlighter): + + def __init__(self, editor): + QSyntaxHighlighter.__init__(self, editor.document()) + + self.editor = editor + + def setDefaultBlockFormat(self, bf): + self._defaultBlockFormat = bf + self.rehighlight() + + def setMisspelledColor(self, color): + self._misspelledColor = color + + def highlightBlock(self, text): + """Apply syntax highlighting to the given block of text. + """ + + QTextCursor(self.currentBlock()).setBlockFormat(self._defaultBlockFormat) + + # Spell checking + # Based on http://john.nachtimwald.com/2009/08/22/qplaintextedit-with-in-line-spell-check/ + WORDS = '(?iu)[\w\']+' + if self.editor.spellcheck: + for word_object in re.finditer(WORDS, text): + if self.editor._dict and not self.editor._dict.check(word_object.group()): + format = self.format(word_object.start()) + format.setUnderlineColor(self._misspelledColor) + format.setUnderlineStyle(QTextCharFormat.SpellCheckUnderline) + self.setFormat(word_object.start(), + word_object.end() - word_object.start(), format) diff --git a/src/ui/editors/editorWidget.py b/src/ui/editors/editorWidget.py index 4725f6a..85cc608 100644 --- a/src/ui/editors/editorWidget.py +++ b/src/ui/editors/editorWidget.py @@ -20,8 +20,9 @@ class editorWidget(QWidget, Ui_editorWidget_ui): self.currentIndex = QModelIndex() self.txtEdits = [] self.scroll.setBackgroundRole(QPalette.Base) - self.toggledSpellcheck.connect(self.txtRedacText.toggleSpellcheck) - self.dictChanged.connect(self.txtRedacText.setDict) + self.toggledSpellcheck.connect(self.txtRedacText.toggleSpellcheck, AUC) + self.dictChanged.connect(self.txtRedacText.setDict, AUC) + self.txtRedacText.setHighlighting(True) self.currentDict = "" self.spellcheck = True self.folderView = "cork" @@ -91,11 +92,16 @@ class editorWidget(QWidget, Ui_editorWidget_ui): l.addWidget(line) def addText(itm): - edt = textEditView(self, index=itm.index(), spellcheck=self.spellcheck, dict=self.currentDict, autoResize=True) + edt = textEditView(self, + index=itm.index(), + spellcheck=self.spellcheck, + dict=self.currentDict, + highlighting=True, + autoResize=True) edt.setFrameShape(QFrame.NoFrame) edt.setStatusTip(itm.path()) - self.toggledSpellcheck.connect(edt.toggleSpellcheck) - self.dictChanged.connect(edt.setDict) + self.toggledSpellcheck.connect(edt.toggleSpellcheck, AUC) + self.dictChanged.connect(edt.setDict, AUC) #edt.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred) self.txtEdits.append(edt) l.addWidget(edt) @@ -153,9 +159,9 @@ class editorWidget(QWidget, Ui_editorWidget_ui): self.corkView.setModel(self._model) self.corkView.setRootIndex(index) self.corkView.selectionModel().selectionChanged.connect( - lambda: mainWindow().redacMetadata.selectionChanged(self.corkView)) + lambda: mainWindow().redacMetadata.selectionChanged(self.corkView), AUC) self.corkView.clicked.connect( - lambda: mainWindow().redacMetadata.selectionChanged(self.corkView)) + lambda: mainWindow().redacMetadata.selectionChanged(self.corkView), AUC) elif item and item.isFolder() and self.folderView == "outline": @@ -166,15 +172,19 @@ class editorWidget(QWidget, Ui_editorWidget_ui): self.outlineView.setModel(self._model) self.outlineView.setRootIndex(index) self.outlineView.selectionModel().selectionChanged.connect( - lambda: mainWindow().redacMetadata.selectionChanged(self.outlineView)) + lambda: mainWindow().redacMetadata.selectionChanged(self.outlineView), AUC) self.outlineView.clicked.connect( - lambda: mainWindow().redacMetadata.selectionChanged(self.outlineView)) + lambda: mainWindow().redacMetadata.selectionChanged(self.outlineView), AUC) else: self.stack.setCurrentIndex(0) # Single text item - self._model.dataChanged.connect(self.modelDataChanged) + try: + self._model.dataChanged.connect(self.modelDataChanged, AUC) + except TypeError: + pass + self.updateStatusBar() diff --git a/src/ui/mainWindow.py b/src/ui/mainWindow.py index a9d61ad..0efa932 100644 --- a/src/ui/mainWindow.py +++ b/src/ui/mainWindow.py @@ -20,15 +20,15 @@ class Ui_MainWindow(object): self.horizontalLayout_12.setObjectName("horizontalLayout_12") self.stack = QtWidgets.QStackedWidget(self.centralwidget) self.stack.setObjectName("stack") - self.page_5 = QtWidgets.QWidget() - self.page_5.setObjectName("page_5") - self.gridLayout = QtWidgets.QGridLayout(self.page_5) + self.welcomePage = QtWidgets.QWidget() + self.welcomePage.setObjectName("welcomePage") + self.gridLayout = QtWidgets.QGridLayout(self.welcomePage) self.gridLayout.setObjectName("gridLayout") spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.gridLayout.addItem(spacerItem, 1, 0, 1, 1) spacerItem1 = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.gridLayout.addItem(spacerItem1, 1, 2, 1, 1) - self.welcome = welcome(self.page_5) + self.welcome = welcome(self.welcomePage) self.welcome.setMinimumSize(QtCore.QSize(200, 200)) self.welcome.setObjectName("welcome") self.gridLayout.addWidget(self.welcome, 1, 1, 1, 1) @@ -36,7 +36,7 @@ class Ui_MainWindow(object): self.gridLayout.addItem(spacerItem2, 0, 1, 1, 1) spacerItem3 = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding) self.gridLayout.addItem(spacerItem3, 2, 1, 1, 1) - self.stack.addWidget(self.page_5) + self.stack.addWidget(self.welcomePage) self.page_4 = QtWidgets.QWidget() self.page_4.setObjectName("page_4") self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.page_4) @@ -1107,7 +1107,7 @@ class Ui_MainWindow(object): self.retranslateUi(MainWindow) self.stack.setCurrentIndex(0) - self.tabMain.setCurrentIndex(3) + self.tabMain.setCurrentIndex(5) self.tabSummary.setCurrentIndex(0) self.tabPersos.setCurrentIndex(0) self.tabPlot.setCurrentIndex(1) @@ -1252,12 +1252,12 @@ class Ui_MainWindow(object): self.actCloseProject.setText(_translate("MainWindow", "Close project")) from ui.welcome import welcome -from ui.editors.editorWidget import editorWidget -from ui.views.outlineView import outlineView +from ui.views.basicItemView import basicItemView +from ui.views.plotTreeView import plotTreeView +from ui.views.metadataView import metadataView +from ui.views.treeView import treeView +from ui.sldImportance import sldImportance from ui.views.lineEditView import lineEditView from ui.views.textEditView import textEditView -from ui.views.basicItemView import basicItemView -from ui.sldImportance import sldImportance -from ui.views.metadataView import metadataView -from ui.views.plotTreeView import plotTreeView -from ui.views.treeView import treeView +from ui.views.outlineView import outlineView +from ui.editors.editorWidget import editorWidget diff --git a/src/ui/mainWindow.ui b/src/ui/mainWindow.ui index dc1f95f..45b56c9 100644 --- a/src/ui/mainWindow.ui +++ b/src/ui/mainWindow.ui @@ -32,7 +32,7 @@ 0 - + @@ -109,7 +109,7 @@ - 3 + 5 true diff --git a/src/ui/views/cmbOutlineTypeChoser.py b/src/ui/views/cmbOutlineTypeChoser.py new file mode 100644 index 0000000..1144d50 --- /dev/null +++ b/src/ui/views/cmbOutlineTypeChoser.py @@ -0,0 +1,144 @@ +#!/usr/bin/env python +#--!-- coding: utf8 --!-- + +from qt import * +from enums import * + + +class cmbOutlineTypeChoser(QComboBox): + + def __init__(self, parent=None): + QComboBox.__init__(self, parent) + self.activated[int].connect(self.submit) + self._column = Outline.type.value + self._index = None + self._indexes = None + self._updating = False + self._various = False + + def setModel(self, mdlOutline): + self.mdlOutline = mdlOutline + self.mdlOutline.dataChanged.connect(self.update) + self.updateItems() + + def updateItems(self): + self.clear() + types = [ + ("t2t", self.tr("Txt2Tags"), "text-x-generic"), + ("html", self.tr("Rich Text (html)"), "text-html"), + ("txt", self.tr("Plain Text"), "text-x-generic"), + ] + for t in types: + self.addItem(QIcon.fromTheme(t[2]), t[1], t[0]) + + self._various = False + + if self._index or self._indexes: + self.updateSelectedItem() + + def setCurrentModelIndex(self, index): + self._indexes = None + if index.column() != self._column: + index = index.sibling(index.row(), self._column) + self._index = index + # Disabled if item type is not text + self.setEnabled(index.internalPointer().type() in ["t2t", "html", "txt"]) + self.updateItems() + self.updateSelectedItem() + + def setCurrentModelIndexes(self, indexes): + self._indexes = [] + self._index = None + + hasText = False + for i in indexes: + if i.isValid(): + if i.column() != self._column: + i = i.sibling(i.row(), self._column) + self._indexes.append(i) + if i.internalPointer().type() in ["t2t", "html", "txt"]: + hasText = True + + self.setEnabled(hasText) + + self.updateItems() + self.updateSelectedItem() + + def update(self, topLeft, bottomRight): + + if self._updating: + # We are currently putting data in the model, so no updates + return + + if self._index: + if topLeft.row() <= self._index.row() <= bottomRight.row(): + self.updateSelectedItem() + + elif self._indexes: + update = False + for i in self._indexes: + if topLeft.row() <= i.row() <= bottomRight.row(): + update = True + if update: + self.updateSelectedItem() + + def getType(self, index): + item = index.internalPointer() + return item.type() + + def updateSelectedItem(self): + + if self._updating: + return + + if self._index: + _type = self.getType(self._index) + i = self.findData(_type) + if i != -1: + self.setCurrentIndex(i) + + elif self._indexes: + types = [] + same = True + + for i in self._indexes: + types.append(self.getType(i)) + + for t in types[1:]: + if t != types[0]: + same = False + break + + if same: + self._various = False + i = self.findData(types[0]) + if i != -1: + self.setCurrentIndex(i) + + else: + if not self._various: + self.insertItem(0, self.tr("Various")) + f = self.font() + f.setItalic(True) + self.setItemData(0, f, Qt.FontRole) + self.setItemData(0, QBrush(Qt.darkGray), Qt.ForegroundRole) + self._various = True + self.setCurrentIndex(0) + + else: + self.setCurrentIndex(0) + + def submit(self, idx): + if self._index: + self.mdlOutline.setData(self._index, self.currentData()) + + elif self._indexes: + value = self.currentData() + + if self._various and self.currentIndex() == 0: + return + + self._updating = True + for i in self._indexes: + self.mdlOutline.setData(i, value) + self._updating = False \ No newline at end of file diff --git a/src/ui/views/outlineBasics.py b/src/ui/views/outlineBasics.py index bc9e425..19b27ea 100644 --- a/src/ui/views/outlineBasics.py +++ b/src/ui/views/outlineBasics.py @@ -142,13 +142,17 @@ class outlineBasics(QAbstractItemView): def addText(self): self.addItem("text") - def addItem(self, type="folder"): + def addItem(self, _type="folder"): if len(self.selectedIndexes()) == 0: parent = self.rootIndex() else: parent = self.currentIndex() + + if _type == "text": + _type = self.model()._defaultTextType + print(_type) - item = outlineItem(title=qApp.translate("outlineBasics", "New"), type=type) + item = outlineItem(title=qApp.translate("outlineBasics", "New"), _type=_type) self.model().appendItem(item, parent) def copy(self): diff --git a/src/ui/views/propertiesView.py b/src/ui/views/propertiesView.py index 7aa583a..b458928 100644 --- a/src/ui/views/propertiesView.py +++ b/src/ui/views/propertiesView.py @@ -16,6 +16,7 @@ class propertiesView(QWidget, Ui_propertiesView): self.cmbPOV.setModels(mdlPersos, mdlOutline) self.cmbLabel.setModels(mdlLabels, mdlOutline) self.cmbStatus.setModels(mdlStatus, mdlOutline) + self.cmbType.setModel(mdlOutline) self.chkCompile.setModel(mdlOutline) self.txtTitle.setModel(mdlOutline) self.txtGoal.setModel(mdlOutline) @@ -51,6 +52,8 @@ class propertiesView(QWidget, Ui_propertiesView): self.txtTitle.setCurrentModelIndex(idx) self.txtGoal.setCurrentModelIndex(idx) + self.cmbType.setCurrentModelIndex(idx) + else: self.setEnabled(True) self.setLabelsItalic(True) @@ -61,6 +64,8 @@ class propertiesView(QWidget, Ui_propertiesView): self.cmbLabel.setCurrentModelIndexes(indexes) self.cmbStatus.setCurrentModelIndexes(indexes) + self.cmbType.setCurrentModelIndexes(indexes) + def setLabelsItalic(self, value): f = self.lblPOV.font() f.setItalic(value) diff --git a/src/ui/views/propertiesView_ui.py b/src/ui/views/propertiesView_ui.py index 9b75a93..c900e64 100644 --- a/src/ui/views/propertiesView_ui.py +++ b/src/ui/views/propertiesView_ui.py @@ -71,14 +71,14 @@ class Ui_propertiesView(object): self.formLayout.setWidget(2, QtWidgets.QFormLayout.FieldRole, self.cmbLabel) self.lblCompile = QtWidgets.QLabel(self.page) self.lblCompile.setObjectName("lblCompile") - self.formLayout.setWidget(3, QtWidgets.QFormLayout.LabelRole, self.lblCompile) + self.formLayout.setWidget(5, QtWidgets.QFormLayout.LabelRole, self.lblCompile) self.chkCompile = chkOutlineCompile(self.page) self.chkCompile.setText("") self.chkCompile.setObjectName("chkCompile") - self.formLayout.setWidget(3, QtWidgets.QFormLayout.FieldRole, self.chkCompile) + self.formLayout.setWidget(5, QtWidgets.QFormLayout.FieldRole, self.chkCompile) self.lblGoal = QtWidgets.QLabel(self.page) self.lblGoal.setObjectName("lblGoal") - self.formLayout.setWidget(4, QtWidgets.QFormLayout.LabelRole, self.lblGoal) + self.formLayout.setWidget(6, QtWidgets.QFormLayout.LabelRole, self.lblGoal) self.txtGoal = lineEditView(self.page) sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed) sizePolicy.setHorizontalStretch(0) @@ -89,7 +89,19 @@ class Ui_propertiesView(object): self.txtGoal.setStyleSheet("border-radius: 6px;") self.txtGoal.setFrame(False) self.txtGoal.setObjectName("txtGoal") - self.formLayout.setWidget(4, QtWidgets.QFormLayout.FieldRole, self.txtGoal) + self.formLayout.setWidget(6, QtWidgets.QFormLayout.FieldRole, self.txtGoal) + self.lblLabel_2 = QtWidgets.QLabel(self.page) + self.lblLabel_2.setObjectName("lblLabel_2") + self.formLayout.setWidget(3, QtWidgets.QFormLayout.LabelRole, self.lblLabel_2) + self.cmbType = cmbOutlineTypeChoser(self.page) + sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed) + sizePolicy.setHorizontalStretch(0) + sizePolicy.setVerticalStretch(0) + sizePolicy.setHeightForWidth(self.cmbType.sizePolicy().hasHeightForWidth()) + self.cmbType.setSizePolicy(sizePolicy) + self.cmbType.setFrame(False) + self.cmbType.setObjectName("cmbType") + self.formLayout.setWidget(3, QtWidgets.QFormLayout.FieldRole, self.cmbType) self.verticalLayout_2.addLayout(self.formLayout) self.stack.addWidget(self.page) self.page_2 = QtWidgets.QWidget() @@ -174,6 +186,7 @@ class Ui_propertiesView(object): self.lblCompile.setText(_translate("propertiesView", "Compile")) self.lblGoal.setText(_translate("propertiesView", "Goal")) self.txtGoal.setPlaceholderText(_translate("propertiesView", "Word count")) + self.lblLabel_2.setText(_translate("propertiesView", "Text type:")) self.lblPOV_2.setText(_translate("propertiesView", "POV")) self.label_31.setText(_translate("propertiesView", "Status")) self.label_34.setText(_translate("propertiesView", "Label")) @@ -181,8 +194,9 @@ class Ui_propertiesView(object): self.label_36.setText(_translate("propertiesView", "Goal")) self.txtGoalMulti.setPlaceholderText(_translate("propertiesView", "Word count")) +from ui.views.lineEditView import lineEditView +from ui.views.chkOutlineCompile import chkOutlineCompile +from ui.views.cmbOutlineTypeChoser import cmbOutlineTypeChoser from ui.views.cmbOutlineLabelChoser import cmbOutlineLabelChoser from ui.views.cmbOutlinePersoChoser import cmbOutlinePersoChoser -from ui.views.lineEditView import lineEditView from ui.views.cmbOutlineStatusChoser import cmbOutlineStatusChoser -from ui.views.chkOutlineCompile import chkOutlineCompile diff --git a/src/ui/views/propertiesView_ui.ui b/src/ui/views/propertiesView_ui.ui index 8c638a5..e1ee32a 100644 --- a/src/ui/views/propertiesView_ui.ui +++ b/src/ui/views/propertiesView_ui.ui @@ -105,28 +105,28 @@ - + Compile - + - + Goal - + @@ -148,6 +148,26 @@ + + + + Text type: + + + + + + + + 0 + 0 + + + + false + + + @@ -274,6 +294,11 @@ + + lineEditView + QLineEdit +
ui.views.lineEditView.h
+
cmbOutlinePersoChoser QComboBox @@ -295,9 +320,9 @@
ui.views.cmbOutlineLabelChoser.h
- lineEditView - QLineEdit -
ui.views.lineEditView.h
+ cmbOutlineTypeChoser + QComboBox +
ui.views.cmbOutlineTypeChoser.h
diff --git a/src/ui/views/textEditView.py b/src/ui/views/textEditView.py index d9bee1f..27a28cb 100644 --- a/src/ui/views/textEditView.py +++ b/src/ui/views/textEditView.py @@ -4,6 +4,8 @@ from qt import * from enums import * from ui.editors.t2tHighlighter import * +from ui.editors.basicHighlighter import * +from models.outlineModel import * from functions import * try: @@ -13,7 +15,7 @@ except ImportError: class textEditView(QTextEdit): - def __init__(self, parent=None, index=None, html=None, spellcheck=True, dict="", autoResize=False): + def __init__(self, parent=None, index=None, html=None, spellcheck=True, highlighting=False, dict="", autoResize=False): QTextEdit.__init__(self, parent) self._column = Outline.text.value @@ -22,7 +24,8 @@ class textEditView(QTextEdit): self._placeholderText = None self._updating = False self._item = None - self._highlighting = True + self._highlighting = highlighting + self.setAcceptRichText(False) self.spellcheck = spellcheck self.currentDict = dict @@ -33,6 +36,7 @@ class textEditView(QTextEdit): self.highligtCS = False self.defaultFontPointSize = qApp.font().pointSize() self._dict = None + self.document().contentsChanged.connect(self.submit, AUC) if index: self.setCurrentModelIndex(index) @@ -55,7 +59,7 @@ class textEditView(QTextEdit): def setModel(self, model): self._model = model - self._model.dataChanged.connect(self.update) + self._model.dataChanged.connect(self.update, AUC) def setColumn(self, col): self._column = col @@ -74,27 +78,46 @@ class textEditView(QTextEdit): if index.column() != self._column: index = index.sibling(index.row(), self._column) self._index = index - self._item = index.internalPointer() if self._placeholderText != None: self.setPlaceholderText(self._placeholderText) self._model = index.model() - self.document().contentsChanged.connect(self.submit) - self._model.dataChanged.connect(self.update) + try: + self._model.dataChanged.connect(self.update, AUC) + except TypeError: + pass + + #self.document().contentsChanged.connect(self.submit, AUC) self.updateText() - if self._highlighting and not self.highlighter: - self.highlighter = t2tHighlighter(self) - self.highlighter.setDefaultBlockFormat(self._defaultBlockFormat) + self.setupEditorForIndex(self._index) + else: self._index = QModelIndex() try: self.document().contentsChanged.disconnect(self.submit) - self._model.dataChanged.disconnect(self.update) + #self._model.dataChanged.disconnect(self.update) except: pass self.setPlainText("") + def setupEditorForIndex(self, index): + # Setting highlighter + if self._highlighting: + item = index.internalPointer() + if self._column == Outline.text.value and not item.isT2T(): + self.highlighter = basicHighlighter(self) + else: + self.highlighter = t2tHighlighter(self) + + self.highlighter.setDefaultBlockFormat(self._defaultBlockFormat) + + # Accept richtext maybe + if self.indexIsHtml(index): + self.setAcceptRichText(True) + else: + self.setAcceptRichText(False) + def setCurrentModelIndexes(self, indexes): self._index = None self._indexes = [] @@ -105,7 +128,7 @@ class textEditView(QTextEdit): i = i.sibling(i.row(), self._column) self._indexes.append(i) - self.document().contentsChanged.connect(self.submit) + #self.document().contentsChanged.connect(self.submit) self.updateText() def update(self, topLeft, bottomRight): @@ -114,6 +137,12 @@ class textEditView(QTextEdit): elif self._index: if topLeft.row() <= self._index.row() <= bottomRight.row(): + + if topLeft.column() <= Outline.type.value <= bottomRight.column(): + # If item type change, we reset the index to set the proper + # highlighter and other defaults + self.setupEditorForIndex(self._index) + self.updateText() elif self._indexes: @@ -125,10 +154,18 @@ class textEditView(QTextEdit): self.updateText() def updateText(self): + + if self._updating: + return + self._updating = True if self._index: - if self.toPlainText() != toString(self._model.data(self._index)): - self.document().setPlainText(toString(self._model.data(self._index))) + if self.indexIsHtml(self._index): + if self.toHtml() != toString(self._model.data(self._index)): + self.document().setHtml(toString(self._model.data(self._index))) + else: + if self.toPlainText() != toString(self._model.data(self._index)): + self.document().setPlainText(toString(self._model.data(self._index))) elif self._indexes: t = [] @@ -143,6 +180,7 @@ class textEditView(QTextEdit): break if same: + # Assuming that we don't use HTML with multiple items self.document().setPlainText(t[0]) else: self.document().setPlainText("") @@ -159,11 +197,17 @@ class textEditView(QTextEdit): return if self._index: - #item = self._index.internalPointer() - if self.toPlainText() != self._model.data(self._index): - self._updating = True - self._model.setData(self._index, self.toPlainText()) - self._updating = False + item = self._index.internalPointer() + if self.indexIsHtml(self._index): + if self.toHtml() != self._model.data(self._index): + self._updating = True + self._model.setData(self._index, self.toHtml()) + self._updating = False + else: + if self.toPlainText() != self._model.data(self._index): + self._updating = True + self._model.setData(self._index, self.toPlainText()) + self._updating = False elif self._indexes: self._updating = True @@ -173,6 +217,19 @@ class textEditView(QTextEdit): self._model.setData(i, self.toPlainText()) self._updating = False + def indexIsHtml(self, index): + if not index.isValid(): + return False + + if type(index.model()) != outlineModel: + return False + + item = index.internalPointer() + if item.isHTML(): + return True + else: + return False + # ----------------------------------------------------------------------------------------------------- # Resize stuff diff --git a/src/ui/welcome.py b/src/ui/welcome.py index 0e33401..7f9f3d1 100644 --- a/src/ui/welcome.py +++ b/src/ui/welcome.py @@ -174,6 +174,13 @@ class welcome(QWidget, Ui_welcome): (1000, None) ]) ] + + def defaultTextType(self): + return [ + ("t2t", self.tr("Txt2Tags"), "text-x-generic"), + ("html", self.tr("Rich Text (html)"), "text-html"), + ("txt", self.tr("Plain Text"), "text-x-generic"), + ] def changeTemplate(self, item, column): template = [i for i in self.templates() if i[0] == item.text(0)] @@ -293,8 +300,13 @@ class welcome(QWidget, Ui_welcome): item = self.addTopLevelItem(self.tr("Demo projects")) # FIXME: none yet + # Populates default text type + self.cmbDefaultType.clear() + for t in self.defaultTextType(): + self.cmbDefaultType.addItem(QIcon.fromTheme(t[2]), t[1], t[0]) + self.tree.expandAll() - + def loadDefaultDatas(self): # Données self.mw.mdlFlatData = QStandardItemModel(2, 8) @@ -337,8 +349,9 @@ class welcome(QWidget, Ui_welcome): # Outline self.mw.mdlOutline = outlineModel() - root = self.mw.mdlOutline.rootItem + _type = self.cmbDefaultType.currentData() + self.mw.mdlOutline._defaultTextType = _type def addElement(parent, datas): if len(datas) == 2 and datas[1][1] == None or \ @@ -350,7 +363,7 @@ class welcome(QWidget, Ui_welcome): item = outlineItem(title="{} {}".format( datas[0][1], str(n)), - type="text") + _type=_type) if len(datas) == 2: item.setData(Outline.setGoal.value, datas[1][0]) parent.appendChild(item) @@ -361,7 +374,7 @@ class welcome(QWidget, Ui_welcome): item = outlineItem(title="{} {}".format( datas[0][1], str(n)), - type="folder") + _type="folder") parent.appendChild(item) addElement(item, datas[1:]) diff --git a/src/ui/welcome_ui.py b/src/ui/welcome_ui.py index 1cc31cc..0929669 100644 --- a/src/ui/welcome_ui.py +++ b/src/ui/welcome_ui.py @@ -78,6 +78,15 @@ class Ui_welcome(object): self.btnAddWC.setObjectName("btnAddWC") self.horizontalLayout_2.addWidget(self.btnAddWC) self.templateLayout.addLayout(self.horizontalLayout_2) + self.horizontalLayout_3 = QtWidgets.QHBoxLayout() + self.horizontalLayout_3.setObjectName("horizontalLayout_3") + self.lblTotal_2 = QtWidgets.QLabel(self.frame_2) + self.lblTotal_2.setObjectName("lblTotal_2") + self.horizontalLayout_3.addWidget(self.lblTotal_2) + self.cmbDefaultType = QtWidgets.QComboBox(self.frame_2) + self.cmbDefaultType.setObjectName("cmbDefaultType") + self.horizontalLayout_3.addWidget(self.cmbDefaultType) + self.templateLayout.addLayout(self.horizontalLayout_3) self.horizontalLayout_23.addLayout(self.templateLayout) self.verticalLayout_32.addLayout(self.horizontalLayout_23) self.line_4 = QtWidgets.QFrame(self.frame_2) @@ -124,6 +133,7 @@ class Ui_welcome(object): self.tree.setSortingEnabled(__sortingEnabled) self.btnAddLevel.setText(_translate("welcome", "Add level")) self.btnAddWC.setText(_translate("welcome", "Add wordcount")) + self.lblTotal_2.setText(_translate("welcome", "Default text type:")) self.chkLoadLastProject.setText(_translate("welcome", "Next time, automatically open last project")) self.btnOpen.setText(_translate("welcome", "Open...")) self.btnRecent.setText(_translate("welcome", "Recent")) diff --git a/src/ui/welcome_ui.ui b/src/ui/welcome_ui.ui index cf7129f..0a5cf2e 100644 --- a/src/ui/welcome_ui.ui +++ b/src/ui/welcome_ui.ui @@ -190,6 +190,20 @@ + + + + + + Default text type: + + + + + + + +