UI/UserInterface.py

changeset 5362
e9b8797923da
parent 5314
76013775e623
child 5371
01c4c059142b
--- a/UI/UserInterface.py	Sat Dec 03 18:20:38 2016 +0100
+++ b/UI/UserInterface.py	Sun Dec 04 18:40:41 2016 +0100
@@ -267,6 +267,7 @@
         self.findFilesDialog = None
         self.replaceFilesDialog = None
         self.__notification = None
+        self.__readingSession = False
         
         # now setup the connections
         splash.showMessage(self.tr("Setting up connections..."))
@@ -370,9 +371,15 @@
         self.project.projectClosed.connect(self.__projectClosed)
         self.project.projectClosed.connect(
             self.backgroundService.preferencesOrProjectChanged)
+        self.project.projectOpened.connect(self.__writeCrashSession)
+        self.project.projectClosed.connect(self.__writeCrashSession)
         
         self.multiProject.multiProjectOpened.connect(
             self.__activateMultiProjectBrowser)
+        self.multiProject.multiProjectOpened.connect(
+            self.__writeCrashSession)
+        self.multiProject.multiProjectClosed.connect(
+            self.__writeCrashSession)
         
         self.debuggerUI.resetUI.connect(self.viewmanager.handleResetUI)
         self.debuggerUI.resetUI.connect(self.debugViewer.handleResetUI)
@@ -450,6 +457,10 @@
             self.projectBrowser.handleEditorLineChanged)
         self.viewmanager.checkActions.connect(
             self.cooperation.checkEditorActions)
+        self.viewmanager.editorOpened.connect(self.__writeCrashSession)
+        self.viewmanager.editorClosed.connect(self.__writeCrashSession)
+        self.viewmanager.editorRenamed.connect(self.__writeCrashSession)
+        self.viewmanager.editorChanged.connect(self.__writeCrashSession)
         
         self.shell.zoomValueChanged.connect(self.viewmanager.zoomValueChanged)
         
@@ -536,7 +547,7 @@
         self.currentProfile = None
         
         self.shutdownCalled = False
-        self.inCloseEevent = False
+        self.inCloseEvent = False
 
         # now redirect stdout and stderr
         # TODO: release - reenable redirection
@@ -1088,6 +1099,10 @@
             .e4p, then it is opened as a project file. If it ends in
             .e4m or .e5m, it is opened as a multiproject.
         """
+        # check and optionally read a crash session and ignore any arguments
+        if self.__readCrashSession():
+            return
+        
         # no args, return
         if args is None:
             if not self.__noOpenAtStartup:
@@ -1257,6 +1272,32 @@
         self.exitAct.setMenuRole(QAction.QuitRole)
         self.actions.append(self.exitAct)
 
+        self.saveSessionAct = E5Action(
+            self.tr('Save session'),
+            self.tr('Save session...'),
+            0, 0, self, 'save_session_to_file')
+        self.saveSessionAct.setStatusTip(self.tr('Save session'))
+        self.saveSessionAct.setWhatsThis(self.tr(
+            """<b>Save session...</b>"""
+            """<p>This saves the current session to disk. A dialog is"""
+            """ opened to select the file name.</p>"""
+        ))
+        self.saveSessionAct.triggered.connect(self.__saveSessionToFile)
+        self.actions.append(self.saveSessionAct)
+
+        self.loadSessionAct = E5Action(
+            self.tr('Load session'),
+            self.tr('Load session...'),
+            0, 0, self, 'load_session_from_file')
+        self.loadSessionAct.setStatusTip(self.tr('Load session'))
+        self.loadSessionAct.setWhatsThis(self.tr(
+            """<b>Load session...</b>"""
+            """<p>This loads a session saved to disk previously. A dialog is"""
+            """ opened to select the file name.</p>"""
+        ))
+        self.loadSessionAct.triggered.connect(self.__loadSessionFromFile)
+        self.actions.append(self.loadSessionAct)
+
         self.newWindowAct = E5Action(
             self.tr('New Window'),
             UI.PixmapCache.getIcon("newWindow.png"),
@@ -2465,6 +2506,9 @@
         self.__menus["file"] = self.viewmanager.initFileMenu()
         mb.addMenu(self.__menus["file"])
         self.__menus["file"].addSeparator()
+        self.__menus["file"].addAction(self.saveSessionAct)
+        self.__menus["file"].addAction(self.loadSessionAct)
+        self.__menus["file"].addSeparator()
         self.__menus["file"].addAction(self.exitAct)
         act = self.__menus["file"].actions()[0]
         sep = self.__menus["file"].insertSeparator(act)
@@ -5781,54 +5825,168 @@
                     "<p>The tasks file <b>{0}</b> could not be read.</p>")
                 .format(fn))
         
-    def __writeSession(self):
+    def __writeSession(self, filename="", crashSession=False):
         """
         Private slot to write the session data to an XML file (.e5s).
-        """
-        fn = os.path.join(Utilities.getConfigDir(), "eric6session.e5s")
+        
+        @param filename name of a session file to write
+        @type str
+        @param crashSession flag indicating to write a crash session file
+        @type bool
+        @return flag indicating success
+        @rtype bool
+        """
+        res = False
+        if filename:
+            fn = filename
+        elif crashSession:
+            fn = os.path.join(Utilities.getConfigDir(),
+                              "eric6_crash_session.e5s")
+        else:
+            fn = os.path.join(Utilities.getConfigDir(),
+                              "eric6session.e5s")
         f = QFile(fn)
         if f.open(QIODevice.WriteOnly):
             from E5XML.SessionWriter import SessionWriter
             SessionWriter(f, None).writeXML()
             f.close()
