Implemented functions to load UML graphics from disc.

Mon, 10 Sep 2012 18:42:28 +0200

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Mon, 10 Sep 2012 18:42:28 +0200
changeset 2034
8de0fc1f7fef
parent 2033
4b99609f6a87
child 2035
11bb61bc138d

Implemented functions to load UML graphics from disc.

Graphics/ApplicationDiagramBuilder.py file | annotate | diff | comparison | revisions
Graphics/AssociationItem.py file | annotate | diff | comparison | revisions
Graphics/ClassItem.py file | annotate | diff | comparison | revisions
Graphics/ImportsDiagramBuilder.py file | annotate | diff | comparison | revisions
Graphics/ModuleItem.py file | annotate | diff | comparison | revisions
Graphics/PackageDiagramBuilder.py file | annotate | diff | comparison | revisions
Graphics/PackageItem.py file | annotate | diff | comparison | revisions
Graphics/UMLClassDiagramBuilder.py file | annotate | diff | comparison | revisions
Graphics/UMLDiagramBuilder.py file | annotate | diff | comparison | revisions
Graphics/UMLDialog.py file | annotate | diff | comparison | revisions
Graphics/UMLGraphicsView.py file | annotate | diff | comparison | revisions
Graphics/UMLItem.py file | annotate | diff | comparison | revisions
Project/Project.py file | annotate | diff | comparison | revisions
Project/ProjectSourcesBrowser.py file | annotate | diff | comparison | revisions
QScintilla/Editor.py file | annotate | diff | comparison | revisions
--- a/Graphics/ApplicationDiagramBuilder.py	Sun Sep 09 19:38:07 2012 +0200
+++ b/Graphics/ApplicationDiagramBuilder.py	Mon Sep 10 18:42:28 2012 +0200
@@ -12,6 +12,8 @@
 
 from PyQt4.QtGui import QApplication, QProgressDialog
 
+from E5Gui import E5MessageBox
+
 from .UMLDiagramBuilder import UMLDiagramBuilder
 from .PackageItem import PackageItem, PackageModel
 from .AssociationItem import AssociationItem, Imports
@@ -247,11 +249,32 @@
         return "project={0}, no_modules={1}".format(
             self.project.getProjectFile(), self.noModules)
     
-    def parsePersistenceData(self, data):
+    def parsePersistenceData(self, version, data):
         """
         Public method to parse persisted data.
         
-        @param dat persisted data to be parsed (string)
+        @param version version of the data (string)
+        @param data persisted data to be parsed (string)
+        @return flag indicating success (boolean)
         """
-        # TODO: implement this
-        return
+        parts = data.split(", ")
+        if len(parts) != 2 or \
+           not parts[0].startswith("project=") or \
+           not parts[1].startswith("no_modules="):
+            return False
+        
+        projectFile = parts[0].split("=", 1)[1].strip()
+        if projectFile != self.project.getProjectFile():
+            res = E5MessageBox.yesNo(None,
+                self.trUtf8("Load Diagram"),
+                self.trUtf8("""<p>The diagram belongs to the project <b>{0}</b>."""
+                             """ Shall this project be opened?</p>""").format(
+                    projectFile))
+            if res:
+                self.project.openProject(projectFile)
+            
+        self.noModules = Utilities.toBool(parts[1].split("=", 1)[1].strip())
+        
+        self.initialize()
+        
+        return True
--- a/Graphics/AssociationItem.py	Sun Sep 09 19:38:07 2012 +0200
+++ b/Graphics/AssociationItem.py	Mon Sep 10 18:42:28 2012 +0200
@@ -549,7 +549,7 @@
                 elif key == "dst":
                     dst = int(value)
                 elif key == "type":
-                    assocType = value
+                    assocType = int(value)
                 elif key == "topToBottom":
                     topToBottom = Utilities.toBool(value)
         
--- a/Graphics/ClassItem.py	Sun Sep 09 19:38:07 2012 +0200
+++ b/Graphics/ClassItem.py	Mon Sep 10 18:42:28 2012 +0200
@@ -11,6 +11,8 @@
 
 from .UMLItem import UMLItem
 
