--- a/WebBrowser/Session/SessionManager.py Sun Jul 02 19:40:39 2017 +0200 +++ b/WebBrowser/Session/SessionManager.py Mon Jul 03 19:23:54 2017 +0200 @@ -15,7 +15,8 @@ from PyQt5.QtCore import pyqtSlot, pyqtSignal, Qt, QObject, QTimer, QDir, \ QFile, QFileInfo, QFileSystemWatcher, QByteArray, QDateTime from PyQt5.QtWidgets import QMenu, QAction, QActionGroup, QApplication, \ - QInputDialog, QLineEdit + QInputDialog, QLineEdit, QDialog, QDialogButtonBox, QLabel, QComboBox, \ + QVBoxLayout from E5Gui import E5MessageBox @@ -87,17 +88,24 @@ self.__backupSavedSession() - self.__autoSaveTimer = QTimer() - self.__autoSaveTimer.setSingleShot(True) - self.__autoSaveTimer.timeout.connect(self.__autoSaveSession) - self.__initSessionSaveTimer() + self.__autoSaveTimer = None + self.__shutdown = False + + def activateTimer(self): + """ + Public method to activate the session save timer. + """ + if self.__autoSaveTimer is None: + self.__autoSaveTimer = QTimer() + self.__autoSaveTimer.setSingleShot(True) + self.__autoSaveTimer.timeout.connect(self.__autoSaveSession) + self.__initSessionSaveTimer() def preferencesChanged(self): """ Public slot to react upon changes of the settings. """ self.__initSessionSaveTimer() - # TODO: implement this def getSessionsDirectory(self): """ @@ -132,6 +140,14 @@ Public method to perform any shutdown actions. """ self.__autoSaveTimer.stop() + if not self.__shutdown: + self.__autoSaveSession(startTimer=False) + self.__shutdown = True + + def autoSaveSession(self): + """ + Public method to save the current session state. + """ self.__autoSaveSession(startTimer=False) def __initSessionSaveTimer(self): @@ -176,6 +192,7 @@ sessionData = {"Windows": []} + activeWindow = WebBrowserWindow.getWindow() for window in WebBrowserWindow.mainWindows(): data = window.tabWidget().getSessionData() @@ -184,15 +201,20 @@ data["WindowGeometry"] = bytes(geometry.toBase64()).decode("ascii") sessionData["Windows"].append(data) + + if window is activeWindow: + sessionData["CurrentWindowIndex"] = \ + len(sessionData["Windows"]) -1 if sessionData["Windows"]: sessionFile = open(sessionFileName, "w") json.dump(sessionData, sessionFile, indent=2) sessionFile.close() - def __readSessionFromFile(self, sessionFileName): + @classmethod + def readSessionFromFile(cls, sessionFileName): """ - Private method to read the session data from a file. + Class method to read the session data from a file. @param sessionFileName file name of the session file @type str @@ -203,11 +225,34 @@ sessionFile = open(sessionFileName, "r") sessionData = json.load(sessionFile) sessionFile.close() + if not cls.isValidSession(sessionData): + sessionData = {} except (IOError, OSError): sessionData = {} return sessionData + @classmethod + def isValidSession(cls, session): + """ + Class method to check the validity of a session. + + @param session dictionary containing the session data + @type dict + @return flag indicating validity + @rtype bool + """ + if not session: + return False + + if "Windows" not in session: + return False + + if not session["Windows"]: + return False + + return True + def __backupSavedSession(self): """ Private method to backup the most recently saved session. @@ -264,7 +309,7 @@ ["*.json"], QDir.Files, QDir.Time) for sessionFileInfo in sessionFilesInfoList: - sessionData = self.__readSessionFromFile( + sessionData = self.readSessionFromFile( sessionFileInfo.absoluteFilePath()) if not sessionData or not sessionData["Windows"]: continue @@ -335,9 +380,9 @@ path = act.data() self.switchToSession(path) - def __openSession(self, sessionFilePath, flags=0): + def openSession(self, sessionFilePath, flags=0): """ - Private method to open a session from a given session file. + Public method to open a session from a given session file. @param sessionFilePath name of the session file to get session from @type str @@ -347,7 +392,7 @@ if self.__isActive(sessionFilePath): return - sessionData = self.__readSessionFromFile(sessionFilePath) + sessionData = self.readSessionFromFile(sessionFilePath) if not sessionData or not sessionData["Windows"]: return @@ -363,7 +408,7 @@ window = window.newWindow(restoreSession=True) # close all existing windows - for win in WebBrowserWindow.mainWindows(): + for win in WebBrowserWindow.mainWindows()[:]: if win is not window: win.forceClose() @@ -373,6 +418,21 @@ QFileInfo(sessionFilePath).canonicalFilePath() self.__sessionMetaData = [] + self.restoreSessionFromData(window, sessionData) + + @classmethod + def restoreSessionFromData(cls, window=None, sessionData=None): + """ + Class method to restore a session from a session data dictionary. + + @param window reference to main window to restore to + @type WebBrowserWindow + @param sessionData dictionary containing the session data + """ + from WebBrowser.WebBrowserWindow import WebBrowserWindow + if window is None: + window = WebBrowserWindow.mainWindow() + QApplication.setOverrideCursor(Qt.WaitCursor) # restore session for first window data = sessionData["Windows"].pop(0) @@ -381,6 +441,9 @@ geometry = QByteArray.fromBase64( data["WindowGeometry"].encode("ascii")) window.restoreGeometry(geometry) + if Utilities.isWindowsPlatform(): + window.hide() + window.show() QApplication.processEvents() # restore additional windows @@ -392,12 +455,25 @@ geometry = QByteArray.fromBase64( data["WindowGeometry"].encode("ascii")) window.restoreGeometry(geometry) + if Utilities.isWindowsPlatform(): + window.hide() + window.show() QApplication.processEvents() QApplication.restoreOverrideCursor() + + if "CurrentWindowIndex" in sessionData: + currentWindowIndex = sessionData["CurrentWindowIndex"] + try: + currentWindow = \ + WebBrowserWindow.mainWindows()[currentWindowIndex] + currentWindow.raise_() + except IndexError: + # ignore it + pass def renameSession(self, sessionFilePath, flags=0): """ - Public method to rename or clone a session + Public method to rename or clone a session. @param sessionFilePath name of the session file @type str @@ -493,6 +569,8 @@ @param sessionFilePath file name of the session file to replace with @type str + @return flag indicating success + @rtype bool """ from WebBrowser.WebBrowserWindow import WebBrowserWindow res = E5MessageBox.yesNo( @@ -501,7 +579,10 @@ self.tr("""Are you sure you want to replace the current""" """ session?""")) if res: - self.__openSession(sessionFilePath, SessionManager.ReplaceSession) + self.openSession(sessionFilePath, SessionManager.ReplaceSession) + return True + else: + return False def switchToSession(self, sessionFilePath): """ @@ -509,8 +590,11 @@ @param sessionFilePath file name of the session file to switch to @type str + @return flag indicating success + @rtype bool """ - self.__openSession(sessionFilePath, SessionManager.SwitchSession) + self.openSession(sessionFilePath, SessionManager.SwitchSession) + return True def cloneSession(self, sessionFilePath): """ @@ -526,7 +610,7 @@ Public method to delete a session. @param sessionFilePath file name of the session file to be deleted - @type str + @type str """ from WebBrowser.WebBrowserWindow import WebBrowserWindow res = E5MessageBox.yesNo( @@ -586,3 +670,53 @@ dlg = SessionManagerDialog(WebBrowserWindow.getWindow()) dlg.open() + + def selectSession(self): + """ + Public method to select a session to be restored. + + @return name of the session file to be restored + @rtype str + """ + from WebBrowser.WebBrowserWindow import WebBrowserWindow + + self.__fillMetaDataList() + + if self.__sessionMetaData: + # skip, if no session file available + dlg = QDialog(WebBrowserWindow.getWindow(), + Qt.WindowStaysOnTopHint) + lbl = QLabel(self.tr("Please select the startup session:")) + combo = QComboBox(dlg) + buttonBox = QDialogButtonBox( + QDialogButtonBox.Ok | QDialogButtonBox.Cancel, dlg) + buttonBox.accepted.connect(dlg.accept) + buttonBox.rejected.connect(dlg.reject) + + layout = QVBoxLayout() + layout.addWidget(lbl) + layout.addWidget(combo) + layout.addWidget(buttonBox) + dlg.setLayout(layout) + + lastActiveSessionFileInfo = QFileInfo(self.__lastActiveSession) + + for metaData in self.__sessionMetaData: + if QFileInfo(metaData.filePath) != lastActiveSessionFileInfo: + combo.addItem(metaData.name, metaData.filePath) + else: + combo.insertItem( + 0, + self.tr("{0} (last session)").format(metaData.name), + metaData.filePath + ) + combo.setCurrentIndex(0) + + if dlg.exec_() == QDialog.Accepted: + session = combo.currentData() + if session is None: + self.__lastActiveSession = self.__sessionDefault + else: + self.__lastActiveSession = session + + return self.__lastActiveSession