+            res = True
         else:
             E5MessageBox.critical(
                 self,
                 self.tr("Save session"),
-                self.tr(
-                    "<p>The session file <b>{0}</b> could not be written.</p>")
+                self.tr("<p>The session file <b>{0}</b> could not be"
+                        " written.</p>")
                 .format(fn))
-        
-    def __readSession(self):
+        return res
+        
+    def __readSession(self, filename=""):
         """
         Private slot to read in the session file (.e5s or .e4s).
-        """
-        fn = os.path.join(Utilities.getConfigDir(), "eric6session.e5s")
-        if not os.path.exists(fn):
-            fn = os.path.join(Utilities.getConfigDir(), "eric6session.e4s")
+        
+        @param filename name of a session file to read
+        @type str
+        @return flag indicating success
+        @rtype bool
+        """
+        if filename:
+            fn = filename
+        else:
+            fn = os.path.join(Utilities.getConfigDir(),
+                              "eric6session.e5s")
             if not os.path.exists(fn):
+                fn = os.path.join(Utilities.getConfigDir(),
+                                  "eric6session.e4s")
+                if not os.path.exists(fn):
+                    E5MessageBox.critical(
+                        self,
+                        self.tr("Read session"),
+                        self.tr("<p>The session file <b>{0}</b> could not"
+                                " be read.</p>")
+                        .format(fn))
+                    fn = ""
+        
+        res = False
+        if fn:
+            f = QFile(fn)
+            if f.open(QIODevice.ReadOnly):
+                from E5XML.SessionReader import SessionReader
+                self.__readingSession = True
+                reader = SessionReader(f, True)
+                reader.readXML()
+                self.__readingSession = False
+                f.close()
+                res = True
+            else:
                 E5MessageBox.critical(
                     self,
                     self.tr("Read session"),
-                    self.tr(
-                        "<p>The session file <b>{0}</b> could not"
-                        " be read.</p>")
+                    self.tr("<p>The session file <b>{0}</b> could not be"
+                            " read.</p>")
                     .format(fn))
-                return
-        
-        f = QFile(fn)
-        if f.open(QIODevice.ReadOnly):
-            from E5XML.SessionReader import SessionReader
-            reader = SessionReader(f, True)
-            reader.readXML()
-            f.close()
-        else:
-            E5MessageBox.critical(
+        
+        # Write a crash session after a session was read.
+        self.__writeCrashSession()
+        
+        return res
+    
+    def __saveSessionToFile(self):
+        """
+        Private slot to save a session to disk.
+        """
+        sessionFile, selectedFilter = E5FileDialog.getSaveFileNameAndFilter(
+            self,
+            self.tr("Save session"),
+            Utilities.getHomeDir(),
+            self.tr("eric6 Session Files (*.e5s)"),
+            "")
+        
+        if not sessionFile:
+            return
+        
+        ext = QFileInfo(sessionFile).suffix()
+        if not ext:
+            ex = selectedFilter.split("(*")[1].split(")")[0]
+            if ex:
+                sessionFile += ex
+        
+        self.__writeSession(filename=sessionFile)
+    
+    def __loadSessionFromFile(self):
+        """
+        Private slot to load a session from disk.
+        """
+        sessionFile = E5FileDialog.getOpenFileName(
+            self,
+            self.tr("Load session"),
+            Utilities.getHomeDir(),
+            self.tr("eric6 Session Files (*.e5s)"))
+        
+        if not sessionFile:
+            return
+        
+        self.__readSession(filename=sessionFile)
+    
+    def __deleteCrashSession(self):
+        """
+        Private slot to delete the crash session file.
+        """
+        fn = os.path.join(Utilities.getConfigDir(),
+                          "eric6_crash_session.e5s")
+        if os.path.exists(fn):
+            try:
+                os.remove(fn)
+            except OSError:
+                # ignore it silently
+                pass
+    
+    def __writeCrashSession(self):
+        """
+        Private slot to write a crash session file.
+        """
+        if not self.__readingSession:
+            self.__writeSession(crashSession=True)
+    
+    def __readCrashSession(self):
+        """
+        Private method to check for and read a crash session.
+        
+        @return flag indicating a crash session file was found and read
+        @rtype bool
+        """
+        res = False
+        fn = os.path.join(Utilities.getConfigDir(),
+                          "eric6_crash_session.e5s")
+        if os.path.exists(fn):
+            yes = E5MessageBox.yesNo(
                 self,
-                self.tr("Read session"),
-                self.tr(
-                    "<p>The session file <b>{0}</b> could not be read.</p>")
-                .format(fn))
+                self.tr("Crash Session found!"),
+                self.tr("""A session file of a crashed session was found."""
+                        """ Shall this session be restored?"""))
+            if yes:
+                res = self.__readSession(filename=fn)
+        
+        return res
     
     def showFindFileByNameDialog(self):
         """
@@ -6034,8 +6192,8 @@
         """
         if self.__shutdown():
             event.accept()
-            if not self.inCloseEevent:
-                self.inCloseEevent = True
+            if not self.inCloseEvent:
+                self.inCloseEvent = True
                 QTimer.singleShot(0, e5App().closeAllWindows)
         else:
             event.ignore()
@@ -6056,7 +6214,7 @@
         if not self.irc.shutdown():
             return False
         
-        self.__writeSession()
+        sessionCreated = self.__writeSession()
         
         if not self.project.closeProject():
             return False
@@ -6067,6 +6225,9 @@
         if not self.viewmanager.closeViewManager():
             return False
         
+        if sessionCreated:
+            self.__deleteCrashSession()
+        
         self.__previewer.shutdown()
         
         self.shell.closeShell()

eric ide

mercurial