+import Utilities
+
 
 class ClassModel(object):
     """
@@ -242,10 +244,39 @@
         
         return ", " + ", ".join(entries)
     
-    def parseItemDataString(self, data):
+    def parseItemDataString(self, version, data):
         """
         Public method to parse the given persistence data.
         
+        @param version version of the data (string)
         @param data persisted data to be parsed (string)
+        @return flag indicating success (boolean)
         """
-        # TODO: implement this
+        parts = data.split(", ")
+        if len(parts) < 3:
+            return False
+        
+        name = ""
+        attributes = []
+        methods = []
+        
+        for part in parts:
+            key, value = part.split("=", 1)
+            if key == "is_external":
+                self.external = Utilities.toBool(value.strip())
+            elif key == "no_attributes":
+                self.noAttrs = Utilities.toBool(value.strip())
+            elif key == "name":
+                name = value.strip()
+            elif key == "attributes":
+                attributes = value.strip().split("||")
+            elif key == "methods":
+                methods = value.strip().split("||")
+            else:
+                return False
+        
+        self.model = ClassModel(name, methods, attributes)
+        self.__createTexts()
+        self.__calculateSize()
+        
+        return True
--- a/Graphics/ImportsDiagramBuilder.py	Sun Sep 09 19:38:07 2012 +0200
+++ b/Graphics/ImportsDiagramBuilder.py	Mon Sep 10 18:42:28 2012 +0200
@@ -249,11 +249,23 @@
         return "package={0}, show_external={1}".format(
             self.packagePath, self.showExternalImports)
     
-    def parsePersistenceData(self, data):
+    def parsePersistenceData(self, version, data):
         """
         Public method to parse persisted data.
         
-        @param dat persisted data to be parsed (string)
+        @param version version of the data (string)
+        @param data persisted data to be parsed (string)
+        @return flag indicating success (boolean)
         """
-        # TODO: implement this
-        return
+        parts = data.split(", ")
+        if len(parts) != 2 or \
+           not parts[0].startswith("package=") or \
+           not parts[1].startswith("show_external="):
+            return False
+        
+        self.packagePath = parts[0].split("=", 1)[1].strip()
+        self.showExternalImports = Utilities.toBool(parts[1].split("=", 1)[1].strip())
+        
+        self.initialize()
+        
+        return True
--- a/Graphics/ModuleItem.py	Sun Sep 09 19:38:07 2012 +0200
+++ b/Graphics/ModuleItem.py	Mon Sep 10 18:42:28 2012 +0200
@@ -183,10 +183,32 @@
         
         return ", " + ", ".join(entries)
     
-    def parseItemDataString(self, data):
+    def parseItemDataString(self, version, data):
         """
         Public method to parse the given persistence data.
         
+        @param version version of the data (string)
         @param data persisted data to be parsed (string)
+        @return flag indicating success (boolean)
         """
-        # TODO: implement this
+        parts = data.split(", ")
+        if len(parts) < 1:
+            return False
+        
+        name = ""
+        classes = []
+        
+        for part in parts:
+            key, value = part.split("=", 1)
+            if key == "name":
+                name = value.strip()
+            elif key == "classes":
+                classes = value.strip().split("||")
+            else:
+                return False
+        
+        self.model = ModuleModel(name, classes)
+        self.__createTexts()
+        self.__calculateSize()
+        
+        return True
--- a/Graphics/PackageDiagramBuilder.py	Sun Sep 09 19:38:07 2012 +0200
+++ b/Graphics/PackageDiagramBuilder.py	Mon Sep 10 18:42:28 2012 +0200
@@ -322,11 +322,23 @@
         """
         return "package={0}, no_attributes={1}".format(self.package, self.noAttrs)
     
-    def parsePersistenceData(self, data):
+    def parsePersistenceData(self, version, data):
         """
         Public method to parse persisted data.
         
-        @param dat persisted data to be parsed (string)
+        @param version version of the data (string)
+        @param data persisted data to be parsed (string)
+        @return flag indicating success (boolean)
         """
