From 589eb42235d2393cf3b4e0a328cbfd0b3b88cdf1 Mon Sep 17 00:00:00 2001 From: Curtis Gedak Date: Sun, 21 May 2017 11:33:07 -0600 Subject: [PATCH] Fixes: after project close, open or create project fails See issue #96. This change creates a new class disconnectAll() to ensure that all connections are disconnected for a specific signal and slot. Now when a project is closed, the UI signals are disconnected. As before, these signals and slots are connected when a project is opened. Because Manuskript permits working on only one project at a time, the menu items for File Open and Recents are disabled after a project is loaded. These menu items are enabled when a project is closed. Prior to this commit, subsequent open project selections would complain with the following message: TypeError: connection is not unique --- manuskript/mainWindow.py | 76 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) diff --git a/manuskript/mainWindow.py b/manuskript/mainWindow.py index 2499ae79..9977318c 100644 --- a/manuskript/mainWindow.py +++ b/manuskript/mainWindow.py @@ -360,6 +360,8 @@ class MainWindow(QMainWindow, Ui_MainWindow): self.saveTimerNoChanges.stop() # UI + for i in [self.actOpen, self.menuRecents]: + i.setEnabled(False) for i in [self.actSave, self.actSaveAs, self.actCloseProject, self.menuEdit, self.menuView, self.menuTools, self.menuHelp]: i.setEnabled(True) @@ -393,7 +395,11 @@ class MainWindow(QMainWindow, Ui_MainWindow): self.saveTimer.stop() loadSave.clearSaveCache() + self.breakConnections() + # UI + for i in [self.actOpen, self.menuRecents]: + i.setEnabled(True) for i in [self.actSave, self.actSaveAs, self.actCloseProject, self.menuEdit, self.menuView, self.menuTools, self.menuHelp]: i.setEnabled(False) @@ -699,6 +705,76 @@ class MainWindow(QMainWindow, Ui_MainWindow): self.lstDebugLabels.setModel(self.mdlLabels) self.lstDebugStatus.setModel(self.mdlStatus) + def disconnectAll(self, signal, oldHandler=None): + # Disconnect all "oldHandler" slot connections for a signal + # + # Ref: PyQt Widget connect() and disconnect() + # https://stackoverflow.com/questions/21586643/pyqt-widget-connect-and-disconnect + # + # The loop is needed for safely disconnecting a specific handler, + # because it may have been connected multiple times, and + # disconnect only removes one connection at a time. + while True: + try: + if oldHandler is not None: + signal.disconnect(oldHandler) + else: + signal.disconnect() + except TypeError: + break + + def breakConnections(self): + # Break connections for UI elements that were connected in makeConnections() + + # Characters + self.disconnectAll(self.btnAddPerso.clicked, self.mdlCharacter.addCharacter) + self.disconnectAll(self.btnRmPerso.clicked, self.lstCharacters.removeCharacter) + self.disconnectAll(self.btnPersoColor.clicked, self.lstCharacters.choseCharacterColor) + self.disconnectAll(self.btnPersoAddInfo.clicked, self.lstCharacters.addCharacterInfo) + self.disconnectAll(self.btnPersoRmInfo.clicked, self.lstCharacters.removeCharacterInfo) + + # Plots + self._updatingSubPlot = False + self.disconnectAll(self.btnAddPlot.clicked, self.mdlPlots.addPlot) + self.disconnectAll(self.btnRmPlot.clicked, lambda: + self.mdlPlots.removePlot(self.lstPlots.currentPlotIndex())) + self.disconnectAll(self.btnAddSubPlot.clicked, self.mdlPlots.addSubPlot) + 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.btnRmPlotPerso.clicked, self.mdlPlots.removePlotPerso) + + self.disconnectAll(self.mdlCharacter.dataChanged, self.mdlPlots.updatePlotPersoButton) + + # World + self.disconnectAll(self.treeWorld.selectionModel().selectionChanged, self.changeCurrentWorld) + self.disconnectAll(self.btnAddWorld.clicked, self.mdlWorld.addItem) + self.disconnectAll(self.btnRmWorld.clicked, self.mdlWorld.removeItem) + + # Outline + self.disconnectAll(self.treeOutlineOutline.selectionModel().selectionChanged, self.outlineItemEditor.selectionChanged) + self.disconnectAll(self.treeOutlineOutline.clicked, self.outlineItemEditor.selectionChanged) + + # Sync selection + self.disconnectAll(self.treeRedacOutline.selectionModel().selectionChanged, self.redacMetadata.selectionChanged) + self.disconnectAll(self.treeRedacOutline.clicked, self.redacMetadata.selectionChanged) + + self.disconnectAll(self.treeRedacOutline.selectionModel().selectionChanged, self.mainEditor.selectionChanged) + + # Debug + self.disconnectAll(self.tblDebugPersos.selectionModel().currentChanged, + lambda: self.tblDebugPersosInfos.setRootIndex(self.mdlCharacter.index( + self.tblDebugPersos.selectionModel().currentIndex().row(), + Character.name.value))) + self.disconnectAll(self.tblDebugPlots.selectionModel().currentChanged, + lambda: self.tblDebugPlotsPersos.setRootIndex(self.mdlPlots.index( + self.tblDebugPlots.selectionModel().currentIndex().row(), + Plot.characters.value))) + self.disconnectAll(self.tblDebugPlots.selectionModel().currentChanged, + lambda: self.tblDebugSubPlots.setRootIndex(self.mdlPlots.index( + self.tblDebugPlots.selectionModel().currentIndex().row(), + Plot.steps.value))) + ############################################################################### # GENERAL AKA UNSORTED ###############################################################################