From e393848bc0f10b067ce5c47dd8526fd8779295aa Mon Sep 17 00:00:00 2001 From: Olivier Keshavjee Date: Sun, 29 Oct 2017 10:21:28 +0100 Subject: [PATCH] App crash when moving a step in Plots section #134 --- manuskript/mainWindow.py | 27 ++++++++++--- manuskript/models/plotModel.py | 61 ++++++++++++++++++++++------- manuskript/ui/mainWindow.py | 42 +++++++++++++------- manuskript/ui/mainWindow.ui | 41 +++++++++++++++---- manuskript/ui/views/plotTreeView.py | 10 ++++- 5 files changed, 137 insertions(+), 44 deletions(-) diff --git a/manuskript/mainWindow.py b/manuskript/mainWindow.py index ade25242..b47892e5 100644 --- a/manuskript/mainWindow.py +++ b/manuskript/mainWindow.py @@ -297,10 +297,23 @@ class MainWindow(QMainWindow, Ui_MainWindow): def updateSubPlotView(self): # Hide columns - for i in range(self.mdlPlots.columnCount()): - self.lstSubPlots.hideColumn(i) - self.lstSubPlots.showColumn(PlotStep.name.value) - self.lstSubPlots.showColumn(PlotStep.meta.value) + # FIXME: when columns are hidden, and drag and drop InternalMove is enabled + # as well as selectionBehavior=SelectRows, then when moving a row + # hidden cells (here: summary and ID) are deleted... + # So instead we set their width to 0. + #for i in range(self.mdlPlots.columnCount()): + #self.lstSubPlots.hideColumn(i) + #self.lstSubPlots.showColumn(PlotStep.name.value) + #self.lstSubPlots.showColumn(PlotStep.meta.value) + + self.lstSubPlots.horizontalHeader().setSectionResizeMode( + PlotStep.ID.value, QHeaderView.Fixed) + self.lstSubPlots.horizontalHeader().setSectionResizeMode( + PlotStep.summary.value, QHeaderView.Fixed) + self.lstSubPlots.horizontalHeader().resizeSection( + PlotStep.ID.value, 0) + self.lstSubPlots.horizontalHeader().resizeSection( + PlotStep.summary.value, 0) self.lstSubPlots.horizontalHeader().setSectionResizeMode( PlotStep.name.value, QHeaderView.Stretch) @@ -715,9 +728,9 @@ class MainWindow(QMainWindow, Ui_MainWindow): self.tabPersos.setEnabled(False) # Plots - self.lstPlots.setPlotModel(self.mdlPlots) - self.lstPlotPerso.setModel(self.mdlPlots) self.lstSubPlots.setModel(self.mdlPlots) + self.lstPlotPerso.setModel(self.mdlPlots) + self.lstPlots.setPlotModel(self.mdlPlots) self._updatingSubPlot = False self.btnAddPlot.clicked.connect(self.mdlPlots.addPlot, AUC) self.btnRmPlot.clicked.connect(lambda: @@ -727,6 +740,7 @@ class MainWindow(QMainWindow, Ui_MainWindow): self.btnRmSubPlot.clicked.connect(self.mdlPlots.removeSubPlot, AUC) self.lstPlotPerso.selectionModel().selectionChanged.connect(self.plotPersoSelectionChanged) self.btnRmPlotPerso.clicked.connect(self.mdlPlots.removePlotPerso, AUC) + self.lstSubPlots.selectionModel().currentRowChanged.connect(self.changeCurrentSubPlot, AUC) for w, c in [ (self.txtPlotName, Plot.name.value), @@ -857,6 +871,7 @@ class MainWindow(QMainWindow, Ui_MainWindow): self.disconnectAll(self.btnAddSubPlot.clicked, self.updateSubPlotView) self.disconnectAll(self.btnRmSubPlot.clicked, self.mdlPlots.removeSubPlot) self.disconnectAll(self.lstPlotPerso.selectionModel().selectionChanged, self.plotPersoSelectionChanged) + self.disconnectAll(self.lstSubPlots.selectionModel().currentRowChanged, self.changeCurrentSubPlot) self.disconnectAll(self.btnRmPlotPerso.clicked, self.mdlPlots.removePlotPerso) self.disconnectAll(self.mdlCharacter.dataChanged, self.mdlPlots.updatePlotPersoButton) diff --git a/manuskript/models/plotModel.py b/manuskript/models/plotModel.py index 2130e439..0dfbefe2 100644 --- a/manuskript/models/plotModel.py +++ b/manuskript/models/plotModel.py @@ -41,10 +41,23 @@ class plotModel(QStandardItemModel): item = self.itemFromIndex(index) lst = [] for i in range(item.rowCount()): - _ID = item.child(i, Plot.ID.value).text() - name = item.child(i, Plot.name.value).text() - summary = item.child(i, 3).text() - lst.append((_ID, name, summary)) + if item.child(i, PlotStep.ID.value): + _ID = item.child(i, PlotStep.ID.value).text() + + # Don't know why sometimes name is None (while drag'n'droping + # several items) + if item.child(i, PlotStep.name.value): + name = item.child(i, PlotStep.name.value).text() + else: + name = "" + + # Don't know why sometimes summary is None + if item.child(i, PlotStep.summary.value): + summary = item.child(i, PlotStep.summary.value).text() + else: + summary = "" + + lst.append((_ID, name, summary)) return lst def getPlotNameByID(self, ID): @@ -68,8 +81,8 @@ class plotModel(QStandardItemModel): is ``subplotRaw``, of plot whose ID is ``plotID``. """ plotIndex = self.getIndexFromID(plotID) - name = plotIndex.child(subplotRaw, Plot.name.value).data() - summary = plotIndex.child(subplotRaw, 3).data() # 3 is for summary + name = plotIndex.child(subplotRaw, PlotStep.name.value).data() + summary = plotIndex.child(subplotRaw, PlotStep.summary.value).data() return name, summary def getIndexFromID(self, ID): @@ -162,19 +175,32 @@ class plotModel(QStandardItemModel): _id = QStandardItem(self.getUniqueID(parent)) summary = QStandardItem() - # Don't know why, if summary is in third position, then drag/drop deletes it... - parentItem.appendRow([p, _id, QStandardItem(), summary]) - - # Select last index - self.mw.lstSubPlots.setCurrentIndex(parent.child(self.rowCount(parent) - 1, 0)) + currentIndex = self.mw.lstSubPlots.selectionModel().selectedIndexes() + if currentIndex: + # We use last item of selection in case of many + currentIndex = currentIndex[-1] + row = currentIndex.row() + 1 + parentItem.insertRow(row, [p, _id, QStandardItem(), summary]) + # Select last index + self.mw.lstSubPlots.setCurrentIndex(currentIndex.sibling(row, 0)) + else: + # Don't know why, if summary is in third position, then drag/drop deletes it... + parentItem.appendRow([p, _id, QStandardItem(), summary]) + # Select last index + self.mw.lstSubPlots.setCurrentIndex(parent.child(self.rowCount(parent) - 1, 0)) def removeSubPlot(self): - index = self.mw.lstSubPlots.currentIndex() - if not index.isValid(): + """ + Remove all selected subplots / plot steps, in mw.lstSubPlots. + """ + parent = self.mw.lstSubPlots.rootIndex() + if not parent.isValid(): return - parent = index.parent() parentItem = self.itemFromIndex(parent) - parentItem.takeRow(index.row()) + + while self.mw.lstSubPlots.selectionModel().selectedRows(): + i = self.mw.lstSubPlots.selectionModel().selectedRows()[0] + parentItem.takeRow(i.row()) def flags(self, index): parent = index.parent() @@ -230,5 +256,10 @@ class plotModel(QStandardItemModel): menus[2 - imp].addAction(a) + # Disabling empty menus + for m in menus: + if not m.actions(): + m.setEnabled(False) + mpr.mapped.connect(self.addPlotPerso) self.mw.btnAddPlotPerso.setMenu(menu) diff --git a/manuskript/ui/mainWindow.py b/manuskript/ui/mainWindow.py index a2a9a74e..73237964 100644 --- a/manuskript/ui/mainWindow.py +++ b/manuskript/ui/mainWindow.py @@ -2,8 +2,7 @@ # Form implementation generated from reading ui file 'manuskript/ui/mainWindow.ui' # -# Created: Sun Oct 15 22:19:14 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! @@ -17,14 +16,15 @@ class Ui_MainWindow(object): self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.centralwidget) - self.horizontalLayout_2.setSpacing(0) self.horizontalLayout_2.setContentsMargins(0, 1, 0, 0) + self.horizontalLayout_2.setSpacing(0) self.horizontalLayout_2.setObjectName("horizontalLayout_2") self.stack = QtWidgets.QStackedWidget(self.centralwidget) self.stack.setObjectName("stack") self.welcomePage = QtWidgets.QWidget() self.welcomePage.setObjectName("welcomePage") self.gridLayout = QtWidgets.QGridLayout(self.welcomePage) + self.gridLayout.setContentsMargins(0, 0, 0, 0) self.gridLayout.setObjectName("gridLayout") spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) self.gridLayout.addItem(spacerItem, 1, 0, 1, 1) @@ -161,6 +161,7 @@ class Ui_MainWindow(object): self.tabSummaryPage1 = QtWidgets.QWidget() self.tabSummaryPage1.setObjectName("tabSummaryPage1") self.verticalLayout_5 = QtWidgets.QVBoxLayout(self.tabSummaryPage1) + self.verticalLayout_5.setContentsMargins(0, 0, 0, 0) self.verticalLayout_5.setObjectName("verticalLayout_5") self.label = QtWidgets.QLabel(self.tabSummaryPage1) self.label.setObjectName("label") @@ -183,6 +184,7 @@ class Ui_MainWindow(object): self.tabSummaryPage2 = QtWidgets.QWidget() self.tabSummaryPage2.setObjectName("tabSummaryPage2") self.horizontalLayout_4 = QtWidgets.QHBoxLayout(self.tabSummaryPage2) + self.horizontalLayout_4.setContentsMargins(0, 0, 0, 0) self.horizontalLayout_4.setObjectName("horizontalLayout_4") self.verticalLayout = QtWidgets.QVBoxLayout() self.verticalLayout.setObjectName("verticalLayout") @@ -225,6 +227,7 @@ class Ui_MainWindow(object): self.tabSummaryPage3 = QtWidgets.QWidget() self.tabSummaryPage3.setObjectName("tabSummaryPage3") self.horizontalLayout_7 = QtWidgets.QHBoxLayout(self.tabSummaryPage3) + self.horizontalLayout_7.setContentsMargins(0, 0, 0, 0) self.horizontalLayout_7.setObjectName("horizontalLayout_7") self.verticalLayout_6 = QtWidgets.QVBoxLayout() self.verticalLayout_6.setObjectName("verticalLayout_6") @@ -260,6 +263,7 @@ class Ui_MainWindow(object): self.tabSummaryPage4 = QtWidgets.QWidget() self.tabSummaryPage4.setObjectName("tabSummaryPage4") self.horizontalLayout_8 = QtWidgets.QHBoxLayout(self.tabSummaryPage4) + self.horizontalLayout_8.setContentsMargins(0, 0, 0, 0) self.horizontalLayout_8.setObjectName("horizontalLayout_8") self.verticalLayout_7 = QtWidgets.QVBoxLayout() self.verticalLayout_7.setObjectName("verticalLayout_7") @@ -369,8 +373,8 @@ class Ui_MainWindow(object): self.info = QtWidgets.QWidget() self.info.setObjectName("info") self.verticalLayout_20 = QtWidgets.QVBoxLayout(self.info) - self.verticalLayout_20.setSpacing(0) self.verticalLayout_20.setContentsMargins(0, 0, 0, 0) + self.verticalLayout_20.setSpacing(0) self.verticalLayout_20.setObjectName("verticalLayout_20") self.scrollAreaPersoInfos = QtWidgets.QScrollArea(self.info) self.scrollAreaPersoInfos.setFrameShape(QtWidgets.QFrame.NoFrame) @@ -383,6 +387,7 @@ class Ui_MainWindow(object): self.scrollAreaPersoInfosWidget.setObjectName("scrollAreaPersoInfosWidget") self.formLayout_8 = QtWidgets.QFormLayout(self.scrollAreaPersoInfosWidget) self.formLayout_8.setFieldGrowthPolicy(QtWidgets.QFormLayout.AllNonFixedFieldsGrow) + self.formLayout_8.setContentsMargins(0, 0, 0, 0) self.formLayout_8.setObjectName("formLayout_8") self.label_4 = QtWidgets.QLabel(self.scrollAreaPersoInfosWidget) self.label_4.setObjectName("label_4") @@ -639,6 +644,7 @@ class Ui_MainWindow(object): self.verticalLayout_28 = QtWidgets.QVBoxLayout(self.tab_15) self.verticalLayout_28.setObjectName("verticalLayout_28") self.lstSubPlots = QtWidgets.QTableView(self.tab_15) + self.lstSubPlots.setDragDropOverwriteMode(False) self.lstSubPlots.setDragDropMode(QtWidgets.QAbstractItemView.InternalMove) self.lstSubPlots.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows) self.lstSubPlots.setShowGrid(False) @@ -697,6 +703,7 @@ class Ui_MainWindow(object): self.page = QtWidgets.QWidget() self.page.setObjectName("page") self.horizontalLayout_6 = QtWidgets.QHBoxLayout(self.page) + self.horizontalLayout_6.setContentsMargins(0, 0, 0, 0) self.horizontalLayout_6.setObjectName("horizontalLayout_6") self.txtPlotSummaryPara = textEditView(self.page) self.txtPlotSummaryPara.setObjectName("txtPlotSummaryPara") @@ -705,6 +712,7 @@ class Ui_MainWindow(object): self.page_2 = QtWidgets.QWidget() self.page_2.setObjectName("page_2") self.horizontalLayout_10 = QtWidgets.QHBoxLayout(self.page_2) + self.horizontalLayout_10.setContentsMargins(0, 0, 0, 0) self.horizontalLayout_10.setObjectName("horizontalLayout_10") self.txtPlotSummaryPage = textEditView(self.page_2) self.txtPlotSummaryPage.setObjectName("txtPlotSummaryPage") @@ -713,6 +721,7 @@ class Ui_MainWindow(object): self.page_3 = QtWidgets.QWidget() self.page_3.setObjectName("page_3") self.horizontalLayout_13 = QtWidgets.QHBoxLayout(self.page_3) + self.horizontalLayout_13.setContentsMargins(0, 0, 0, 0) self.horizontalLayout_13.setObjectName("horizontalLayout_13") self.txtPlotSummaryFull = textEditView(self.page_3) self.txtPlotSummaryFull.setObjectName("txtPlotSummaryFull") @@ -987,6 +996,7 @@ class Ui_MainWindow(object): self.tblDebugPlotsPersos.setObjectName("tblDebugPlotsPersos") self.verticalLayout_22.addWidget(self.tblDebugPlotsPersos) self.tblDebugSubPlots = QtWidgets.QTableView(self.tab_2) + self.tblDebugSubPlots.setDragDropMode(QtWidgets.QAbstractItemView.InternalMove) self.tblDebugSubPlots.setObjectName("tblDebugSubPlots") self.verticalLayout_22.addWidget(self.tblDebugSubPlots) self.horizontalLayout_11.addLayout(self.verticalLayout_22) @@ -1208,14 +1218,14 @@ class Ui_MainWindow(object): self.retranslateUi(MainWindow) self.stack.setCurrentIndex(1) - self.tabMain.setCurrentIndex(6) + self.tabMain.setCurrentIndex(3) self.tabSummary.setCurrentIndex(0) self.tabPersos.setCurrentIndex(0) self.tabPlot.setCurrentIndex(0) self.comboBox_2.setCurrentIndex(0) self.stkPlotSummary.setCurrentIndex(0) self.tabWorld.setCurrentIndex(0) - self.tabWidget.setCurrentIndex(3) + self.tabWidget.setCurrentIndex(2) self.comboBox_2.currentIndexChanged['int'].connect(self.stkPlotSummary.setCurrentIndex) self.btnPlanShowDetails.toggled['bool'].connect(self.frame.setVisible) self.cmbSummary.currentIndexChanged['int'].connect(self.tabSummary.setCurrentIndex) @@ -1283,6 +1293,10 @@ class Ui_MainWindow(object): self.label_28.setText(_translate("MainWindow", "Result")) self.tabPlot.setTabText(self.tabPlot.indexOf(self.infos_2), _translate("MainWindow", "Basic info")) self.grpSubPlotSummary.setTitle(_translate("MainWindow", "Summary:")) + self.btnAddSubPlot.setToolTip(_translate("MainWindow", "Add plot step (CTRL+Enter)")) + self.btnAddSubPlot.setShortcut(_translate("MainWindow", "Ctrl+Return")) + self.btnRmSubPlot.setToolTip(_translate("MainWindow", "Remove selected plot step(s) (CTRL+Backspace)")) + self.btnRmSubPlot.setShortcut(_translate("MainWindow", "Ctrl+Backspace")) self.tabPlot.setTabText(self.tabPlot.indexOf(self.tab_15), _translate("MainWindow", "Resolution steps")) self.grpPlotSummary.setTitle(_translate("MainWindow", "Summary")) self.comboBox_2.setItemText(0, _translate("MainWindow", "One paragraph")) @@ -1347,18 +1361,18 @@ class Ui_MainWindow(object): self.actAbout.setText(_translate("MainWindow", "&About")) self.actAbout.setToolTip(_translate("MainWindow", "About Manuskript")) -from manuskript.ui.views.textEditView import textEditView from manuskript.ui.cheatSheet import cheatSheet from manuskript.ui.editors.mainEditor import mainEditor -from manuskript.ui.welcome import welcome -from manuskript.ui.views.characterTreeView import characterTreeView -from manuskript.ui.views.basicItemView import basicItemView -from manuskript.ui.views.storylineView import storylineView -from manuskript.ui.views.treeView import treeView from manuskript.ui.search import search -from manuskript.ui.views.plotTreeView import plotTreeView +from manuskript.ui.views.basicItemView import basicItemView +from manuskript.ui.views.characterTreeView import characterTreeView +from manuskript.ui.views.lineEditView import lineEditView from manuskript.ui.views.metadataView import metadataView from manuskript.ui.views.outlineView import outlineView -from manuskript.ui.views.lineEditView import lineEditView +from manuskript.ui.views.plotTreeView import plotTreeView from manuskript.ui.views.sldImportance import sldImportance +from manuskript.ui.views.storylineView import storylineView from manuskript.ui.views.textEditCompleter import textEditCompleter +from manuskript.ui.views.textEditView import textEditView +from manuskript.ui.views.treeView import treeView +from manuskript.ui.welcome import welcome diff --git a/manuskript/ui/mainWindow.ui b/manuskript/ui/mainWindow.ui index 000cf691..05063d73 100644 --- a/manuskript/ui/mainWindow.ui +++ b/manuskript/ui/mainWindow.ui @@ -124,7 +124,7 @@ QTabWidget::Rounded - 6 + 3 true @@ -1317,6 +1317,9 @@ + + false + QAbstractItemView::InternalMove @@ -1344,6 +1347,9 @@ + + Add plot step (CTRL+Enter) + @@ -1351,6 +1357,9 @@ ../../../../../../../.designer/backup../../../../../../../.designer/backup + + Ctrl+Return + true @@ -1358,6 +1367,9 @@ + + Remove selected plot step(s) (CTRL+Backspace) + @@ -1365,6 +1377,9 @@ ../../../../../../../.designer/backup../../../../../../../.designer/backup + + Ctrl+Backspace + true @@ -1974,7 +1989,7 @@ QTabWidget::West - 3 + 2 @@ -2013,7 +2028,11 @@ - + + + QAbstractItemView::InternalMove + + @@ -2350,7 +2369,9 @@ QListView::item:hover { - + + + &Labels... @@ -2358,7 +2379,9 @@ QListView::item:hover { - + + + &Status... @@ -2430,7 +2453,9 @@ QListView::item:hover { - + + + Co&mpile @@ -2446,7 +2471,9 @@ QListView::item:hover { - + + + &About diff --git a/manuskript/ui/views/plotTreeView.py b/manuskript/ui/views/plotTreeView.py index 79ab9fa4..31d4cfe0 100644 --- a/manuskript/ui/views/plotTreeView.py +++ b/manuskript/ui/views/plotTreeView.py @@ -6,7 +6,7 @@ from PyQt5.QtWidgets import QTreeWidget, QTreeWidgetItem from lxml import etree as ET from manuskript import settings -from manuskript.enums import Plot, Outline +from manuskript.enums import Plot, Outline, PlotStep from manuskript.models import references as Ref @@ -76,7 +76,13 @@ class plotTreeView(QTreeWidget): ############################################################################### def updateMaybe(self, topLeft, bottomRight): - if topLeft.parent() != QModelIndex(): + if topLeft.parent() != QModelIndex() and \ + topLeft.column() <= PlotStep.name.value <= bottomRight.column() and \ + self._showSubPlot: + # Name's of Step has been updated, we update Items if showing + # subplots. + self.updateItems() + elif topLeft.parent() != QModelIndex(): return if topLeft.column() <= Plot.name.value <= bottomRight.column():