-        # TODO: implement this
-        return
+        parts = data.split(", ")
+        if len(parts) != 2 or \
+           not parts[0].startswith("package=") or \
+           not parts[1].startswith("no_attributes="):
+            return False
+        
+        self.package = parts[0].split("=", 1)[1].strip()
+        self.noAttrs = Utilities.toBool(parts[1].split("=", 1)[1].strip())
+        
+        self.initialize()
+        
+        return True
--- a/Graphics/PackageItem.py	Sun Sep 09 19:38:07 2012 +0200
+++ b/Graphics/PackageItem.py	Mon Sep 10 18:42:28 2012 +0200
@@ -11,6 +11,8 @@
 
 from .UMLItem import UMLItem
 
+import Utilities
+
 
 class PackageModel(object):
     """
@@ -203,10 +205,34 @@
         
         return ", " + ", ".join(entries)
     
-    def parseItemDataString(self, data):
+    def parseItemDataString(self, version, data):
         """
         Public method to parse the given persistence data.
         
+        @param version version of the data (string)
         @param data persisted data to be parsed (string)
+        @return flag indicating success (boolean)
         """
-        # TODO: implement this
+        parts = data.split(", ")
+        if len(parts) < 2:
+            return False
+        
+        name = ""
+        modules = []
+        
+        for part in parts:
+            key, value = part.split("=", 1)
+            if key == "no_modules":
+                self.external = Utilities.toBool(value.strip())
+            elif key == "name":
+                name = value.strip()
+            elif key == "modules":
+                modules = value.strip().split("||")
+            else:
+                return False
+        
+        self.model = PackageModel(name, modules)
+        self.__createTexts()
+        self.__calculateSize()
+        
+        return True
--- a/Graphics/UMLClassDiagramBuilder.py	Sun Sep 09 19:38:07 2012 +0200
+++ b/Graphics/UMLClassDiagramBuilder.py	Mon Sep 10 18:42:28 2012 +0200
@@ -11,6 +11,7 @@
 
 from PyQt4.QtGui import QGraphicsTextItem
 
+import Utilities
 import Utilities.ModuleParser
 import Preferences
 
@@ -275,11 +276,23 @@
         """
         return "file={0}, no_attributes={1}".format(self.file, self.noAttrs)
     
-    def parsePersistenceData(self, data):
+    def parsePersistenceData(self, version, data):
         """
         Public method to parse persisted data.
         
-        @param dat persisted data to be parsed (string)
+        @param version version of the data (string)
+        @param data persisted data to be parsed (string)
+        @return flag indicating success (boolean)
         """
-        # TODO: implement this
-        return
+        parts = data.split(", ")
+        if len(parts) != 2 or \
+           not parts[0].startswith("file=") or \
+           not parts[1].startswith("no_attributes="):
+            return False
+        
+        self.file = parts[0].split("=", 1)[1].strip()
+        self.noAttrs = Utilities.toBool(parts[1].split("=", 1)[1].strip())
+        
+        self.initialize()
+        
+        return True
--- a/Graphics/UMLDiagramBuilder.py	Sun Sep 09 19:38:07 2012 +0200
+++ b/Graphics/UMLDiagramBuilder.py	Mon Sep 10 18:42:28 2012 +0200
@@ -51,10 +51,12 @@
         """
         return ""
     
-    def parsePersistenceData(self, data):
+    def parsePersistenceData(self, version, data):
         """
         Public method to parse persisted data.
         
-        @param dat persisted data to be parsed (string)
+        @param version version of the data (string)
+        @param data persisted data to be parsed (string)
+        @return flag indicating success (boolean)
         """
-        return
+        return True
--- a/Graphics/UMLDialog.py	Sun Sep 09 19:38:07 2012 +0200
+++ b/Graphics/UMLDialog.py	Mon Sep 10 18:42:28 2012 +0200
@@ -22,18 +22,21 @@
     """
     Class implementing a dialog showing UML like diagrams.
     """
+    NoDiagram = 255
     ClassDiagram = 0
     PackageDiagram = 1
     ImportsDiagram = 2
     ApplicationDiagram = 3
     
+    FileVersions = ["1.0"]
+    
     def __init__(self, diagramType, project, path="", parent=None, initBuilder=True,
                  **kwargs):
         """
         Constructor
         
