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
This commit is contained in:
Curtis Gedak 2017-05-21 11:33:07 -06:00
parent 9a646cb403
commit 589eb42235

View file

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