-        @param diagramType type of the diagram
-            (one of ApplicationDiagram, ClassDiagram, ImportsDiagram, PackageDiagram)
+        @param diagramType type of the diagram (one of ApplicationDiagram, ClassDiagram,
+            ImportsDiagram, NoDiagram, PackageDiagram)
         @param project reference to the project object (Project)
         @param path file or directory path to build the diagram from (string)
         @param parent parent widget of the dialog (QWidget)
@@ -44,11 +47,12 @@
         self.setObjectName("UMLDialog")
         
         self.__diagramType = diagramType
+        self.__project = project
         
         self.scene = QGraphicsScene(0.0, 0.0, 800.0, 600.0)
         self.umlView = UMLGraphicsView(self.scene, parent=self)
-        self.builder = self.__diagramBuilder(self.__diagramType, project, path, **kwargs)
-        if initBuilder:
+        self.builder = self.__diagramBuilder(self.__diagramType, path, **kwargs)
+        if self.builder and initBuilder:
             self.builder.initialize()
         
         self.__fileName = ""
@@ -69,6 +73,11 @@
                     self.trUtf8("Close"), self)
         self.closeAct.triggered[()].connect(self.close)
         
+        self.openAct = \
+            QAction(UI.PixmapCache.getIcon("open.png"),
+                    self.trUtf8("Load"), self)
+        self.openAct.triggered[()].connect(self.load)
+        
         self.saveAct = \
             QAction(UI.PixmapCache.getIcon("fileSave.png"),
                     self.trUtf8("Save"), self)
@@ -104,6 +113,8 @@
         
         self.fileToolBar = QToolBar(self.trUtf8("File"), self)
         self.fileToolBar.setIconSize(UI.Config.ToolBarIconSize)
+        self.fileToolBar.addAction(self.openAct)
+        self.fileToolBar.addSeparator()
         self.fileToolBar.addAction(self.saveAct)
         self.fileToolBar.addAction(self.saveAsAct)
         self.fileToolBar.addAction(self.saveImageAct)
@@ -117,41 +128,51 @@
         self.addToolBar(Qt.TopToolBarArea, self.windowToolBar)
         self.addToolBar(Qt.TopToolBarArea, self.umlToolBar)
     
-    def show(self):
+    def show(self, fromFile=False):
         """
-        Overriden method to show the dialog.
+        Public method to show the dialog.
+        
+        @keyparam fromFile flag indicating, that the diagram was loaded
+            from file (boolean)
         """
-        self.builder.buildDiagram()
+        if not fromFile and self.builder:
+            self.builder.buildDiagram()
         super().show()
     
     def __relayout(self):
         """
         Private method to relayout the diagram.
         """
-        self.builder.buildDiagram()
+        if self.builder:
+            self.builder.buildDiagram()
     
-    def __diagramBuilder(self, diagramType, project, path, **kwargs):
+    def __diagramBuilder(self, diagramType, path, **kwargs):
         """
         Private method to instantiate a diagram builder object.
         
         @param diagramType type of the diagram
             (one of ApplicationDiagram, ClassDiagram, ImportsDiagram, PackageDiagram)
-        @param project reference to the project object (Project)
         @param path file or directory path to build the diagram from (string)
         @param kwargs diagram specific data
         """
         if diagramType == UMLDialog.ClassDiagram:
             from .UMLClassDiagramBuilder import UMLClassDiagramBuilder
-            return UMLClassDiagramBuilder(self, self.umlView, project, path, **kwargs)
+            return UMLClassDiagramBuilder(self, self.umlView, self.__project, path,
+                                          **kwargs)
         elif diagramType == UMLDialog.PackageDiagram:
             from .PackageDiagramBuilder import PackageDiagramBuilder
-            return PackageDiagramBuilder(self, self.umlView, project, path, **kwargs)
+            return PackageDiagramBuilder(self, self.umlView, self.__project, path,
+                                         **kwargs)
         elif diagramType == UMLDialog.ImportsDiagram:
             from .ImportsDiagramBuilder import ImportsDiagramBuilder
-            return ImportsDiagramBuilder(self, self.umlView, project, path, **kwargs)
+            return ImportsDiagramBuilder(self, self.umlView, self.__project, path,
+                                         **kwargs)
         elif diagramType == UMLDialog.ApplicationDiagram:
             from .ApplicationDiagramBuilder import ApplicationDiagramBuilder
-            return ApplicationDiagramBuilder(self, self.umlView, project, **kwargs)
+            return ApplicationDiagramBuilder(self, self.umlView, self.__project,
+                                             **kwargs)
+        elif diagramType == UMLDialog.NoDiagram:
+            return None
         else:
             raise ValueError(
                 self.trUtf8("Illegal diagram type '{0}' given.").format(diagramType))
@@ -229,18 +250,115 @@
             E5MessageBox.critical(self,
                 self.trUtf8("Save Diagram"),
                 self.trUtf8("""<p>The file <b>{0}</b> could not be saved.</p>"""
-                             """<p>Reason: {1}</p>""").format(fname, str(err)))
+                             """<p>Reason: {1}</p>""").format(filename, str(err)))
+            return
         
         self.__fileName = filename
     
-    @classmethod
-    def generateDialogFromFile(cls, project, parent=None):
+    def load(self):
+        """
+        Public method to load a diagram from a file.
+        
+        @return flag indicating success (boolean)
         """
-        Class method to generate a dialog reading data from a file.
+        filename = E5FileDialog.getOpenFileName(
+            self,
+            self.trUtf8("Load Diagram"),
+            "",
+            self.trUtf8("Eric5 Graphics File (*.e5g);;All Files (*)"))
+        if not filename:
+            # Cancelled by user
+            return False
+        
+        try:
+            f = open(filename, "r", encoding="utf-8")
+            data = f.read()
+            f.close()
+        except (IOError, OSError) as err:
+            E5MessageBox.critical(self,
+                self.trUtf8("Load Diagram"),
+                self.trUtf8("""<p>The file <b>{0}</b> could not be read.</p>"""
+                             """<p>Reason: {1}</p>""").format(filename, str(err)))
+            return False
+        
+        lines = data.splitlines()
+        if len(lines) < 3:
+            self.__showInvalidDataMessage(filename)
+            return False
         
-        @param project reference to the project object (Project)
-        @param parent parent widget of the dialog (QWidget)
-        @return generated dialog (UMLDialog)
+        try:
+            # step 1: check version
+            linenum = 0
+            key, value = lines[linenum].split(": ", 1)
+            if key.strip() != "version" or value.strip() not in UMLDialog.FileVersions:
+                self.__showInvalidDataMessage(filename, linenum)
+                return False
+            else:
+                version = value
+            
+            # step 2: extract diagram type
+            linenum += 1
+            key, value = lines[linenum].split(": ", 1)
+            if key.strip() != "diagram_type":
+                self.__showInvalidDataMessage(filename, linenum)
+                return False
+            try:
+                self.__diagramType = int(value.strip().split(None, 1)[0])
+            except ValueError:
+                self.__showInvalidDataMessage(filename, linenum)
+                return False
+            self.scene.clear()
+            self.builder = self.__diagramBuilder(self.__diagramType, "")
+            
+            # step 3: extract scene size
+            linenum += 1
+            key, value = lines[linenum].split(": ", 1)
+            if key.strip() != "scene_size":
+                self.__showInvalidDataMessage(filename, linenum)
+                return False
+            try:
+                width, height = [float(v.strip()) for v in value.split(";")]
+            except ValueError:
+                self.__showInvalidDataMessage(filename, linenum)
+                return False
+            self.umlView.setSceneSize(width, height)
+            
+            # step 4: extract builder data if available
+            linenum += 1
+            key, value = lines[linenum].split(": ", 1)
+            if key.strip() == "builder_data":
+                ok = self.builder.parsePersistenceData(version, value)
+                if not ok:
+                    self.__showInvalidDataMessage(filename, linenum)
+                    return False
+                linenum += 1
+            
+            # step 5: extract the graphics items
+            ok, vlinenum = self.umlView.parsePersistenceData(version, lines[linenum:])
+            if not ok:
+                self.__showInvalidDataMessage(filename, linenum + vlinenum)
+                return False
+        
+        except IndexError:
+            self.__showInvalidDataMessage(filename)
+            return False
+        
+        # everything worked fine, so remember the file name
+        self.__fileName = filename
+        return True
+    
+    def __showInvalidDataMessage(self, filename, linenum=-1):
         """
-        # TODO: implement this
-        return None
+        Private slot to show a message dialog indicating an invalid data file.
+        
+        @param filename name of the file containing the invalid data (string)
+        @param linenum number of the invalid line (integer)
+        """
+        if linenum < 0:
+            msg = self.trUtf8("""<p>The file <b>{0}</b> does not contain"""
+                               """ valid data.</p>""").format(filename)
+        else:
+            msg = self.trUtf8("""<p>The file <b>{0}</b> does not contain"""
+                               """ valid data.</p><p>Invalid line: {1}</p>"""
+                              ).format(filename, linenum + 1)
+        E5MessageBox.critical(self, self.trUtf8("Load Diagram"), msg)
--- a/Graphics/UMLGraphicsView.py	Sun Sep 09 19:38:07 2012 +0200
+++ b/Graphics/UMLGraphicsView.py	Mon Sep 10 18:42:28 2012 +0200
@@ -16,6 +16,9 @@
 
 from .UMLItem import UMLItem
 from .AssociationItem import AssociationItem
+from .ClassItem import ClassItem
+from .ModuleItem import ModuleItem
+from .PackageItem import PackageItem
 from .UMLSceneSizeDialog import UMLSceneSizeDialog
 from .ZoomDialog import ZoomDialog
 
@@ -603,11 +606,52 @@
         
         return lines
     
-    def parsePersistenceData(self, data):
+    def parsePersistenceData(self, version, data):
         """
         Public method to parse persisted data.
         
-        @param dat persisted data to be parsed (string)
+        @param version version of the data (string)
+        @param data persisted data to be parsed (list of string)
+        @return tuple of flag indicating success (boolean) and faulty line
+            number (integer)
         """
-        # TODO: implement this
-        return
+        umlItems = {}
+        
+        if not data[0].startswith("diagram_name:"):
+            return False, 0
+        self.diagramName = data[0].split(": ", 1)[1].strip()
+        
+        linenum = 0
+        for line in data[1:]:
+            linenum += 1
+            if not line.startswith(("item:", "association:")):
+                return False, linenum
+            
+            key, value = line.split(": ", 1)
+            if key == "item":
+                id, x, y, itemType, itemData = value.split(", ", 4)
+                try:
+                    id = int(id.split("=", 1)[1].strip())
+                    x = float(x.split("=", 1)[1].strip())
+                    y = float(y.split("=", 1)[1].strip())
+                    itemType = itemType.split("=", 1)[1].strip()
+                    if itemType == ClassItem.ItemType:
+                        itm = ClassItem(x=x, y=y, scene=self.scene())
+                    elif itemType == ModuleItem.ItemType:
+                        itm = ModuleItem(x=x, y=y, scene=self.scene())
+                    elif itemType == PackageItem.ItemType:
+                        itm = PackageItem(x=x, y=y, scene=self.scene())
+                    itm.setId(id)
+                    umlItems[id] = itm
+                    if not itm.parseItemDataString(version, itemData):
+                        return False, linenum
+                except ValueError:
+                    return False, linenum
+            elif key == "association":
+                srcId, dstId, assocType, topToBottom = \
+                    AssociationItem.parseAssociationItemDataString(value.strip())
+                assoc = AssociationItem(umlItems[srcId], umlItems[dstId],
+                    assocType, topToBottom)
+                self.scene().addItem(assoc)
+        
+        return True, -1
--- a/Graphics/UMLItem.py	Sun Sep 09 19:38:07 2012 +0200
+++ b/Graphics/UMLItem.py	Mon Sep 10 18:42:28 2012 +0200
@@ -184,10 +184,12 @@
         """
         return ""
     
-    def parseItemDataString(self, data):
+    def parseItemDataString(self, version, data):
         """
         Public method to parse the given persistence data.
         
+        @param version version of the data (string)
         @param data persisted data to be parsed (string)
+        @return flag indicating success (boolean)
         """
-        pass
+        return True
--- a/Project/Project.py	Sun Sep 09 19:38:07 2012 +0200
+++ b/Project/Project.py	Mon Sep 10 18:42:28 2012 +0200
@@ -233,6 +233,7 @@
         self.codecoverage = None
         self.profiledata = None
         self.applicationDiagram = None
+        self.loadedDiagram = None
         
     def __initProjectTypes(self):
         """
@@ -2494,6 +2495,7 @@
         self.codecoverage       and self.codecoverage.close()
         self.profiledata        and self.profiledata.close()
         self.applicationDiagram and self.applicationDiagram.close()
+        self.loadedDiagram      and self.loadedDiagram.close()
         
     def closeProject(self, reopen=False, noSave=False):
         """
@@ -3251,9 +3253,11 @@
         self.codeProfileAct.triggered[()].connect(self.__showProfileData)
         self.actions.append(self.codeProfileAct)
 
+        self.graphicsGrp = createActionGroup(self)
+
         self.applicationDiagramAct = E5Action(self.trUtf8('Application Diagram'),
                 self.trUtf8('&Application Diagram...'), 0, 0,
-                self.chkGrp, 'project_application_diagram')
+                self.graphicsGrp, 'project_application_diagram')
         self.applicationDiagramAct.setStatusTip(
             self.trUtf8('Show a diagram of the project.'))
         self.applicationDiagramAct.setWhatsThis(self.trUtf8(
@@ -3263,6 +3267,18 @@
         self.applicationDiagramAct.triggered[()].connect(self.handleApplicationDiagram)
         self.actions.append(self.applicationDiagramAct)
 
+        self.loadDiagramAct = E5Action(self.trUtf8('Load Diagram'),
+                self.trUtf8('&Load Diagram...'), 0, 0,
+                self.graphicsGrp, 'project_load_diagram')
+        self.loadDiagramAct.setStatusTip(
+            self.trUtf8('Load a diagram from file.'))
+        self.loadDiagramAct.setWhatsThis(self.trUtf8(
+            """<b>Load Diagram...</b>"""
+            """<p>This loads a diagram from file.</p>"""
+        ))
+        self.loadDiagramAct.triggered[()].connect(self.__loadDiagram)
+        self.actions.append(self.loadDiagramAct)
+
         self.pluginGrp = createActionGroup(self)
 
         self.pluginPkgListAct = E5Action(self.trUtf8('Create Package List'),
@@ -3378,6 +3394,8 @@
         # build the diagrams menu
         self.graphicsMenu.setTearOffEnabled(True)
         self.graphicsMenu.addAction(self.applicationDiagramAct)
+        self.graphicsMenu.addSeparator()
+        self.graphicsMenu.addAction(self.loadDiagramAct)
         
         # build the session menu
         self.sessionMenu.setTearOffEnabled(True)
@@ -3988,6 +4006,16 @@
                                             self.parent(), noModules=not res)
         self.applicationDiagram.show()
     
+    def __loadDiagram(self):
+        """
+        Private slot to load a diagram from file.
+        """
+        self.loadedDiagram = None
+        loadedDiagram = UMLDialog(UMLDialog.NoDiagram, self, parent=self.parent())
+        if loadedDiagram.load():
+            self.loadedDiagram = loadedDiagram
+            self.loadedDiagram.show(fromFile=True)
+    
     #########################################################################
     ## Below is the interface to the VCS monitor thread
     #########################################################################
--- a/Project/ProjectSourcesBrowser.py	Sun Sep 09 19:38:07 2012 +0200
+++ b/Project/ProjectSourcesBrowser.py	Mon Sep 10 18:42:28 2012 +0200
@@ -31,6 +31,7 @@
 from .NewPythonPackageDialog import NewPythonPackageDialog
 
 import Utilities
+import UI.PixmapCache
 
 
 class ProjectSourcesBrowser(ProjectBaseBrowser):
@@ -78,6 +79,7 @@
         self.importsDiagram = None
         self.packageDiagram = None
         self.applicationDiagram = None
+        self.loadedDiagram = None
         
     def __closeAllWindows(self):
         """
@@ -90,6 +92,7 @@
         self.importsDiagram     and self.importsDiagram.close()
         self.packageDiagram     and self.packageDiagram.close()
         self.applicationDiagram and self.applicationDiagram.close()
+        self.loadedDiagram      and self.loadedDiagram.close()
         
     def _projectClosed(self):
         """
@@ -134,6 +137,9 @@
             self.trUtf8("Imports Diagram..."), self.__showImportsDiagram)
         self.graphicsMenu.addAction(
             self.trUtf8("Application Diagram..."), self.__showApplicationDiagram)
+        self.graphicsMenu.addSeparator()
+        self.graphicsMenu.addAction(UI.PixmapCache.getIcon("open.png"),
+            self.trUtf8("Load Diagram..."), self.__loadDiagram)
         self.graphicsMenu.aboutToShow.connect(self.__showContextMenuGraphics)
         
         self.unittestAction = self.sourceMenu.addAction(
@@ -287,6 +293,9 @@
             self.__showPackageDiagram)
         self.graphicsMenu.addAction(self.trUtf8("Application Diagram..."),
             self.__showApplicationDiagram)
+        self.graphicsMenu.addSeparator()
+        self.graphicsMenu.addAction(UI.PixmapCache.getIcon("fileOpen.png"),
+            self.trUtf8("Load Diagram..."), self.__loadDiagram)
         
         self.sourceMenu.addSeparator()
         act = self.sourceMenu.addAction(self.trUtf8('Rename file'), self._renameFile)
@@ -908,3 +917,13 @@
         self.applicationDiagram = UMLDialog(UMLDialog.ApplicationDiagram, self.project,
                                             self, noModules=not res)
         self.applicationDiagram.show()
+    
+    def __loadDiagram(self):
+        """
+        Private slot to load a diagram from file.
+        """
+        self.loadedDiagram = None
+        loadedDiagram = UMLDialog(UMLDialog.NoDiagram, self.project, parent=self)
+        if loadedDiagram.load():
+            self.loadedDiagram = loadedDiagram
+            self.loadedDiagram.show(fromFile=True)
--- a/QScintilla/Editor.py	Sun Sep 09 19:38:07 2012 +0200
+++ b/QScintilla/Editor.py	Mon Sep 10 18:42:28 2012 +0200
@@ -788,6 +788,9 @@
         self.applicationDiagramMenuAct = \
             menu.addAction(self.trUtf8('Application Diagram...'),
                 self.__showApplicationDiagram)
+        menu.addSeparator()
+        menu.addAction(UI.PixmapCache.getIcon("open.png"),
+            self.trUtf8("Load Diagram..."), self.__loadDiagram)
         
         menu.aboutToShow.connect(self.__showContextMenuGraphics)
         
@@ -5848,6 +5851,17 @@
                                             self, noModules=not res)
         self.applicationDiagram.show()
     
+    def __loadDiagram(self):
+        """
+        Private slot to load a diagram from file.
+        """
+        from Graphics.UMLDialog import UMLDialog
+        self.loadedDiagram = UMLDialog(UMLDialog.NoDiagram, self.project, parent=self)
+        if self.loadedDiagram.load():
+            self.loadedDiagram.show(fromFile=True)
+        else:
+            self.loadedDiagram = None
+    
     #######################################################################
     ## Typing aids related methods below
     #######################################################################

eric ide

mercurial