Merged with default branch to prepare release 21.6. maintenance release-21.06

Thu, 03 Jun 2021 11:39:23 +0200

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Thu, 03 Jun 2021 11:39:23 +0200
branch
maintenance
changeset 8400
b3eefd7e58d1
parent 8274
197414ba11cc (current diff)
parent 8397
40b5069e9f4c (diff)
child 8401
832e9474cf77

Merged with default branch to prepare release 21.6.

docs/changelog file | annotate | diff | comparison | revisions
eric6/APIs/Python3/eric6.api file | annotate | diff | comparison | revisions
eric6/DebugClients/Python/DebugClientBase.py file | annotate | diff | comparison | revisions
eric6/Debugger/DebugServer.py file | annotate | diff | comparison | revisions
eric6/Debugger/DebugUI.py file | annotate | diff | comparison | revisions
eric6/Documentation/Help/source.qch file | annotate | diff | comparison | revisions
eric6/Documentation/Help/source.qhp file | annotate | diff | comparison | revisions
eric6/Globals/__init__.py file | annotate | diff | comparison | revisions
eric6/Graphics/ApplicationDiagramBuilder.py file | annotate | diff | comparison | revisions
eric6/Graphics/ImportsDiagramBuilder.py file | annotate | diff | comparison | revisions
eric6/Graphics/PackageDiagramBuilder.py file | annotate | diff | comparison | revisions
eric6/Graphics/UMLClassDiagramBuilder.py file | annotate | diff | comparison | revisions
eric6/Graphics/UMLDialog.py file | annotate | diff | comparison | revisions
eric6/Graphics/UMLGraphicsView.py file | annotate | diff | comparison | revisions
eric6/PluginManager/PluginManager.py file | annotate | diff | comparison | revisions
eric6/Plugins/VcsPlugins/vcsMercurial/hg.py file | annotate | diff | comparison | revisions
eric6/Plugins/WizardPlugins/FileDialogWizard/FileDialogWizardDialog.py file | annotate | diff | comparison | revisions
eric6/Preferences/__init__.py file | annotate | diff | comparison | revisions
eric6/Project/Project.py file | annotate | diff | comparison | revisions
eric6/PyUnit/UnittestDialog.py file | annotate | diff | comparison | revisions
eric6/QScintilla/Editor.py file | annotate | diff | comparison | revisions
eric6/QScintilla/Lexers/__init__.py file | annotate | diff | comparison | revisions
eric6/QScintilla/MiniEditor.py file | annotate | diff | comparison | revisions
eric6/Tasks/TaskViewer.py file | annotate | diff | comparison | revisions
eric6/UI/BrowserModel.py file | annotate | diff | comparison | revisions
eric6/UI/UserInterface.py file | annotate | diff | comparison | revisions
eric6/Utilities/BackgroundClient.py file | annotate | diff | comparison | revisions
eric6/Utilities/BackgroundService.py file | annotate | diff | comparison | revisions
eric6/Utilities/ModuleParser.py file | annotate | diff | comparison | revisions
eric6/Utilities/__init__.py file | annotate | diff | comparison | revisions
eric6/ViewManager/ViewManager.py file | annotate | diff | comparison | revisions
eric6/WebBrowser/Sync/FtpSyncHandler.py file | annotate | diff | comparison | revisions
eric6/i18n/eric6_cs.ts file | annotate | diff | comparison | revisions
eric6/i18n/eric6_de.qm file | annotate | diff | comparison | revisions
eric6/i18n/eric6_de.ts file | annotate | diff | comparison | revisions
eric6/i18n/eric6_empty.ts file | annotate | diff | comparison | revisions
eric6/i18n/eric6_en.ts file | annotate | diff | comparison | revisions
eric6/i18n/eric6_es.qm file | annotate | diff | comparison | revisions
eric6/i18n/eric6_es.ts file | annotate | diff | comparison | revisions
eric6/i18n/eric6_fr.ts file | annotate | diff | comparison | revisions
eric6/i18n/eric6_it.ts file | annotate | diff | comparison | revisions
eric6/i18n/eric6_pt.ts file | annotate | diff | comparison | revisions
eric6/i18n/eric6_ru.qm file | annotate | diff | comparison | revisions
eric6/i18n/eric6_ru.ts file | annotate | diff | comparison | revisions
eric6/i18n/eric6_tr.ts file | annotate | diff | comparison | revisions
eric6/i18n/eric6_zh_CN.ts file | annotate | diff | comparison | revisions
scripts/install.py file | annotate | diff | comparison | revisions
--- a/.hgignore	Sat May 01 14:27:38 2021 +0200
+++ b/.hgignore	Thu Jun 03 11:39:23 2021 +0200
@@ -2,6 +2,7 @@
 glob:_eric5project
 glob:.eric6project
 glob:_eric6project
+glob:.eric7project
 glob:.ropeproject
 glob:_ropeproject
 glob:.directory
--- a/docs/changelog	Sat May 01 14:27:38 2021 +0200
+++ b/docs/changelog	Thu Jun 03 11:39:23 2021 +0200
@@ -1,5 +1,19 @@
 Change Log
 ----------
+Version 21.6:
+- bug fixes
+- Tasks
+  -- made the task properties dialog adapt to the task kind
+  -- added code to get typed manual tasks
+- UML Diagrams
+  -- extended the class items to show class attributes
+  -- added code to load a saved UML diagram via the file browser or
+     the project others browser
+  -- improved the diagram layout of the Import Diagram and the
+     Application Diagram
+  -- added code to save and load diagrams as JSON files
+  -- changed print code
+
 Version 21.5:
 - bug fixes
 - Code Style Checker
--- a/eric6.epj	Sat May 01 14:27:38 2021 +0200
+++ b/eric6.epj	Thu Jun 03 11:39:23 2021 +0200
@@ -2275,7 +2275,9 @@
       "eric6/Plugins/CheckerPlugins/CodeStyleChecker/Simplify/SimplifyNodeVisitor.py",
       "eric6/Plugins/CheckerPlugins/CodeStyleChecker/Annotations/AnnotationsFunctionVisitor.py",
       "eric6/Plugins/CheckerPlugins/CodeStyleChecker/Annotations/AnnotationsEnums.py",
-      "eric6/Plugins/CheckerPlugins/CodeStyleChecker/Annotations/AnnotationsCheckerDefaults.py"
+      "eric6/Plugins/CheckerPlugins/CodeStyleChecker/Annotations/AnnotationsCheckerDefaults.py",
+      "eric6/E5Network/E5JsonClient.py",
+      "eric6/E5Network/E5JsonServer.py"
     ],
     "SPELLEXCLUDES": "Dictionaries/excludes.dic",
     "SPELLLANGUAGE": "en_US",
--- a/eric6/APIs/Python3/eric6.api	Sat May 01 14:27:38 2021 +0200
+++ b/eric6/APIs/Python3/eric6.api	Thu Jun 03 11:39:23 2021 +0200
@@ -1654,18 +1654,18 @@
 eric6.E5Gui.E5ZoomWidget.E5ZoomWidget?1(outPix, inPix, resetPix, parent=None)
 eric6.E5Network.E5Ftp.E5Ftp.connect?4(host="", port=0, timeout=-999)
 eric6.E5Network.E5Ftp.E5Ftp.login?4(user="", password="", acct="")
-eric6.E5Network.E5Ftp.E5Ftp.setProxy?4(proxyType=E5FtpProxyType.NoProxy, proxyHost="", proxyPort=ftplib.FTP_PORT, proxyUser="", proxyPassword="", proxyAccount="")
+eric6.E5Network.E5Ftp.E5Ftp.setProxy?4(proxyType=E5FtpProxyType.NO_PROXY, proxyHost="", proxyPort=ftplib.FTP_PORT, proxyUser="", proxyPassword="", proxyAccount="")
 eric6.E5Network.E5Ftp.E5Ftp.setProxyAuthentication?4(proxyUser="", proxyPassword="", proxyAccount="")
-eric6.E5Network.E5Ftp.E5Ftp?1(host="", user="", password="", acct="", proxyType=E5FtpProxyType.NoProxy, proxyHost="", proxyPort=ftplib.FTP_PORT, proxyUser="", proxyPassword="", proxyAccount="", timeout=_GLOBAL_DEFAULT_TIMEOUT)
-eric6.E5Network.E5Ftp.E5FtpProxyType.AuthResp?7
-eric6.E5Network.E5Ftp.E5FtpProxyType.Bluecoat?7
-eric6.E5Network.E5Ftp.E5FtpProxyType.NoProxy?7
-eric6.E5Network.E5Ftp.E5FtpProxyType.NonAuthorizing?7
-eric6.E5Network.E5Ftp.E5FtpProxyType.Open?7
-eric6.E5Network.E5Ftp.E5FtpProxyType.ProxyuserAtServer?7
-eric6.E5Network.E5Ftp.E5FtpProxyType.Site?7
-eric6.E5Network.E5Ftp.E5FtpProxyType.UserAtProxyuserAtServer?7
-eric6.E5Network.E5Ftp.E5FtpProxyType.UserAtServer?7
+eric6.E5Network.E5Ftp.E5Ftp?1(host="", user="", password="", acct="", proxyType=E5FtpProxyType.NO_PROXY, proxyHost="", proxyPort=ftplib.FTP_PORT, proxyUser="", proxyPassword="", proxyAccount="", timeout=_GLOBAL_DEFAULT_TIMEOUT)
+eric6.E5Network.E5Ftp.E5FtpProxyType.AUTH_RESP?7
+eric6.E5Network.E5Ftp.E5FtpProxyType.BLUECOAT?7
+eric6.E5Network.E5Ftp.E5FtpProxyType.NON_AUTHORIZING?7
+eric6.E5Network.E5Ftp.E5FtpProxyType.NO_PROXY?7
+eric6.E5Network.E5Ftp.E5FtpProxyType.OPEN?7
+eric6.E5Network.E5Ftp.E5FtpProxyType.PROXYUSER_SERVER?7
+eric6.E5Network.E5Ftp.E5FtpProxyType.SITE?7
+eric6.E5Network.E5Ftp.E5FtpProxyType.USER_PROXYUSER_SERVER?7
+eric6.E5Network.E5Ftp.E5FtpProxyType.USER_SERVER?7
 eric6.E5Network.E5GoogleMail.E5GoogleMail.sendMessage?4(message)
 eric6.E5Network.E5GoogleMail.E5GoogleMail.sendResult?7
 eric6.E5Network.E5GoogleMail.E5GoogleMail?1(parent=None)
@@ -1680,6 +1680,18 @@
 eric6.E5Network.E5GoogleMailHelpers.TOKEN_FILE?7
 eric6.E5Network.E5GoogleMailHelpers.getInstallCommand?4()
 eric6.E5Network.E5GoogleMailHelpers.isClientSecretFileAvailable?4()
+eric6.E5Network.E5JsonClient.E5JsonClient.handleCall?4(method, params)
+eric6.E5Network.E5JsonClient.E5JsonClient.run?4()
+eric6.E5Network.E5JsonClient.E5JsonClient.sendJson?4(command, params)
+eric6.E5Network.E5JsonClient.E5JsonClient?1(host, port, idString="")
+eric6.E5Network.E5JsonServer.E5JsonServer.connectionNames?4()
+eric6.E5Network.E5JsonServer.E5JsonServer.handleCall?4(method, params)
+eric6.E5Network.E5JsonServer.E5JsonServer.handleNewConnection?4()
+eric6.E5Network.E5JsonServer.E5JsonServer.sendJson?4(command, params, flush=False, idString="")
+eric6.E5Network.E5JsonServer.E5JsonServer.startClient?4(interpreter, clientScript, clientArgs, idString="", environment=None)
+eric6.E5Network.E5JsonServer.E5JsonServer.stopAllClients?4()
+eric6.E5Network.E5JsonServer.E5JsonServer.stopClient?4(idString="")
+eric6.E5Network.E5JsonServer.E5JsonServer?1(name="", multiplex=False, parent=None)
 eric6.E5Network.E5NetworkHeaderDetailsDialog.E5NetworkHeaderDetailsDialog.setData?4(name, value)
 eric6.E5Network.E5NetworkHeaderDetailsDialog.E5NetworkHeaderDetailsDialog?1(parent=None)
 eric6.E5Network.E5NetworkProxyFactory.E5NetworkProxyFactory.queryProxy?4(query)
@@ -1921,7 +1933,8 @@
 eric6.Globals.getInstallInfoFilePath?4()
 eric6.Globals.getPyQt5ModulesDirectory?4()
 eric6.Globals.getPyQtToolsPath?4(version=5)
-eric6.Globals.getPythonModulesDirectory?4()
+eric6.Globals.getPythonLibraryDirectory?4()
+eric6.Globals.getPythonModulesDirectory?7
 eric6.Globals.getQtBinariesPath?4()
 eric6.Globals.getWebBrowserSupport?4()
 eric6.Globals.isGnomeDesktop?4()
@@ -1951,11 +1964,15 @@
 eric6.Globals.toList?4(value)
 eric6.Globals.versionToTuple?4(version, length=3)
 eric6.Graphics.ApplicationDiagramBuilder.ApplicationDiagramBuilder.buildDiagram?4()
+eric6.Graphics.ApplicationDiagramBuilder.ApplicationDiagramBuilder.fromDict?4(version, data)
 eric6.Graphics.ApplicationDiagramBuilder.ApplicationDiagramBuilder.getPersistenceData?4()
 eric6.Graphics.ApplicationDiagramBuilder.ApplicationDiagramBuilder.parsePersistenceData?4(version, data)
+eric6.Graphics.ApplicationDiagramBuilder.ApplicationDiagramBuilder.toDict?4()
 eric6.Graphics.ApplicationDiagramBuilder.ApplicationDiagramBuilder?1(dialog, view, project, noModules=False)
 eric6.Graphics.AssociationItem.AssociationItem.buildAssociationItemDataString?4()
+eric6.Graphics.AssociationItem.AssociationItem.fromDict?4(data, umlItems, colors=None)
 eric6.Graphics.AssociationItem.AssociationItem.parseAssociationItemDataString?4(data)
+eric6.Graphics.AssociationItem.AssociationItem.toDict?4()
 eric6.Graphics.AssociationItem.AssociationItem.unassociate?4()
 eric6.Graphics.AssociationItem.AssociationItem.widgetMoved?4()
 eric6.Graphics.AssociationItem.AssociationItem?1(itemA, itemB, assocType=AssociationType.NORMAL, topToBottom=False, colors=None, parent=None)
@@ -1974,42 +1991,54 @@
 eric6.Graphics.AssociationItem.AssociationType.NORMAL?7
 eric6.Graphics.ClassItem.ClassItem.ItemType?7
 eric6.Graphics.ClassItem.ClassItem.buildItemDataString?4()
+eric6.Graphics.ClassItem.ClassItem.fromDict?4(data, colors=None)
 eric6.Graphics.ClassItem.ClassItem.isExternal?4()
 eric6.Graphics.ClassItem.ClassItem.paint?4(painter, option, widget=None)
 eric6.Graphics.ClassItem.ClassItem.parseItemDataString?4(version, data)
 eric6.Graphics.ClassItem.ClassItem.setModel?4(model)
+eric6.Graphics.ClassItem.ClassItem.toDict?4()
 eric6.Graphics.ClassItem.ClassItem?1(model=None, external=False, x=0, y=0, rounded=False, noAttrs=False, colors=None, parent=None, scene=None)
-eric6.Graphics.ClassItem.ClassModel.addAttribute?4(attribute)
+eric6.Graphics.ClassItem.ClassModel.addClassAttribute?4(attribute)
+eric6.Graphics.ClassItem.ClassModel.addInstanceAttribute?4(attribute)
 eric6.Graphics.ClassItem.ClassModel.addMethod?4(method)
-eric6.Graphics.ClassItem.ClassModel.getAttributes?4()
+eric6.Graphics.ClassItem.ClassModel.getClassAttributes?4()
+eric6.Graphics.ClassItem.ClassModel.getInstanceAttributes?4()
 eric6.Graphics.ClassItem.ClassModel.getMethods?4()
-eric6.Graphics.ClassItem.ClassModel?1(name, methods=None, attributes=None)
+eric6.Graphics.ClassItem.ClassModel?1(name, methods=None, instanceAttributes=None, classAttributes=None)
 eric6.Graphics.GraphicsUtilities._buildChildrenLists?5(routes)
 eric6.Graphics.GraphicsUtilities.sort?4(nodes, routes, noRecursion=False)
 eric6.Graphics.ImportsDiagramBuilder.ImportsDiagramBuilder.buildDiagram?4()
+eric6.Graphics.ImportsDiagramBuilder.ImportsDiagramBuilder.fromDict?4(version, data)
 eric6.Graphics.ImportsDiagramBuilder.ImportsDiagramBuilder.getPersistenceData?4()
 eric6.Graphics.ImportsDiagramBuilder.ImportsDiagramBuilder.initialize?4()
 eric6.Graphics.ImportsDiagramBuilder.ImportsDiagramBuilder.parsePersistenceData?4(version, data)
+eric6.Graphics.ImportsDiagramBuilder.ImportsDiagramBuilder.toDict?4()
 eric6.Graphics.ImportsDiagramBuilder.ImportsDiagramBuilder?1(dialog, view, project, package, showExternalImports=False)
 eric6.Graphics.ModuleItem.ModuleItem.ItemType?7
 eric6.Graphics.ModuleItem.ModuleItem.buildItemDataString?4()
+eric6.Graphics.ModuleItem.ModuleItem.fromDict?4(data, colors=None)
 eric6.Graphics.ModuleItem.ModuleItem.paint?4(painter, option, widget=None)
 eric6.Graphics.ModuleItem.ModuleItem.parseItemDataString?4(version, data)
 eric6.Graphics.ModuleItem.ModuleItem.setModel?4(model)
+eric6.Graphics.ModuleItem.ModuleItem.toDict?4()
 eric6.Graphics.ModuleItem.ModuleItem?1(model=None, x=0, y=0, rounded=False, colors=None, parent=None, scene=None)
 eric6.Graphics.ModuleItem.ModuleModel.addClass?4(classname)
 eric6.Graphics.ModuleItem.ModuleModel.getClasses?4()
 eric6.Graphics.ModuleItem.ModuleModel?1(name, classlist=None)
 eric6.Graphics.PackageDiagramBuilder.PackageDiagramBuilder.buildDiagram?4()
+eric6.Graphics.PackageDiagramBuilder.PackageDiagramBuilder.fromDict?4(version, data)
 eric6.Graphics.PackageDiagramBuilder.PackageDiagramBuilder.getPersistenceData?4()
 eric6.Graphics.PackageDiagramBuilder.PackageDiagramBuilder.initialize?4()
 eric6.Graphics.PackageDiagramBuilder.PackageDiagramBuilder.parsePersistenceData?4(version, data)
+eric6.Graphics.PackageDiagramBuilder.PackageDiagramBuilder.toDict?4()
 eric6.Graphics.PackageDiagramBuilder.PackageDiagramBuilder?1(dialog, view, project, package, noAttrs=False)
 eric6.Graphics.PackageItem.PackageItem.ItemType?7
 eric6.Graphics.PackageItem.PackageItem.buildItemDataString?4()
+eric6.Graphics.PackageItem.PackageItem.fromDict?4(data, colors=None)
 eric6.Graphics.PackageItem.PackageItem.paint?4(painter, option, widget=None)
 eric6.Graphics.PackageItem.PackageItem.parseItemDataString?4(version, data)
 eric6.Graphics.PackageItem.PackageItem.setModel?4(model)
+eric6.Graphics.PackageItem.PackageItem.toDict?4()
 eric6.Graphics.PackageItem.PackageItem?1(model=None, x=0, y=0, rounded=False, noModules=False, colors=None, parent=None, scene=None)
 eric6.Graphics.PackageItem.PackageModel.addModule?4(modulename)
 eric6.Graphics.PackageItem.PackageModel.getModules?4()
@@ -2030,29 +2059,37 @@
 eric6.Graphics.SvgDiagram.SvgDiagram.wheelEvent?4(evt)
 eric6.Graphics.SvgDiagram.SvgDiagram?1(svgFile, parent=None, name=None)
 eric6.Graphics.UMLClassDiagramBuilder.UMLClassDiagramBuilder.buildDiagram?4()
+eric6.Graphics.UMLClassDiagramBuilder.UMLClassDiagramBuilder.fromDict?4(version, data)
 eric6.Graphics.UMLClassDiagramBuilder.UMLClassDiagramBuilder.getPersistenceData?4()
 eric6.Graphics.UMLClassDiagramBuilder.UMLClassDiagramBuilder.initialize?4()
 eric6.Graphics.UMLClassDiagramBuilder.UMLClassDiagramBuilder.parsePersistenceData?4(version, data)
+eric6.Graphics.UMLClassDiagramBuilder.UMLClassDiagramBuilder.toDict?4()
 eric6.Graphics.UMLClassDiagramBuilder.UMLClassDiagramBuilder?1(dialog, view, project, file, noAttrs=False)
 eric6.Graphics.UMLDiagramBuilder.UMLDiagramBuilder.buildDiagram?4()
+eric6.Graphics.UMLDiagramBuilder.UMLDiagramBuilder.buildErrorMessage?4(msg)
+eric6.Graphics.UMLDiagramBuilder.UMLDiagramBuilder.fromDict?4(version, data)
 eric6.Graphics.UMLDiagramBuilder.UMLDiagramBuilder.getPersistenceData?4()
 eric6.Graphics.UMLDiagramBuilder.UMLDiagramBuilder.initialize?4()
 eric6.Graphics.UMLDiagramBuilder.UMLDiagramBuilder.parsePersistenceData?4(version, data)
+eric6.Graphics.UMLDiagramBuilder.UMLDiagramBuilder.toDict?4()
 eric6.Graphics.UMLDiagramBuilder.UMLDiagramBuilder?1(dialog, view, project)
-eric6.Graphics.UMLDialog.UMLDialog.ApplicationDiagram?7
-eric6.Graphics.UMLDialog.UMLDialog.ClassDiagram?7
 eric6.Graphics.UMLDialog.UMLDialog.FileVersions?7
-eric6.Graphics.UMLDialog.UMLDialog.ImportsDiagram?7
-eric6.Graphics.UMLDialog.UMLDialog.NoDiagram?7
-eric6.Graphics.UMLDialog.UMLDialog.PackageDiagram?7
-eric6.Graphics.UMLDialog.UMLDialog.load?4()
+eric6.Graphics.UMLDialog.UMLDialog.JsonFileVersions?7
+eric6.Graphics.UMLDialog.UMLDialog.UMLDialogType2String?7
+eric6.Graphics.UMLDialog.UMLDialog.load?4(filename="")
 eric6.Graphics.UMLDialog.UMLDialog.show?4(fromFile=False)
 eric6.Graphics.UMLDialog.UMLDialog?1(diagramType, project, path="", parent=None, initBuilder=True, **kwargs)
+eric6.Graphics.UMLDialog.UMLDialogType.APPLICATION_DIAGRAM?7
+eric6.Graphics.UMLDialog.UMLDialogType.CLASS_DIAGRAM?7
+eric6.Graphics.UMLDialog.UMLDialogType.IMPORTS_DIAGRAM?7
+eric6.Graphics.UMLDialog.UMLDialogType.NO_DIAGRAM?7
+eric6.Graphics.UMLDialog.UMLDialogType.PACKAGE_DIAGRAM?7
 eric6.Graphics.UMLGraphicsView.UMLGraphicsView.autoAdjustSceneSize?4(limit=False)
 eric6.Graphics.UMLGraphicsView.UMLGraphicsView.event?4(evt)
 eric6.Graphics.UMLGraphicsView.UMLGraphicsView.filteredItems?4(items, itemType=UMLItem)
 eric6.Graphics.UMLGraphicsView.UMLGraphicsView.findItem?4(itemId)
 eric6.Graphics.UMLGraphicsView.UMLGraphicsView.findItemByName?4(name)
+eric6.Graphics.UMLGraphicsView.UMLGraphicsView.fromDict?4(version, data)
 eric6.Graphics.UMLGraphicsView.UMLGraphicsView.gestureEvent?4(evt)
 eric6.Graphics.UMLGraphicsView.UMLGraphicsView.getItemId?4()
 eric6.Graphics.UMLGraphicsView.UMLGraphicsView.getPersistenceData?4()
@@ -2066,12 +2103,15 @@
 eric6.Graphics.UMLGraphicsView.UMLGraphicsView.selectItem?4(item)
 eric6.Graphics.UMLGraphicsView.UMLGraphicsView.selectItems?4(items)
 eric6.Graphics.UMLGraphicsView.UMLGraphicsView.setDiagramName?4(name)
+eric6.Graphics.UMLGraphicsView.UMLGraphicsView.setLayoutActionsEnabled?4(enable)
+eric6.Graphics.UMLGraphicsView.UMLGraphicsView.toDict?4()
 eric6.Graphics.UMLGraphicsView.UMLGraphicsView.wheelEvent?4(evt)
 eric6.Graphics.UMLGraphicsView.UMLGraphicsView?1(scene, parent=None)
 eric6.Graphics.UMLItem.UMLItem.ItemType?7
 eric6.Graphics.UMLItem.UMLItem.addAssociation?4(assoc)
 eric6.Graphics.UMLItem.UMLItem.adjustAssociations?4()
 eric6.Graphics.UMLItem.UMLItem.buildItemDataString?4()
+eric6.Graphics.UMLItem.UMLItem.fromDict?4(data, colors=None)
 eric6.Graphics.UMLItem.UMLItem.getId?4()
 eric6.Graphics.UMLItem.UMLItem.getItemType?4()
 eric6.Graphics.UMLItem.UMLItem.getName?4()
@@ -2084,6 +2124,7 @@
 eric6.Graphics.UMLItem.UMLItem.setId?4(itemId)
 eric6.Graphics.UMLItem.UMLItem.setPos?4(x, y)
 eric6.Graphics.UMLItem.UMLItem.setSize?4(width, height)
+eric6.Graphics.UMLItem.UMLItem.toDict?4()
 eric6.Graphics.UMLItem.UMLItem?1(model=None, x=0, y=0, rounded=False, colors=None, parent=None)
 eric6.Graphics.UMLItem.UMLModel.getName?4()
 eric6.Graphics.UMLItem.UMLModel?1(name)
@@ -3052,7 +3093,8 @@
 eric6.PluginManager.PluginManager.PluginManager.isPluginLoaded?4(pluginName)
 eric6.PluginManager.PluginManager.PluginManager.isValidPluginName?4(pluginName)
 eric6.PluginManager.PluginManager.PluginManager.loadDocumentationSetPlugins?4()
-eric6.PluginManager.PluginManager.PluginManager.loadPlugin?4(name, directory, reload_=False)
+eric6.PluginManager.PluginManager.PluginManager.loadPlugin?4(name, directory, reload_=False, install=False)
+eric6.PluginManager.PluginManager.PluginManager.pipInstall?4(packages)
 eric6.PluginManager.PluginManager.PluginManager.pluginAboutToBeActivated?7
 eric6.PluginManager.PluginManager.PluginManager.pluginAboutToBeDeactivated?7
 eric6.PluginManager.PluginManager.PluginManager.pluginActivated?7
@@ -5328,6 +5370,7 @@
 eric6.Plugins.VcsPlugins.vcsMercurial.HgUserConfigHostMinimumProtocolDialog.HgUserConfigHostMinimumProtocolDialog.on_minimumProtocolComboBox_currentIndexChanged?4(index)
 eric6.Plugins.VcsPlugins.vcsMercurial.HgUserConfigHostMinimumProtocolDialog.HgUserConfigHostMinimumProtocolDialog?1(allowedProtocols, parent=None, host="", protocol="")
 eric6.Plugins.VcsPlugins.vcsMercurial.HgUtilities.getConfigPath?4()
+eric6.Plugins.VcsPlugins.vcsMercurial.HgUtilities.getHgExecutable?4()
 eric6.Plugins.VcsPlugins.vcsMercurial.HgUtilities.hgVersion?4(plugin)
 eric6.Plugins.VcsPlugins.vcsMercurial.HgUtilities.prepareProcess?4(proc, encoding="", language="")
 eric6.Plugins.VcsPlugins.vcsMercurial.HisteditExtension.HgHisteditCommitEditor.HgHisteditCommitEditor.on_buttonBox_accepted?4()
@@ -8916,13 +8959,6 @@
 eric6.Tasks.Task.Task.TaskType2ColorName?7
 eric6.Tasks.Task.Task.TaskType2IconName?7
 eric6.Tasks.Task.Task.TaskType2MarkersName?7
-eric6.Tasks.Task.Task.TypeDocu?7
-eric6.Tasks.Task.Task.TypeFixme?7
-eric6.Tasks.Task.Task.TypeNone?7
-eric6.Tasks.Task.Task.TypeNote?7
-eric6.Tasks.Task.Task.TypeTest?7
-eric6.Tasks.Task.Task.TypeTodo?7
-eric6.Tasks.Task.Task.TypeWarning?7
 eric6.Tasks.Task.Task.colorizeTask?4()
 eric6.Tasks.Task.Task.getFilename?4()
 eric6.Tasks.Task.Task.getLineno?4()
@@ -8937,8 +8973,19 @@
 eric6.Tasks.Task.Task.setPriority?4(priority)
 eric6.Tasks.Task.Task.setProjectTask?4(pt)
 eric6.Tasks.Task.Task.setSummary?4(summary)
+eric6.Tasks.Task.Task.setTaskType?4(taskType)
 eric6.Tasks.Task.Task.toDict?4()
-eric6.Tasks.Task.Task?1(summary, priority=1, filename="", lineno=0, completed=False, _time=0, isProjectTask=False, taskType=TypeTodo, project=None, description="", uid="", parentUid="")
+eric6.Tasks.Task.Task?1(summary, priority=TaskPriority.NORMAL, filename="", lineno=0, completed=False, _time=0, isProjectTask=False, taskType=TaskType.TODO, project=None, description="", uid="", parentUid="")
+eric6.Tasks.Task.TaskPriority.HIGH?7
+eric6.Tasks.Task.TaskPriority.LOW?7
+eric6.Tasks.Task.TaskPriority.NORMAL?7
+eric6.Tasks.Task.TaskType.DOCU?7
+eric6.Tasks.Task.TaskType.FIXME?7
+eric6.Tasks.Task.TaskType.NONE?7
+eric6.Tasks.Task.TaskType.NOTE?7
+eric6.Tasks.Task.TaskType.TEST?7
+eric6.Tasks.Task.TaskType.TODO?7
+eric6.Tasks.Task.TaskType.WARNING?7
 eric6.Tasks.TaskFilter.TaskFilter.hasActiveFilter?4()
 eric6.Tasks.TaskFilter.TaskFilter.setActive?4(enabled)
 eric6.Tasks.TaskFilter.TaskFilter.setFileNameFilter?4(filterStr)
@@ -8952,7 +8999,7 @@
 eric6.Tasks.TaskFilterConfigDialog.TaskFilterConfigDialog.configureTaskFilter?4(taskFilter)
 eric6.Tasks.TaskFilterConfigDialog.TaskFilterConfigDialog?1(taskFilter, parent=None)
 eric6.Tasks.TaskPropertiesDialog.TaskPropertiesDialog.getData?4()
-eric6.Tasks.TaskPropertiesDialog.TaskPropertiesDialog.setReadOnly?4()
+eric6.Tasks.TaskPropertiesDialog.TaskPropertiesDialog.isManualTaskMode?4()
 eric6.Tasks.TaskPropertiesDialog.TaskPropertiesDialog.setSubTaskMode?4(projectTask)
 eric6.Tasks.TaskPropertiesDialog.TaskPropertiesDialog?1(task=None, parent=None, projectOpen=False)
 eric6.Tasks.TaskViewer.ProjectTaskExtractionThread.requestInterrupt?4()
@@ -8960,8 +9007,8 @@
 eric6.Tasks.TaskViewer.ProjectTaskExtractionThread.scan?4(markers, files)
 eric6.Tasks.TaskViewer.ProjectTaskExtractionThread.taskFound?7
 eric6.Tasks.TaskViewer.ProjectTaskExtractionThread?1(parent=None)
-eric6.Tasks.TaskViewer.TaskViewer.addFileTask?4(summary, filename, lineno, taskType=Task.TypeTodo, description="")
-eric6.Tasks.TaskViewer.TaskViewer.addTask?4(summary, priority=1, filename="", lineno=0, completed=False, _time=0, isProjectTask=False, taskType=Task.TypeTodo, description="", uid="", parentTask=None)
+eric6.Tasks.TaskViewer.TaskViewer.addFileTask?4(summary, filename, lineno, taskType=TaskType.TODO, description="")
+eric6.Tasks.TaskViewer.TaskViewer.addTask?4(summary, priority=TaskPriority.NORMAL, filename="", lineno=0, completed=False, _time=0, isProjectTask=False, taskType=TaskType.TODO, description="", uid="", parentTask=None)
 eric6.Tasks.TaskViewer.TaskViewer.clearFileTasks?4(filename, conditionally=False)
 eric6.Tasks.TaskViewer.TaskViewer.clearProjectTasks?4(fileOnly=False)
 eric6.Tasks.TaskViewer.TaskViewer.clearTasks?4()
@@ -9134,6 +9181,7 @@
 eric6.UI.Browser.Browser.sourceFile?7
 eric6.UI.Browser.Browser.svgFile?7
 eric6.UI.Browser.Browser.trpreview?7
+eric6.UI.Browser.Browser.umlFile?7
 eric6.UI.Browser.Browser.unittestOpen?7
 eric6.UI.Browser.Browser.wantedItem?4(itm, filterList=None)
 eric6.UI.Browser.Browser?1(parent=None)
--- a/eric6/APIs/Python3/eric6.bas	Sat May 01 14:27:38 2021 +0200
+++ b/eric6/APIs/Python3/eric6.bas	Thu Jun 03 11:39:23 2021 +0200
@@ -187,11 +187,13 @@
 E5FileSaveConfirmDialog QDialog
 E5Ftp ftplib.FTP
 E5FtpProxyError ftplib.Error
+E5FtpProxyType enum.Enum
 E5GenericDiffHighlighter QSyntaxHighlighter
 E5GoogleMail QObject
 E5GoogleMailAuthBrowser QDialog
 E5GraphicsView QGraphicsView
 E5HorizontalToolBox E5TabWidget
+E5JsonServer QTcpServer
 E5Led QWidget
 E5LedType enum.Enum
 E5LineEdit QLineEdit
@@ -937,7 +939,9 @@
 TagError Exception
 Task QTreeWidgetItem
 TaskFilterConfigDialog QDialog Ui_TaskFilterConfigDialog
+TaskPriority enum.IntEnum
 TaskPropertiesDialog QDialog Ui_TaskPropertiesDialog
+TaskType enum.IntEnum
 TaskViewer QTreeWidget
 TasksFile QObject
 TasksPage ConfigurationPageBase Ui_TasksPage
@@ -975,6 +979,7 @@
 UMLClassDiagramBuilder UMLDiagramBuilder
 UMLDiagramBuilder QObject
 UMLDialog E5MainWindow
+UMLDialogType enum.Enum
 UMLGraphicsView E5GraphicsView
 UMLItem QGraphicsRectItem
 UMLSceneSizeDialog QDialog Ui_UMLSceneSizeDialog
--- a/eric6/DebugClients/Python/DebugClientBase.py	Sat May 01 14:27:38 2021 +0200
+++ b/eric6/DebugClients/Python/DebugClientBase.py	Thu Jun 03 11:39:23 2021 +0200
@@ -20,7 +20,6 @@
 import signal
 import time
 import types
-import importlib.util
 import fnmatch
 import contextlib
 
@@ -870,9 +869,7 @@
                         os.path.dirname(os.path.abspath(params["filename"]))
                     )
                     if params["filename"]:
-                        spec = importlib.util.spec_from_file_location(
-                            params["testname"], params["filename"])
-                        utModule = importlib.util.module_from_spec(spec)
+                        utModule = __import__(params["testname"])
                     else:
                         utModule = None
                     if params["failed"]:
@@ -1514,7 +1511,7 @@
             if scope:
                 varDict = self.debugMod.__dict__
             else:
-                scope = -1
+                scope = -2
         elif scope:
             varDict = f.f_globals
         elif f.f_globals is f.f_locals:
@@ -1522,7 +1519,7 @@
         else:
             varDict = f.f_locals
         
-        varlist = [] if scope == -1 else self.__formatVariablesList(
+        varlist = [] if scope < 0 else self.__formatVariablesList(
             varDict, scope, filterList)
         
         self.sendJsonCommand("ResponseVariables", {
--- a/eric6/Debugger/DebugServer.py	Sat May 01 14:27:38 2021 +0200
+++ b/eric6/Debugger/DebugServer.py	Thu Jun 03 11:39:23 2021 +0200
@@ -1743,8 +1743,8 @@
         """
         Public method to process the client variables info.
         
-        @param scope scope of the variables (-1 = empty global, 1 = global,
-            0 = local)
+        @param scope scope of the variables
+            (-2 = no frame found, -1 = empty locals, 1 = global, 0 = local)
         @type int
         @param variables the list of variables from the client
         @type list
--- a/eric6/Debugger/DebugUI.py	Sat May 01 14:27:38 2021 +0200
+++ b/eric6/Debugger/DebugUI.py	Thu Jun 03 11:39:23 2021 +0200
@@ -1372,8 +1372,9 @@
         @param debuggerId ID of the debugger backend
         @type str
         """
-        self.debugServer.remoteClientVariables(
-            debuggerId, 0, self.__localsVarFilterList)
+        if self.debugServer.isDebugging():
+            self.debugServer.remoteClientVariables(
+                debuggerId, 0, self.__localsVarFilterList)
     
     def __getClientVariables(self, debuggerId):
         """
@@ -1395,15 +1396,15 @@
         """
         Private method to write the clients variables to the user interface.
         
-        @param scope scope of the variables (-1 = empty locals, 1 = global,
-            0 = local)
+        @param scope scope of the variables
+            (-2 = no frame found, -1 = empty locals, 1 = global, 0 = local)
         @type int
         @param variables the list of variables from the client
         @type list
         @param debuggerId ID of the debugger backend
         @type str
         """
-        if debuggerId == self.getSelectedDebuggerId():
+        if debuggerId == self.getSelectedDebuggerId() and scope > -2:
             self.ui.activateDebugViewer()
             if scope > 0:
                 self.debugViewer.showVariables(variables, True)
Binary file eric6/Documentation/Help/source.qch has changed
--- a/eric6/Documentation/Help/source.qhp	Sat May 01 14:27:38 2021 +0200
+++ b/eric6/Documentation/Help/source.qhp	Thu Jun 03 11:39:23 2021 +0200
@@ -152,6 +152,8 @@
             <section title="eric6.E5Network.E5Ftp" ref="eric6.E5Network.E5Ftp.html" />
             <section title="eric6.E5Network.E5GoogleMail" ref="eric6.E5Network.E5GoogleMail.html" />
             <section title="eric6.E5Network.E5GoogleMailHelpers" ref="eric6.E5Network.E5GoogleMailHelpers.html" />
+            <section title="eric6.E5Network.E5JsonClient" ref="eric6.E5Network.E5JsonClient.html" />
+            <section title="eric6.E5Network.E5JsonServer" ref="eric6.E5Network.E5JsonServer.html" />
             <section title="eric6.E5Network.E5NetworkHeaderDetailsDialog" ref="eric6.E5Network.E5NetworkHeaderDetailsDialog.html" />
             <section title="eric6.E5Network.E5NetworkProxyFactory" ref="eric6.E5Network.E5NetworkProxyFactory.html" />
             <section title="eric6.E5Network.E5RFC6266" ref="eric6.E5Network.E5RFC6266.html" />
@@ -1776,11 +1778,15 @@
       <keyword name="ApplicationDiagramBuilder (Constructor)" id="ApplicationDiagramBuilder (Constructor)" ref="eric6.Graphics.ApplicationDiagramBuilder.html#ApplicationDiagramBuilder.__init__" />
       <keyword name="ApplicationDiagramBuilder (Module)" id="ApplicationDiagramBuilder (Module)" ref="eric6.Graphics.ApplicationDiagramBuilder.html" />
       <keyword name="ApplicationDiagramBuilder.__addPackage" id="ApplicationDiagramBuilder.__addPackage" ref="eric6.Graphics.ApplicationDiagramBuilder.html#ApplicationDiagramBuilder.__addPackage" />
+      <keyword name="ApplicationDiagramBuilder.__arrangeNodes" id="ApplicationDiagramBuilder.__arrangeNodes" ref="eric6.Graphics.ApplicationDiagramBuilder.html#ApplicationDiagramBuilder.__arrangeNodes" />
       <keyword name="ApplicationDiagramBuilder.__buildModulesDict" id="ApplicationDiagramBuilder.__buildModulesDict" ref="eric6.Graphics.ApplicationDiagramBuilder.html#ApplicationDiagramBuilder.__buildModulesDict" />
       <keyword name="ApplicationDiagramBuilder.__createAssociations" id="ApplicationDiagramBuilder.__createAssociations" ref="eric6.Graphics.ApplicationDiagramBuilder.html#ApplicationDiagramBuilder.__createAssociations" />
+      <keyword name="ApplicationDiagramBuilder.__findApplicationRoot" id="ApplicationDiagramBuilder.__findApplicationRoot" ref="eric6.Graphics.ApplicationDiagramBuilder.html#ApplicationDiagramBuilder.__findApplicationRoot" />
       <keyword name="ApplicationDiagramBuilder.buildDiagram" id="ApplicationDiagramBuilder.buildDiagram" ref="eric6.Graphics.ApplicationDiagramBuilder.html#ApplicationDiagramBuilder.buildDiagram" />
+      <keyword name="ApplicationDiagramBuilder.fromDict" id="ApplicationDiagramBuilder.fromDict" ref="eric6.Graphics.ApplicationDiagramBuilder.html#ApplicationDiagramBuilder.fromDict" />
       <keyword name="ApplicationDiagramBuilder.getPersistenceData" id="ApplicationDiagramBuilder.getPersistenceData" ref="eric6.Graphics.ApplicationDiagramBuilder.html#ApplicationDiagramBuilder.getPersistenceData" />
       <keyword name="ApplicationDiagramBuilder.parsePersistenceData" id="ApplicationDiagramBuilder.parsePersistenceData" ref="eric6.Graphics.ApplicationDiagramBuilder.html#ApplicationDiagramBuilder.parsePersistenceData" />
+      <keyword name="ApplicationDiagramBuilder.toDict" id="ApplicationDiagramBuilder.toDict" ref="eric6.Graphics.ApplicationDiagramBuilder.html#ApplicationDiagramBuilder.toDict" />
       <keyword name="ApplicationPage" id="ApplicationPage" ref="eric6.Preferences.ConfigurationPages.ApplicationPage.html#ApplicationPage" />
       <keyword name="ApplicationPage (Constructor)" id="ApplicationPage (Constructor)" ref="eric6.Preferences.ConfigurationPages.ApplicationPage.html#ApplicationPage.__init__" />
       <keyword name="ApplicationPage (Module)" id="ApplicationPage (Module)" ref="eric6.Preferences.ConfigurationPages.ApplicationPage.html" />
@@ -1807,7 +1813,9 @@
       <keyword name="AssociationItem.__mapRectFromItem" id="AssociationItem.__mapRectFromItem" ref="eric6.Graphics.AssociationItem.html#AssociationItem.__mapRectFromItem" />
       <keyword name="AssociationItem.__updateEndPoint" id="AssociationItem.__updateEndPoint" ref="eric6.Graphics.AssociationItem.html#AssociationItem.__updateEndPoint" />
       <keyword name="AssociationItem.buildAssociationItemDataString" id="AssociationItem.buildAssociationItemDataString" ref="eric6.Graphics.AssociationItem.html#AssociationItem.buildAssociationItemDataString" />
+      <keyword name="AssociationItem.fromDict" id="AssociationItem.fromDict" ref="eric6.Graphics.AssociationItem.html#AssociationItem.fromDict" />
       <keyword name="AssociationItem.parseAssociationItemDataString" id="AssociationItem.parseAssociationItemDataString" ref="eric6.Graphics.AssociationItem.html#AssociationItem.parseAssociationItemDataString" />
+      <keyword name="AssociationItem.toDict" id="AssociationItem.toDict" ref="eric6.Graphics.AssociationItem.html#AssociationItem.toDict" />
       <keyword name="AssociationItem.unassociate" id="AssociationItem.unassociate" ref="eric6.Graphics.AssociationItem.html#AssociationItem.unassociate" />
       <keyword name="AssociationItem.widgetMoved" id="AssociationItem.widgetMoved" ref="eric6.Graphics.AssociationItem.html#AssociationItem.widgetMoved" />
       <keyword name="AssociationPointRegion" id="AssociationPointRegion" ref="eric6.Graphics.AssociationItem.html#AssociationPointRegion" />
@@ -2513,15 +2521,19 @@
       <keyword name="ClassItem.__calculateSize" id="ClassItem.__calculateSize" ref="eric6.Graphics.ClassItem.html#ClassItem.__calculateSize" />
       <keyword name="ClassItem.__createTexts" id="ClassItem.__createTexts" ref="eric6.Graphics.ClassItem.html#ClassItem.__createTexts" />
       <keyword name="ClassItem.buildItemDataString" id="ClassItem.buildItemDataString" ref="eric6.Graphics.ClassItem.html#ClassItem.buildItemDataString" />
+      <keyword name="ClassItem.fromDict" id="ClassItem.fromDict" ref="eric6.Graphics.ClassItem.html#ClassItem.fromDict" />
       <keyword name="ClassItem.isExternal" id="ClassItem.isExternal" ref="eric6.Graphics.ClassItem.html#ClassItem.isExternal" />
       <keyword name="ClassItem.paint" id="ClassItem.paint" ref="eric6.Graphics.ClassItem.html#ClassItem.paint" />
       <keyword name="ClassItem.parseItemDataString" id="ClassItem.parseItemDataString" ref="eric6.Graphics.ClassItem.html#ClassItem.parseItemDataString" />
       <keyword name="ClassItem.setModel" id="ClassItem.setModel" ref="eric6.Graphics.ClassItem.html#ClassItem.setModel" />
+      <keyword name="ClassItem.toDict" id="ClassItem.toDict" ref="eric6.Graphics.ClassItem.html#ClassItem.toDict" />
       <keyword name="ClassModel" id="ClassModel" ref="eric6.Graphics.ClassItem.html#ClassModel" />
       <keyword name="ClassModel (Constructor)" id="ClassModel (Constructor)" ref="eric6.Graphics.ClassItem.html#ClassModel.__init__" />
-      <keyword name="ClassModel.addAttribute" id="ClassModel.addAttribute" ref="eric6.Graphics.ClassItem.html#ClassModel.addAttribute" />
+      <keyword name="ClassModel.addClassAttribute" id="ClassModel.addClassAttribute" ref="eric6.Graphics.ClassItem.html#ClassModel.addClassAttribute" />
+      <keyword name="ClassModel.addInstanceAttribute" id="ClassModel.addInstanceAttribute" ref="eric6.Graphics.ClassItem.html#ClassModel.addInstanceAttribute" />
       <keyword name="ClassModel.addMethod" id="ClassModel.addMethod" ref="eric6.Graphics.ClassItem.html#ClassModel.addMethod" />
-      <keyword name="ClassModel.getAttributes" id="ClassModel.getAttributes" ref="eric6.Graphics.ClassItem.html#ClassModel.getAttributes" />
+      <keyword name="ClassModel.getClassAttributes" id="ClassModel.getClassAttributes" ref="eric6.Graphics.ClassItem.html#ClassModel.getClassAttributes" />
+      <keyword name="ClassModel.getInstanceAttributes" id="ClassModel.getInstanceAttributes" ref="eric6.Graphics.ClassItem.html#ClassModel.getInstanceAttributes" />
       <keyword name="ClassModel.getMethods" id="ClassModel.getMethods" ref="eric6.Graphics.ClassItem.html#ClassModel.getMethods" />
       <keyword name="ClbrBase" id="ClbrBase" ref="eric6.Utilities.ClassBrowsers.ClbrBaseClasses.html#ClbrBase" />
       <keyword name="ClbrBase (Constructor)" id="ClbrBase (Constructor)" ref="eric6.Utilities.ClassBrowsers.ClbrBaseClasses.html#ClbrBase.__init__" />
@@ -4155,6 +4167,25 @@
       <keyword name="E5HorizontalToolBox.removeItem" id="E5HorizontalToolBox.removeItem" ref="eric6.E5Gui.E5ToolBox.html#E5HorizontalToolBox.removeItem" />
       <keyword name="E5HorizontalToolBox.setItemEnabled" id="E5HorizontalToolBox.setItemEnabled" ref="eric6.E5Gui.E5ToolBox.html#E5HorizontalToolBox.setItemEnabled" />
       <keyword name="E5HorizontalToolBox.setItemToolTip" id="E5HorizontalToolBox.setItemToolTip" ref="eric6.E5Gui.E5ToolBox.html#E5HorizontalToolBox.setItemToolTip" />
+      <keyword name="E5JsonClient" id="E5JsonClient" ref="eric6.E5Network.E5JsonClient.html#E5JsonClient" />
+      <keyword name="E5JsonClient (Constructor)" id="E5JsonClient (Constructor)" ref="eric6.E5Network.E5JsonClient.html#E5JsonClient.__init__" />
+      <keyword name="E5JsonClient (Module)" id="E5JsonClient (Module)" ref="eric6.E5Network.E5JsonClient.html" />
+      <keyword name="E5JsonClient.__receiveJson" id="E5JsonClient.__receiveJson" ref="eric6.E5Network.E5JsonClient.html#E5JsonClient.__receiveJson" />
+      <keyword name="E5JsonClient.handleCall" id="E5JsonClient.handleCall" ref="eric6.E5Network.E5JsonClient.html#E5JsonClient.handleCall" />
+      <keyword name="E5JsonClient.run" id="E5JsonClient.run" ref="eric6.E5Network.E5JsonClient.html#E5JsonClient.run" />
+      <keyword name="E5JsonClient.sendJson" id="E5JsonClient.sendJson" ref="eric6.E5Network.E5JsonClient.html#E5JsonClient.sendJson" />
+      <keyword name="E5JsonServer" id="E5JsonServer" ref="eric6.E5Network.E5JsonServer.html#E5JsonServer" />
+      <keyword name="E5JsonServer (Constructor)" id="E5JsonServer (Constructor)" ref="eric6.E5Network.E5JsonServer.html#E5JsonServer.__init__" />
+      <keyword name="E5JsonServer (Module)" id="E5JsonServer (Module)" ref="eric6.E5Network.E5JsonServer.html" />
+      <keyword name="E5JsonServer.__handleDisconnect" id="E5JsonServer.__handleDisconnect" ref="eric6.E5Network.E5JsonServer.html#E5JsonServer.__handleDisconnect" />
+      <keyword name="E5JsonServer.__receiveJson" id="E5JsonServer.__receiveJson" ref="eric6.E5Network.E5JsonServer.html#E5JsonServer.__receiveJson" />
+      <keyword name="E5JsonServer.connectionNames" id="E5JsonServer.connectionNames" ref="eric6.E5Network.E5JsonServer.html#E5JsonServer.connectionNames" />
+      <keyword name="E5JsonServer.handleCall" id="E5JsonServer.handleCall" ref="eric6.E5Network.E5JsonServer.html#E5JsonServer.handleCall" />
+      <keyword name="E5JsonServer.handleNewConnection" id="E5JsonServer.handleNewConnection" ref="eric6.E5Network.E5JsonServer.html#E5JsonServer.handleNewConnection" />
+      <keyword name="E5JsonServer.sendJson" id="E5JsonServer.sendJson" ref="eric6.E5Network.E5JsonServer.html#E5JsonServer.sendJson" />
+      <keyword name="E5JsonServer.startClient" id="E5JsonServer.startClient" ref="eric6.E5Network.E5JsonServer.html#E5JsonServer.startClient" />
+      <keyword name="E5JsonServer.stopAllClients" id="E5JsonServer.stopAllClients" ref="eric6.E5Network.E5JsonServer.html#E5JsonServer.stopAllClients" />
+      <keyword name="E5JsonServer.stopClient" id="E5JsonServer.stopClient" ref="eric6.E5Network.E5JsonServer.html#E5JsonServer.stopClient" />
       <keyword name="E5Led" id="E5Led" ref="eric6.E5Gui.E5Led.html#E5Led" />
       <keyword name="E5Led (Constructor)" id="E5Led (Constructor)" ref="eric6.E5Gui.E5Led.html#E5Led.__init__" />
       <keyword name="E5Led (Module)" id="E5Led (Module)" ref="eric6.E5Gui.E5Led.html" />
@@ -8813,12 +8844,15 @@
       <keyword name="ImportsDiagramBuilder (Constructor)" id="ImportsDiagramBuilder (Constructor)" ref="eric6.Graphics.ImportsDiagramBuilder.html#ImportsDiagramBuilder.__init__" />
       <keyword name="ImportsDiagramBuilder (Module)" id="ImportsDiagramBuilder (Module)" ref="eric6.Graphics.ImportsDiagramBuilder.html" />
       <keyword name="ImportsDiagramBuilder.__addModule" id="ImportsDiagramBuilder.__addModule" ref="eric6.Graphics.ImportsDiagramBuilder.html#ImportsDiagramBuilder.__addModule" />
+      <keyword name="ImportsDiagramBuilder.__arrangeNodes" id="ImportsDiagramBuilder.__arrangeNodes" ref="eric6.Graphics.ImportsDiagramBuilder.html#ImportsDiagramBuilder.__arrangeNodes" />
       <keyword name="ImportsDiagramBuilder.__buildModulesDict" id="ImportsDiagramBuilder.__buildModulesDict" ref="eric6.Graphics.ImportsDiagramBuilder.html#ImportsDiagramBuilder.__buildModulesDict" />
       <keyword name="ImportsDiagramBuilder.__createAssociations" id="ImportsDiagramBuilder.__createAssociations" ref="eric6.Graphics.ImportsDiagramBuilder.html#ImportsDiagramBuilder.__createAssociations" />
       <keyword name="ImportsDiagramBuilder.buildDiagram" id="ImportsDiagramBuilder.buildDiagram" ref="eric6.Graphics.ImportsDiagramBuilder.html#ImportsDiagramBuilder.buildDiagram" />
+      <keyword name="ImportsDiagramBuilder.fromDict" id="ImportsDiagramBuilder.fromDict" ref="eric6.Graphics.ImportsDiagramBuilder.html#ImportsDiagramBuilder.fromDict" />
       <keyword name="ImportsDiagramBuilder.getPersistenceData" id="ImportsDiagramBuilder.getPersistenceData" ref="eric6.Graphics.ImportsDiagramBuilder.html#ImportsDiagramBuilder.getPersistenceData" />
       <keyword name="ImportsDiagramBuilder.initialize" id="ImportsDiagramBuilder.initialize" ref="eric6.Graphics.ImportsDiagramBuilder.html#ImportsDiagramBuilder.initialize" />
       <keyword name="ImportsDiagramBuilder.parsePersistenceData" id="ImportsDiagramBuilder.parsePersistenceData" ref="eric6.Graphics.ImportsDiagramBuilder.html#ImportsDiagramBuilder.parsePersistenceData" />
+      <keyword name="ImportsDiagramBuilder.toDict" id="ImportsDiagramBuilder.toDict" ref="eric6.Graphics.ImportsDiagramBuilder.html#ImportsDiagramBuilder.toDict" />
       <keyword name="IndentationWrapper" id="IndentationWrapper" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.CodeStyleFixer.html#IndentationWrapper" />
       <keyword name="IndentationWrapper (Constructor)" id="IndentationWrapper (Constructor)" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.CodeStyleFixer.html#IndentationWrapper.__init__" />
       <keyword name="IndentationWrapper.__buildTokensLogical" id="IndentationWrapper.__buildTokensLogical" ref="eric6.Plugins.CheckerPlugins.CodeStyleChecker.CodeStyleFixer.html#IndentationWrapper.__buildTokensLogical" />
@@ -10248,9 +10282,11 @@
       <keyword name="ModuleItem.__calculateSize" id="ModuleItem.__calculateSize" ref="eric6.Graphics.ModuleItem.html#ModuleItem.__calculateSize" />
       <keyword name="ModuleItem.__createTexts" id="ModuleItem.__createTexts" ref="eric6.Graphics.ModuleItem.html#ModuleItem.__createTexts" />
       <keyword name="ModuleItem.buildItemDataString" id="ModuleItem.buildItemDataString" ref="eric6.Graphics.ModuleItem.html#ModuleItem.buildItemDataString" />
+      <keyword name="ModuleItem.fromDict" id="ModuleItem.fromDict" ref="eric6.Graphics.ModuleItem.html#ModuleItem.fromDict" />
       <keyword name="ModuleItem.paint" id="ModuleItem.paint" ref="eric6.Graphics.ModuleItem.html#ModuleItem.paint" />
       <keyword name="ModuleItem.parseItemDataString" id="ModuleItem.parseItemDataString" ref="eric6.Graphics.ModuleItem.html#ModuleItem.parseItemDataString" />
       <keyword name="ModuleItem.setModel" id="ModuleItem.setModel" ref="eric6.Graphics.ModuleItem.html#ModuleItem.setModel" />
+      <keyword name="ModuleItem.toDict" id="ModuleItem.toDict" ref="eric6.Graphics.ModuleItem.html#ModuleItem.toDict" />
       <keyword name="ModuleLoader" id="ModuleLoader" ref="eric6.DebugClients.Python.ModuleLoader.html#ModuleLoader" />
       <keyword name="ModuleLoader (Constructor)" id="ModuleLoader (Constructor)" ref="eric6.DebugClients.Python.ModuleLoader.html#ModuleLoader.__init__" />
       <keyword name="ModuleLoader (Module)" id="ModuleLoader (Module)" ref="eric6.DebugClients.Python.ModuleLoader.html" />
@@ -10701,18 +10737,22 @@
       <keyword name="PackageDiagramBuilder.__createAssociations" id="PackageDiagramBuilder.__createAssociations" ref="eric6.Graphics.PackageDiagramBuilder.html#PackageDiagramBuilder.__createAssociations" />
       <keyword name="PackageDiagramBuilder.__getCurrentShape" id="PackageDiagramBuilder.__getCurrentShape" ref="eric6.Graphics.PackageDiagramBuilder.html#PackageDiagramBuilder.__getCurrentShape" />
       <keyword name="PackageDiagramBuilder.buildDiagram" id="PackageDiagramBuilder.buildDiagram" ref="eric6.Graphics.PackageDiagramBuilder.html#PackageDiagramBuilder.buildDiagram" />
+      <keyword name="PackageDiagramBuilder.fromDict" id="PackageDiagramBuilder.fromDict" ref="eric6.Graphics.PackageDiagramBuilder.html#PackageDiagramBuilder.fromDict" />
       <keyword name="PackageDiagramBuilder.getPersistenceData" id="PackageDiagramBuilder.getPersistenceData" ref="eric6.Graphics.PackageDiagramBuilder.html#PackageDiagramBuilder.getPersistenceData" />
       <keyword name="PackageDiagramBuilder.initialize" id="PackageDiagramBuilder.initialize" ref="eric6.Graphics.PackageDiagramBuilder.html#PackageDiagramBuilder.initialize" />
       <keyword name="PackageDiagramBuilder.parsePersistenceData" id="PackageDiagramBuilder.parsePersistenceData" ref="eric6.Graphics.PackageDiagramBuilder.html#PackageDiagramBuilder.parsePersistenceData" />
+      <keyword name="PackageDiagramBuilder.toDict" id="PackageDiagramBuilder.toDict" ref="eric6.Graphics.PackageDiagramBuilder.html#PackageDiagramBuilder.toDict" />
       <keyword name="PackageItem" id="PackageItem" ref="eric6.Graphics.PackageItem.html#PackageItem" />
       <keyword name="PackageItem (Constructor)" id="PackageItem (Constructor)" ref="eric6.Graphics.PackageItem.html#PackageItem.__init__" />
       <keyword name="PackageItem (Module)" id="PackageItem (Module)" ref="eric6.Graphics.PackageItem.html" />
       <keyword name="PackageItem.__calculateSize" id="PackageItem.__calculateSize" ref="eric6.Graphics.PackageItem.html#PackageItem.__calculateSize" />
       <keyword name="PackageItem.__createTexts" id="PackageItem.__createTexts" ref="eric6.Graphics.PackageItem.html#PackageItem.__createTexts" />
       <keyword name="PackageItem.buildItemDataString" id="PackageItem.buildItemDataString" ref="eric6.Graphics.PackageItem.html#PackageItem.buildItemDataString" />
+      <keyword name="PackageItem.fromDict" id="PackageItem.fromDict" ref="eric6.Graphics.PackageItem.html#PackageItem.fromDict" />
       <keyword name="PackageItem.paint" id="PackageItem.paint" ref="eric6.Graphics.PackageItem.html#PackageItem.paint" />
       <keyword name="PackageItem.parseItemDataString" id="PackageItem.parseItemDataString" ref="eric6.Graphics.PackageItem.html#PackageItem.parseItemDataString" />
       <keyword name="PackageItem.setModel" id="PackageItem.setModel" ref="eric6.Graphics.PackageItem.html#PackageItem.setModel" />
+      <keyword name="PackageItem.toDict" id="PackageItem.toDict" ref="eric6.Graphics.PackageItem.html#PackageItem.toDict" />
       <keyword name="PackageModel" id="PackageModel" ref="eric6.Graphics.PackageItem.html#PackageModel" />
       <keyword name="PackageModel (Constructor)" id="PackageModel (Constructor)" ref="eric6.Graphics.PackageItem.html#PackageModel.__init__" />
       <keyword name="PackageModel.addModule" id="PackageModel.addModule" ref="eric6.Graphics.PackageItem.html#PackageModel.addModule" />
@@ -11130,6 +11170,7 @@
       <keyword name="PluginManager.isValidPluginName" id="PluginManager.isValidPluginName" ref="eric6.PluginManager.PluginManager.html#PluginManager.isValidPluginName" />
       <keyword name="PluginManager.loadDocumentationSetPlugins" id="PluginManager.loadDocumentationSetPlugins" ref="eric6.PluginManager.PluginManager.html#PluginManager.loadDocumentationSetPlugins" />
       <keyword name="PluginManager.loadPlugin" id="PluginManager.loadPlugin" ref="eric6.PluginManager.PluginManager.html#PluginManager.loadPlugin" />
+      <keyword name="PluginManager.pipInstall" id="PluginManager.pipInstall" ref="eric6.PluginManager.PluginManager.html#PluginManager.pipInstall" />
       <keyword name="PluginManager.preferencesChanged" id="PluginManager.preferencesChanged" ref="eric6.PluginManager.PluginManager.html#PluginManager.preferencesChanged" />
       <keyword name="PluginManager.removePluginFromSysModules" id="PluginManager.removePluginFromSysModules" ref="eric6.PluginManager.PluginManager.html#PluginManager.removePluginFromSysModules" />
       <keyword name="PluginManager.unloadPlugin" id="PluginManager.unloadPlugin" ref="eric6.PluginManager.PluginManager.html#PluginManager.unloadPlugin" />
@@ -15021,6 +15062,7 @@
       <keyword name="Task.setPriority" id="Task.setPriority" ref="eric6.Tasks.Task.html#Task.setPriority" />
       <keyword name="Task.setProjectTask" id="Task.setProjectTask" ref="eric6.Tasks.Task.html#Task.setProjectTask" />
       <keyword name="Task.setSummary" id="Task.setSummary" ref="eric6.Tasks.Task.html#Task.setSummary" />
+      <keyword name="Task.setTaskType" id="Task.setTaskType" ref="eric6.Tasks.Task.html#Task.setTaskType" />
       <keyword name="Task.toDict" id="Task.toDict" ref="eric6.Tasks.Task.html#Task.toDict" />
       <keyword name="TaskFilter" id="TaskFilter" ref="eric6.Tasks.TaskFilter.html#TaskFilter" />
       <keyword name="TaskFilter (Constructor)" id="TaskFilter (Constructor)" ref="eric6.Tasks.TaskFilter.html#TaskFilter.__init__" />
@@ -15038,12 +15080,15 @@
       <keyword name="TaskFilterConfigDialog (Constructor)" id="TaskFilterConfigDialog (Constructor)" ref="eric6.Tasks.TaskFilterConfigDialog.html#TaskFilterConfigDialog.__init__" />
       <keyword name="TaskFilterConfigDialog (Module)" id="TaskFilterConfigDialog (Module)" ref="eric6.Tasks.TaskFilterConfigDialog.html" />
       <keyword name="TaskFilterConfigDialog.configureTaskFilter" id="TaskFilterConfigDialog.configureTaskFilter" ref="eric6.Tasks.TaskFilterConfigDialog.html#TaskFilterConfigDialog.configureTaskFilter" />
+      <keyword name="TaskPriority" id="TaskPriority" ref="eric6.Tasks.Task.html#TaskPriority" />
       <keyword name="TaskPropertiesDialog" id="TaskPropertiesDialog" ref="eric6.Tasks.TaskPropertiesDialog.html#TaskPropertiesDialog" />
       <keyword name="TaskPropertiesDialog (Constructor)" id="TaskPropertiesDialog (Constructor)" ref="eric6.Tasks.TaskPropertiesDialog.html#TaskPropertiesDialog.__init__" />
       <keyword name="TaskPropertiesDialog (Module)" id="TaskPropertiesDialog (Module)" ref="eric6.Tasks.TaskPropertiesDialog.html" />
+      <keyword name="TaskPropertiesDialog.__setMode" id="TaskPropertiesDialog.__setMode" ref="eric6.Tasks.TaskPropertiesDialog.html#TaskPropertiesDialog.__setMode" />
       <keyword name="TaskPropertiesDialog.getData" id="TaskPropertiesDialog.getData" ref="eric6.Tasks.TaskPropertiesDialog.html#TaskPropertiesDialog.getData" />
-      <keyword name="TaskPropertiesDialog.setReadOnly" id="TaskPropertiesDialog.setReadOnly" ref="eric6.Tasks.TaskPropertiesDialog.html#TaskPropertiesDialog.setReadOnly" />
+      <keyword name="TaskPropertiesDialog.isManualTaskMode" id="TaskPropertiesDialog.isManualTaskMode" ref="eric6.Tasks.TaskPropertiesDialog.html#TaskPropertiesDialog.isManualTaskMode" />
       <keyword name="TaskPropertiesDialog.setSubTaskMode" id="TaskPropertiesDialog.setSubTaskMode" ref="eric6.Tasks.TaskPropertiesDialog.html#TaskPropertiesDialog.setSubTaskMode" />
+      <keyword name="TaskType" id="TaskType" ref="eric6.Tasks.Task.html#TaskType" />
       <keyword name="TaskViewer" id="TaskViewer" ref="eric6.Tasks.TaskViewer.html#TaskViewer" />
       <keyword name="TaskViewer (Constructor)" id="TaskViewer (Constructor)" ref="eric6.Tasks.TaskViewer.html#TaskViewer.__init__" />
       <keyword name="TaskViewer (Module)" id="TaskViewer (Module)" ref="eric6.Tasks.TaskViewer.html" />
@@ -15472,28 +15517,39 @@
       <keyword name="UMLClassDiagramBuilder.__createAssociations" id="UMLClassDiagramBuilder.__createAssociations" ref="eric6.Graphics.UMLClassDiagramBuilder.html#UMLClassDiagramBuilder.__createAssociations" />
       <keyword name="UMLClassDiagramBuilder.__getCurrentShape" id="UMLClassDiagramBuilder.__getCurrentShape" ref="eric6.Graphics.UMLClassDiagramBuilder.html#UMLClassDiagramBuilder.__getCurrentShape" />
       <keyword name="UMLClassDiagramBuilder.buildDiagram" id="UMLClassDiagramBuilder.buildDiagram" ref="eric6.Graphics.UMLClassDiagramBuilder.html#UMLClassDiagramBuilder.buildDiagram" />
+      <keyword name="UMLClassDiagramBuilder.fromDict" id="UMLClassDiagramBuilder.fromDict" ref="eric6.Graphics.UMLClassDiagramBuilder.html#UMLClassDiagramBuilder.fromDict" />
       <keyword name="UMLClassDiagramBuilder.getPersistenceData" id="UMLClassDiagramBuilder.getPersistenceData" ref="eric6.Graphics.UMLClassDiagramBuilder.html#UMLClassDiagramBuilder.getPersistenceData" />
       <keyword name="UMLClassDiagramBuilder.initialize" id="UMLClassDiagramBuilder.initialize" ref="eric6.Graphics.UMLClassDiagramBuilder.html#UMLClassDiagramBuilder.initialize" />
       <keyword name="UMLClassDiagramBuilder.parsePersistenceData" id="UMLClassDiagramBuilder.parsePersistenceData" ref="eric6.Graphics.UMLClassDiagramBuilder.html#UMLClassDiagramBuilder.parsePersistenceData" />
+      <keyword name="UMLClassDiagramBuilder.toDict" id="UMLClassDiagramBuilder.toDict" ref="eric6.Graphics.UMLClassDiagramBuilder.html#UMLClassDiagramBuilder.toDict" />
       <keyword name="UMLDiagramBuilder" id="UMLDiagramBuilder" ref="eric6.Graphics.UMLDiagramBuilder.html#UMLDiagramBuilder" />
       <keyword name="UMLDiagramBuilder (Constructor)" id="UMLDiagramBuilder (Constructor)" ref="eric6.Graphics.UMLDiagramBuilder.html#UMLDiagramBuilder.__init__" />
       <keyword name="UMLDiagramBuilder (Module)" id="UMLDiagramBuilder (Module)" ref="eric6.Graphics.UMLDiagramBuilder.html" />
       <keyword name="UMLDiagramBuilder.buildDiagram" id="UMLDiagramBuilder.buildDiagram" ref="eric6.Graphics.UMLDiagramBuilder.html#UMLDiagramBuilder.buildDiagram" />
+      <keyword name="UMLDiagramBuilder.buildErrorMessage" id="UMLDiagramBuilder.buildErrorMessage" ref="eric6.Graphics.UMLDiagramBuilder.html#UMLDiagramBuilder.buildErrorMessage" />
+      <keyword name="UMLDiagramBuilder.fromDict" id="UMLDiagramBuilder.fromDict" ref="eric6.Graphics.UMLDiagramBuilder.html#UMLDiagramBuilder.fromDict" />
       <keyword name="UMLDiagramBuilder.getPersistenceData" id="UMLDiagramBuilder.getPersistenceData" ref="eric6.Graphics.UMLDiagramBuilder.html#UMLDiagramBuilder.getPersistenceData" />
       <keyword name="UMLDiagramBuilder.initialize" id="UMLDiagramBuilder.initialize" ref="eric6.Graphics.UMLDiagramBuilder.html#UMLDiagramBuilder.initialize" />
       <keyword name="UMLDiagramBuilder.parsePersistenceData" id="UMLDiagramBuilder.parsePersistenceData" ref="eric6.Graphics.UMLDiagramBuilder.html#UMLDiagramBuilder.parsePersistenceData" />
+      <keyword name="UMLDiagramBuilder.toDict" id="UMLDiagramBuilder.toDict" ref="eric6.Graphics.UMLDiagramBuilder.html#UMLDiagramBuilder.toDict" />
       <keyword name="UMLDialog" id="UMLDialog" ref="eric6.Graphics.UMLDialog.html#UMLDialog" />
       <keyword name="UMLDialog (Constructor)" id="UMLDialog (Constructor)" ref="eric6.Graphics.UMLDialog.html#UMLDialog.__init__" />
       <keyword name="UMLDialog (Module)" id="UMLDialog (Module)" ref="eric6.Graphics.UMLDialog.html" />
       <keyword name="UMLDialog.__diagramBuilder" id="UMLDialog.__diagramBuilder" ref="eric6.Graphics.UMLDialog.html#UMLDialog.__diagramBuilder" />
+      <keyword name="UMLDialog.__getDiagramTitel" id="UMLDialog.__getDiagramTitel" ref="eric6.Graphics.UMLDialog.html#UMLDialog.__getDiagramTitel" />
       <keyword name="UMLDialog.__initActions" id="UMLDialog.__initActions" ref="eric6.Graphics.UMLDialog.html#UMLDialog.__initActions" />
       <keyword name="UMLDialog.__initToolBars" id="UMLDialog.__initToolBars" ref="eric6.Graphics.UMLDialog.html#UMLDialog.__initToolBars" />
+      <keyword name="UMLDialog.__readJsonGraphicsFile" id="UMLDialog.__readJsonGraphicsFile" ref="eric6.Graphics.UMLDialog.html#UMLDialog.__readJsonGraphicsFile" />
+      <keyword name="UMLDialog.__readLineBasedGraphicsFile" id="UMLDialog.__readLineBasedGraphicsFile" ref="eric6.Graphics.UMLDialog.html#UMLDialog.__readLineBasedGraphicsFile" />
       <keyword name="UMLDialog.__relayout" id="UMLDialog.__relayout" ref="eric6.Graphics.UMLDialog.html#UMLDialog.__relayout" />
       <keyword name="UMLDialog.__save" id="UMLDialog.__save" ref="eric6.Graphics.UMLDialog.html#UMLDialog.__save" />
       <keyword name="UMLDialog.__saveAs" id="UMLDialog.__saveAs" ref="eric6.Graphics.UMLDialog.html#UMLDialog.__saveAs" />
       <keyword name="UMLDialog.__showInvalidDataMessage" id="UMLDialog.__showInvalidDataMessage" ref="eric6.Graphics.UMLDialog.html#UMLDialog.__showInvalidDataMessage" />
+      <keyword name="UMLDialog.__writeJsonGraphicsFile" id="UMLDialog.__writeJsonGraphicsFile" ref="eric6.Graphics.UMLDialog.html#UMLDialog.__writeJsonGraphicsFile" />
+      <keyword name="UMLDialog.__writeLineBasedGraphicsFile" id="UMLDialog.__writeLineBasedGraphicsFile" ref="eric6.Graphics.UMLDialog.html#UMLDialog.__writeLineBasedGraphicsFile" />
       <keyword name="UMLDialog.load" id="UMLDialog.load" ref="eric6.Graphics.UMLDialog.html#UMLDialog.load" />
       <keyword name="UMLDialog.show" id="UMLDialog.show" ref="eric6.Graphics.UMLDialog.html#UMLDialog.show" />
+      <keyword name="UMLDialogType" id="UMLDialogType" ref="eric6.Graphics.UMLDialog.html#UMLDialogType" />
       <keyword name="UMLGraphicsView" id="UMLGraphicsView" ref="eric6.Graphics.UMLGraphicsView.html#UMLGraphicsView" />
       <keyword name="UMLGraphicsView (Constructor)" id="UMLGraphicsView (Constructor)" ref="eric6.Graphics.UMLGraphicsView.html#UMLGraphicsView.__init__" />
       <keyword name="UMLGraphicsView (Module)" id="UMLGraphicsView (Module)" ref="eric6.Graphics.UMLGraphicsView.html" />
@@ -15516,6 +15572,7 @@
       <keyword name="UMLGraphicsView.filteredItems" id="UMLGraphicsView.filteredItems" ref="eric6.Graphics.UMLGraphicsView.html#UMLGraphicsView.filteredItems" />
       <keyword name="UMLGraphicsView.findItem" id="UMLGraphicsView.findItem" ref="eric6.Graphics.UMLGraphicsView.html#UMLGraphicsView.findItem" />
       <keyword name="UMLGraphicsView.findItemByName" id="UMLGraphicsView.findItemByName" ref="eric6.Graphics.UMLGraphicsView.html#UMLGraphicsView.findItemByName" />
+      <keyword name="UMLGraphicsView.fromDict" id="UMLGraphicsView.fromDict" ref="eric6.Graphics.UMLGraphicsView.html#UMLGraphicsView.fromDict" />
       <keyword name="UMLGraphicsView.gestureEvent" id="UMLGraphicsView.gestureEvent" ref="eric6.Graphics.UMLGraphicsView.html#UMLGraphicsView.gestureEvent" />
       <keyword name="UMLGraphicsView.getItemId" id="UMLGraphicsView.getItemId" ref="eric6.Graphics.UMLGraphicsView.html#UMLGraphicsView.getItemId" />
       <keyword name="UMLGraphicsView.getPersistenceData" id="UMLGraphicsView.getPersistenceData" ref="eric6.Graphics.UMLGraphicsView.html#UMLGraphicsView.getPersistenceData" />
@@ -15528,6 +15585,8 @@
       <keyword name="UMLGraphicsView.selectItem" id="UMLGraphicsView.selectItem" ref="eric6.Graphics.UMLGraphicsView.html#UMLGraphicsView.selectItem" />
       <keyword name="UMLGraphicsView.selectItems" id="UMLGraphicsView.selectItems" ref="eric6.Graphics.UMLGraphicsView.html#UMLGraphicsView.selectItems" />
       <keyword name="UMLGraphicsView.setDiagramName" id="UMLGraphicsView.setDiagramName" ref="eric6.Graphics.UMLGraphicsView.html#UMLGraphicsView.setDiagramName" />
+      <keyword name="UMLGraphicsView.setLayoutActionsEnabled" id="UMLGraphicsView.setLayoutActionsEnabled" ref="eric6.Graphics.UMLGraphicsView.html#UMLGraphicsView.setLayoutActionsEnabled" />
+      <keyword name="UMLGraphicsView.toDict" id="UMLGraphicsView.toDict" ref="eric6.Graphics.UMLGraphicsView.html#UMLGraphicsView.toDict" />
       <keyword name="UMLGraphicsView.wheelEvent" id="UMLGraphicsView.wheelEvent" ref="eric6.Graphics.UMLGraphicsView.html#UMLGraphicsView.wheelEvent" />
       <keyword name="UMLItem" id="UMLItem" ref="eric6.Graphics.UMLItem.html#UMLItem" />
       <keyword name="UMLItem (Constructor)" id="UMLItem (Constructor)" ref="eric6.Graphics.UMLItem.html#UMLItem.__init__" />
@@ -15535,6 +15594,7 @@
       <keyword name="UMLItem.addAssociation" id="UMLItem.addAssociation" ref="eric6.Graphics.UMLItem.html#UMLItem.addAssociation" />
       <keyword name="UMLItem.adjustAssociations" id="UMLItem.adjustAssociations" ref="eric6.Graphics.UMLItem.html#UMLItem.adjustAssociations" />
       <keyword name="UMLItem.buildItemDataString" id="UMLItem.buildItemDataString" ref="eric6.Graphics.UMLItem.html#UMLItem.buildItemDataString" />
+      <keyword name="UMLItem.fromDict" id="UMLItem.fromDict" ref="eric6.Graphics.UMLItem.html#UMLItem.fromDict" />
       <keyword name="UMLItem.getId" id="UMLItem.getId" ref="eric6.Graphics.UMLItem.html#UMLItem.getId" />
       <keyword name="UMLItem.getItemType" id="UMLItem.getItemType" ref="eric6.Graphics.UMLItem.html#UMLItem.getItemType" />
       <keyword name="UMLItem.getName" id="UMLItem.getName" ref="eric6.Graphics.UMLItem.html#UMLItem.getName" />
@@ -15547,6 +15607,7 @@
       <keyword name="UMLItem.setId" id="UMLItem.setId" ref="eric6.Graphics.UMLItem.html#UMLItem.setId" />
       <keyword name="UMLItem.setPos" id="UMLItem.setPos" ref="eric6.Graphics.UMLItem.html#UMLItem.setPos" />
       <keyword name="UMLItem.setSize" id="UMLItem.setSize" ref="eric6.Graphics.UMLItem.html#UMLItem.setSize" />
+      <keyword name="UMLItem.toDict" id="UMLItem.toDict" ref="eric6.Graphics.UMLItem.html#UMLItem.toDict" />
       <keyword name="UMLModel" id="UMLModel" ref="eric6.Graphics.UMLItem.html#UMLModel" />
       <keyword name="UMLModel (Constructor)" id="UMLModel (Constructor)" ref="eric6.Graphics.UMLItem.html#UMLModel.__init__" />
       <keyword name="UMLModel.getName" id="UMLModel.getName" ref="eric6.Graphics.UMLItem.html#UMLModel.getName" />
@@ -15775,6 +15836,7 @@
       <keyword name="UserInterface.__openHexEditor" id="UserInterface.__openHexEditor" ref="eric6.UI.UserInterface.html#UserInterface.__openHexEditor" />
       <keyword name="UserInterface.__openMiniEditor" id="UserInterface.__openMiniEditor" ref="eric6.UI.UserInterface.html#UserInterface.__openMiniEditor" />
       <keyword name="UserInterface.__openOnStartup" id="UserInterface.__openOnStartup" ref="eric6.UI.UserInterface.html#UserInterface.__openOnStartup" />
+      <keyword name="UserInterface.__pluginInstallFinished" id="UserInterface.__pluginInstallFinished" ref="eric6.UI.UserInterface.html#UserInterface.__pluginInstallFinished" />
       <keyword name="UserInterface.__pluginsConfigure" id="UserInterface.__pluginsConfigure" ref="eric6.UI.UserInterface.html#UserInterface.__pluginsConfigure" />
       <keyword name="UserInterface.__populateToolbarsMenu" id="UserInterface.__populateToolbarsMenu" ref="eric6.UI.UserInterface.html#UserInterface.__populateToolbarsMenu" />
       <keyword name="UserInterface.__preferencesChanged" id="UserInterface.__preferencesChanged" ref="eric6.UI.UserInterface.html#UserInterface.__preferencesChanged" />
@@ -15820,6 +15882,7 @@
       <keyword name="UserInterface.__showSystemEmailClient" id="UserInterface.__showSystemEmailClient" ref="eric6.UI.UserInterface.html#UserInterface.__showSystemEmailClient" />
       <keyword name="UserInterface.__showToolGroupsMenu" id="UserInterface.__showToolGroupsMenu" ref="eric6.UI.UserInterface.html#UserInterface.__showToolGroupsMenu" />
       <keyword name="UserInterface.__showToolbarsMenu" id="UserInterface.__showToolbarsMenu" ref="eric6.UI.UserInterface.html#UserInterface.__showToolbarsMenu" />
+      <keyword name="UserInterface.__showUml" id="UserInterface.__showUml" ref="eric6.UI.UserInterface.html#UserInterface.__showUml" />
       <keyword name="UserInterface.__showUserToolsMenu" id="UserInterface.__showUserToolsMenu" ref="eric6.UI.UserInterface.html#UserInterface.__showUserToolsMenu" />
       <keyword name="UserInterface.__showVersions" id="UserInterface.__showVersions" ref="eric6.UI.UserInterface.html#UserInterface.__showVersions" />
       <keyword name="UserInterface.__showWindowMenu" id="UserInterface.__showWindowMenu" ref="eric6.UI.UserInterface.html#UserInterface.__showWindowMenu" />
@@ -16001,7 +16064,6 @@
       <keyword name="VcsCommandOptionsDialog.getOptions" id="VcsCommandOptionsDialog.getOptions" ref="eric6.VCS.CommandOptionsDialog.html#VcsCommandOptionsDialog.getOptions" />
       <keyword name="VcsGitPlugin" id="VcsGitPlugin" ref="eric6.Plugins.PluginVcsGit.html#VcsGitPlugin" />
       <keyword name="VcsGitPlugin (Constructor)" id="VcsGitPlugin (Constructor)" ref="eric6.Plugins.PluginVcsGit.html#VcsGitPlugin.__init__" />
-      <keyword name="VcsGitPlugin.__loadTranslator" id="VcsGitPlugin.__loadTranslator" ref="eric6.Plugins.PluginVcsGit.html#VcsGitPlugin.__loadTranslator" />
       <keyword name="VcsGitPlugin.activate" id="VcsGitPlugin.activate" ref="eric6.Plugins.PluginVcsGit.html#VcsGitPlugin.activate" />
       <keyword name="VcsGitPlugin.deactivate" id="VcsGitPlugin.deactivate" ref="eric6.Plugins.PluginVcsGit.html#VcsGitPlugin.deactivate" />
       <keyword name="VcsGitPlugin.getConfigPath" id="VcsGitPlugin.getConfigPath" ref="eric6.Plugins.PluginVcsGit.html#VcsGitPlugin.getConfigPath" />
@@ -17953,6 +18015,7 @@
       <keyword name="getGraphics" id="getGraphics" ref="eric6.Preferences.__init__.html#getGraphics" />
       <keyword name="getHelp" id="getHelp" ref="eric6.Preferences.__init__.html#getHelp" />
       <keyword name="getHexEditor" id="getHexEditor" ref="eric6.Preferences.__init__.html#getHexEditor" />
+      <keyword name="getHgExecutable" id="getHgExecutable" ref="eric6.Plugins.VcsPlugins.vcsMercurial.HgUtilities.html#getHgExecutable" />
       <keyword name="getHomeDir" id="getHomeDir" ref="eric6.Utilities.__init__.html#getHomeDir" />
       <keyword name="getHtmlPage" id="getHtmlPage" ref="eric6.WebBrowser.Tools.WebBrowserTools.html#getHtmlPage" />
       <keyword name="getIcon" id="getIcon" ref="eric6.UI.PixmapCache.html#getIcon" />
@@ -18004,7 +18067,7 @@
       <keyword name="getPyQtToolsPath" id="getPyQtToolsPath" ref="eric6.Globals.__init__.html#getPyQtToolsPath" />
       <keyword name="getPython" id="getPython" ref="eric6.Preferences.__init__.html#getPython" />
       <keyword name="getPythonLibPath" id="getPythonLibPath" ref="eric6.Utilities.__init__.html#getPythonLibPath" />
-      <keyword name="getPythonModulesDirectory" id="getPythonModulesDirectory" ref="eric6.Globals.__init__.html#getPythonModulesDirectory" />
+      <keyword name="getPythonLibraryDirectory" id="getPythonLibraryDirectory" ref="eric6.Globals.__init__.html#getPythonLibraryDirectory" />
       <keyword name="getPythonVersion" id="getPythonVersion" ref="eric6.Utilities.__init__.html#getPythonVersion" />
       <keyword name="getQt" id="getQt" ref="eric6.Preferences.__init__.html#getQt" />
       <keyword name="getQtBinariesPath" id="getQtBinariesPath" ref="eric6.Globals.__init__.html#getQtBinariesPath" />
@@ -18690,6 +18753,8 @@
       <file>eric6.E5Network.E5Ftp.html</file>
       <file>eric6.E5Network.E5GoogleMail.html</file>
       <file>eric6.E5Network.E5GoogleMailHelpers.html</file>
+      <file>eric6.E5Network.E5JsonClient.html</file>
+      <file>eric6.E5Network.E5JsonServer.html</file>
       <file>eric6.E5Network.E5NetworkHeaderDetailsDialog.html</file>
       <file>eric6.E5Network.E5NetworkProxyFactory.html</file>
       <file>eric6.E5Network.E5RFC6266.html</file>
--- a/eric6/Documentation/Source/eric6.E5Graphics.E5GraphicsView.html	Sat May 01 14:27:38 2021 +0200
+++ b/eric6/Documentation/Source/eric6.E5Graphics.E5GraphicsView.html	Thu Jun 03 11:39:23 2021 +0200
@@ -187,23 +187,30 @@
 </p>
 <dl>
 
-<dt><i>rect</i></dt>
+<dt><i>rect</i> (QRectF)</dt>
 <dd>
-minimum rectangle fitting the diagram (QRectF)
+minimum rectangle fitting the diagram
 </dd>
-<dt><i>imageFormat</i></dt>
+<dt><i>imageFormat</i> (str)</dt>
 <dd>
-format for the image file (string)
+format for the image file
 </dd>
 <dt><i>filename</i></dt>
 <dd>
-name of the file for non pixmaps (string)
+name of the file for non pixmaps
+        str
 </dd>
 </dl>
 <dl>
 <dt>Return:</dt>
 <dd>
-diagram pixmap to receive the diagram (QPixmap)
+paint device containing the diagram
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+QPixmap or QSvgGenerator
 </dd>
 </dl>
 <a NAME="E5GraphicsView.__levelForZoom" ID="E5GraphicsView.__levelForZoom"></a>
--- a/eric6/Documentation/Source/eric6.E5Network.E5Ftp.html	Sat May 01 14:27:38 2021 +0200
+++ b/eric6/Documentation/Source/eric6.E5Network.E5Ftp.html	Thu Jun 03 11:39:23 2021 +0200
@@ -107,56 +107,56 @@
 
 <a NAME="E5Ftp.__init__" ID="E5Ftp.__init__"></a>
 <h4>E5Ftp (Constructor)</h4>
-<b>E5Ftp</b>(<i>host="", user="", password="", acct="", proxyType=E5FtpProxyType.NoProxy, proxyHost="", proxyPort=ftplib.FTP_PORT, proxyUser="", proxyPassword="", proxyAccount="", timeout=_GLOBAL_DEFAULT_TIMEOUT</i>)
+<b>E5Ftp</b>(<i>host="", user="", password="", acct="", proxyType=E5FtpProxyType.NO_PROXY, proxyHost="", proxyPort=ftplib.FTP_PORT, proxyUser="", proxyPassword="", proxyAccount="", timeout=_GLOBAL_DEFAULT_TIMEOUT</i>)
 
 <p>
         Constructor
 </p>
 <dl>
 
-<dt><i>host</i></dt>
+<dt><i>host</i> (str)</dt>
 <dd>
-name of the FTP host (string)
+name of the FTP host
 </dd>
-<dt><i>user</i></dt>
+<dt><i>user</i> (str)</dt>
 <dd>
-user name for login to FTP host (string)
+user name for login to FTP host
 </dd>
-<dt><i>password</i></dt>
+<dt><i>password</i> (str)</dt>
 <dd>
-password for login to FTP host (string)
+password for login to FTP host
 </dd>
-<dt><i>acct</i></dt>
+<dt><i>acct</i> (str)</dt>
 <dd>
-account for login to FTP host (string)
+account for login to FTP host
 </dd>
-<dt><i>proxyType</i></dt>
+<dt><i>proxyType</i> (E5FtpProxyType)</dt>
 <dd>
-type of the FTP proxy (integer 0 to 8)
+type of the FTP proxy
 </dd>
-<dt><i>proxyHost</i></dt>
+<dt><i>proxyHost</i> (str)</dt>
 <dd>
-name of the FTP proxy (string)
+name of the FTP proxy
 </dd>
-<dt><i>proxyPort</i></dt>
+<dt><i>proxyPort</i> (int)</dt>
 <dd>
-port of the FTP proxy (integer)
+port of the FTP proxy
 </dd>
-<dt><i>proxyUser</i></dt>
+<dt><i>proxyUser</i> (str)</dt>
 <dd>
-user name for login to the proxy (string)
+user name for login to the proxy
 </dd>
-<dt><i>proxyPassword</i></dt>
+<dt><i>proxyPassword</i> (str)</dt>
 <dd>
-password for login to the proxy (string)
+password for login to the proxy
 </dd>
-<dt><i>proxyAccount</i></dt>
+<dt><i>proxyAccount</i> (str)</dt>
 <dd>
-accounting info for the proxy (string)
+accounting info for the proxy
 </dd>
-<dt><i>timeout</i></dt>
+<dt><i>timeout</i> (int)</dt>
 <dd>
-timeout in seconds for blocking operations (integer)
+timeout in seconds for blocking operations
 </dd>
 </dl>
 <a NAME="E5Ftp.connect" ID="E5Ftp.connect"></a>
@@ -173,23 +173,29 @@
 </p>
 <dl>
 
-<dt><i>host</i></dt>
+<dt><i>host</i> (str)</dt>
 <dd>
-name of the FTP host (string)
+name of the FTP host
 </dd>
-<dt><i>port</i></dt>
+<dt><i>port</i> (int)</dt>
 <dd>
-port of the FTP host (integer)
+port of the FTP host
 </dd>
-<dt><i>timeout</i></dt>
+<dt><i>timeout</i> (int)</dt>
 <dd>
-timeout in seconds for blocking operations (integer)
+timeout in seconds for blocking operations
 </dd>
 </dl>
 <dl>
 <dt>Return:</dt>
 <dd>
-welcome message of the server (string)
+welcome message of the server
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+str
 </dd>
 </dl>
 <dl>
@@ -205,36 +211,36 @@
 
 <a NAME="E5Ftp.setProxy" ID="E5Ftp.setProxy"></a>
 <h4>E5Ftp.setProxy</h4>
-<b>setProxy</b>(<i>proxyType=E5FtpProxyType.NoProxy, proxyHost="", proxyPort=ftplib.FTP_PORT, proxyUser="", proxyPassword="", proxyAccount=""</i>)
+<b>setProxy</b>(<i>proxyType=E5FtpProxyType.NO_PROXY, proxyHost="", proxyPort=ftplib.FTP_PORT, proxyUser="", proxyPassword="", proxyAccount=""</i>)
 
 <p>
         Public method to set the proxy configuration.
 </p>
 <dl>
 
-<dt><i>proxyType</i></dt>
+<dt><i>proxyType</i> (E5FtpProxyType)</dt>
 <dd>
-type of the FTP proxy (integer 0 to 8)
+type of the FTP proxy
 </dd>
-<dt><i>proxyHost</i></dt>
+<dt><i>proxyHost</i> (str)</dt>
 <dd>
-name of the FTP proxy (string)
+name of the FTP proxy
 </dd>
-<dt><i>proxyPort</i></dt>
+<dt><i>proxyPort</i> (int)</dt>
 <dd>
-port of the FTP proxy (integer)
+port of the FTP proxy
 </dd>
-<dt><i>proxyUser</i></dt>
+<dt><i>proxyUser</i> (str)</dt>
 <dd>
-user name for login to the proxy (string)
+user name for login to the proxy
 </dd>
-<dt><i>proxyPassword</i></dt>
+<dt><i>proxyPassword</i> (str)</dt>
 <dd>
-password  for login to the proxy (string)
+password  for login to the proxy
 </dd>
-<dt><i>proxyAccount</i></dt>
+<dt><i>proxyAccount</i> (str)</dt>
 <dd>
-accounting info for the proxy (string)
+accounting info for the proxy
 </dd>
 </dl>
 <a NAME="E5Ftp.setProxyAuthentication" ID="E5Ftp.setProxyAuthentication"></a>
@@ -246,17 +252,17 @@
 </p>
 <dl>
 
-<dt><i>proxyUser</i></dt>
+<dt><i>proxyUser</i> (str)</dt>
 <dd>
-user name for login to the proxy (string)
+user name for login to the proxy
 </dd>
-<dt><i>proxyPassword</i></dt>
+<dt><i>proxyPassword</i> (str)</dt>
 <dd>
-password  for login to the proxy (string)
+password  for login to the proxy
 </dd>
-<dt><i>proxyAccount</i></dt>
+<dt><i>proxyAccount</i> (str)</dt>
 <dd>
-accounting info for the proxy (string)
+accounting info for the proxy
 </dd>
 </dl>
 <div align="right"><a href="#top">Up</a></div>
@@ -322,11 +328,11 @@
     Class defining the supported FTP proxy types.
 </p>
 <h3>Derived from</h3>
-None
+enum.Enum
 <h3>Class Attributes</h3>
 
 <table>
-<tr><td>AuthResp</td></tr><tr><td>Bluecoat</td></tr><tr><td>NoProxy</td></tr><tr><td>NonAuthorizing</td></tr><tr><td>Open</td></tr><tr><td>ProxyuserAtServer</td></tr><tr><td>Site</td></tr><tr><td>UserAtProxyuserAtServer</td></tr><tr><td>UserAtServer</td></tr>
+<tr><td>AUTH_RESP</td></tr><tr><td>BLUECOAT</td></tr><tr><td>NON_AUTHORIZING</td></tr><tr><td>NO_PROXY</td></tr><tr><td>OPEN</td></tr><tr><td>PROXYUSER_SERVER</td></tr><tr><td>SITE</td></tr><tr><td>USER_PROXYUSER_SERVER</td></tr><tr><td>USER_SERVER</td></tr>
 </table>
 <h3>Class Methods</h3>
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eric6/Documentation/Source/eric6.E5Network.E5JsonClient.html	Thu Jun 03 11:39:23 2021 +0200
@@ -0,0 +1,191 @@
+<!DOCTYPE html>
+<html><head>
+<title>eric6.E5Network.E5JsonClient</title>
+<meta charset="UTF-8">
+<style>
+body {
+    background: #EDECE6;
+    margin: 0em 1em 10em 1em;
+    color: black;
+}
+
+h1 { color: white; background: #85774A; }
+h2 { color: white; background: #85774A; }
+h3 { color: white; background: #9D936E; }
+h4 { color: white; background: #9D936E; }
+    
+a { color: #BA6D36; }
+
+</style>
+</head>
+<body>
+<a NAME="top" ID="top"></a>
+<h1>eric6.E5Network.E5JsonClient</h1>
+
+<p>
+Module implementing the JSON based client base class.
+</p>
+<h3>Global Attributes</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Classes</h3>
+
+<table>
+
+<tr>
+<td><a href="#E5JsonClient">E5JsonClient</a></td>
+<td>Class implementing a JSON based client base class.</td>
+</tr>
+</table>
+<h3>Functions</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<hr />
+<hr />
+<a NAME="E5JsonClient" ID="E5JsonClient"></a>
+<h2>E5JsonClient</h2>
+
+<p>
+    Class implementing a JSON based client base class.
+</p>
+<h3>Derived from</h3>
+None
+<h3>Class Attributes</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Class Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Methods</h3>
+
+<table>
+
+<tr>
+<td><a href="#E5JsonClient.__init__">E5JsonClient</a></td>
+<td>Constructor</td>
+</tr>
+<tr>
+<td><a href="#E5JsonClient.__receiveJson">__receiveJson</a></td>
+<td>Private method to receive a JSON encode command and data from the server.</td>
+</tr>
+<tr>
+<td><a href="#E5JsonClient.handleCall">handleCall</a></td>
+<td>Public method to handle a method call from the server.</td>
+</tr>
+<tr>
+<td><a href="#E5JsonClient.run">run</a></td>
+<td>Public method implementing the main loop of the client.</td>
+</tr>
+<tr>
+<td><a href="#E5JsonClient.sendJson">sendJson</a></td>
+<td>Public method to send a single refactoring command to the server.</td>
+</tr>
+</table>
+<h3>Static Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+
+<a NAME="E5JsonClient.__init__" ID="E5JsonClient.__init__"></a>
+<h4>E5JsonClient (Constructor)</h4>
+<b>E5JsonClient</b>(<i>host, port, idString=""</i>)
+
+<p>
+        Constructor
+</p>
+<dl>
+
+<dt><i>host</i> (str)</dt>
+<dd>
+ip address the background service is listening
+</dd>
+<dt><i>port</i> (int)</dt>
+<dd>
+port of the background service
+</dd>
+<dt><i>idString</i> (str)</dt>
+<dd>
+assigned client id to be sent back to the server in
+            order to identify the connection
+</dd>
+</dl>
+<a NAME="E5JsonClient.__receiveJson" ID="E5JsonClient.__receiveJson"></a>
+<h4>E5JsonClient.__receiveJson</h4>
+<b>__receiveJson</b>(<i></i>)
+
+<p>
+        Private method to receive a JSON encode command and data from the
+        server.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+tuple containing the received command and a dictionary
+            containing the associated data
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+tuple of (str, dict)
+</dd>
+</dl>
+<a NAME="E5JsonClient.handleCall" ID="E5JsonClient.handleCall"></a>
+<h4>E5JsonClient.handleCall</h4>
+<b>handleCall</b>(<i>method, params</i>)
+
+<p>
+        Public method to handle a method call from the server.
+</p>
+<p>
+        Note: This is an empty implementation that must be overridden in
+        derived classes.
+</p>
+<dl>
+
+<dt><i>method</i> (str)</dt>
+<dd>
+requested method name
+</dd>
+<dt><i>params</i> (dict)</dt>
+<dd>
+dictionary with method specific parameters
+</dd>
+</dl>
+<a NAME="E5JsonClient.run" ID="E5JsonClient.run"></a>
+<h4>E5JsonClient.run</h4>
+<b>run</b>(<i></i>)
+
+<p>
+        Public method implementing the main loop of the client.
+</p>
+<a NAME="E5JsonClient.sendJson" ID="E5JsonClient.sendJson"></a>
+<h4>E5JsonClient.sendJson</h4>
+<b>sendJson</b>(<i>command, params</i>)
+
+<p>
+        Public method to send a single refactoring command to the server.
+</p>
+<dl>
+
+<dt><i>command</i> (str)</dt>
+<dd>
+command name to be sent
+</dd>
+<dt><i>params</i> (dict)</dt>
+<dd>
+dictionary of named parameters for the command
+</dd>
+</dl>
+<div align="right"><a href="#top">Up</a></div>
+<hr />
+</body></html>
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eric6/Documentation/Source/eric6.E5Network.E5JsonServer.html	Thu Jun 03 11:39:23 2021 +0200
@@ -0,0 +1,311 @@
+<!DOCTYPE html>
+<html><head>
+<title>eric6.E5Network.E5JsonServer</title>
+<meta charset="UTF-8">
+<style>
+body {
+    background: #EDECE6;
+    margin: 0em 1em 10em 1em;
+    color: black;
+}
+
+h1 { color: white; background: #85774A; }
+h2 { color: white; background: #85774A; }
+h3 { color: white; background: #9D936E; }
+h4 { color: white; background: #9D936E; }
+    
+a { color: #BA6D36; }
+
+</style>
+</head>
+<body>
+<a NAME="top" ID="top"></a>
+<h1>eric6.E5Network.E5JsonServer</h1>
+
+<p>
+Module implementing the JSON based server base class.
+</p>
+<h3>Global Attributes</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Classes</h3>
+
+<table>
+
+<tr>
+<td><a href="#E5JsonServer">E5JsonServer</a></td>
+<td>Class implementing a JSON based server base class.</td>
+</tr>
+</table>
+<h3>Functions</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<hr />
+<hr />
+<a NAME="E5JsonServer" ID="E5JsonServer"></a>
+<h2>E5JsonServer</h2>
+
+<p>
+    Class implementing a JSON based server base class.
+</p>
+<h3>Derived from</h3>
+QTcpServer
+<h3>Class Attributes</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Class Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Methods</h3>
+
+<table>
+
+<tr>
+<td><a href="#E5JsonServer.__init__">E5JsonServer</a></td>
+<td>Constructor</td>
+</tr>
+<tr>
+<td><a href="#E5JsonServer.__handleDisconnect">__handleDisconnect</a></td>
+<td>Private slot handling a disconnect of the client.</td>
+</tr>
+<tr>
+<td><a href="#E5JsonServer.__receiveJson">__receiveJson</a></td>
+<td>Private slot handling received data from the client.</td>
+</tr>
+<tr>
+<td><a href="#E5JsonServer.connectionNames">connectionNames</a></td>
+<td>Public method to get the list of active connection names.</td>
+</tr>
+<tr>
+<td><a href="#E5JsonServer.handleCall">handleCall</a></td>
+<td>Public method to handle a method call from the client.</td>
+</tr>
+<tr>
+<td><a href="#E5JsonServer.handleNewConnection">handleNewConnection</a></td>
+<td>Public slot for new incoming connections from a client.</td>
+</tr>
+<tr>
+<td><a href="#E5JsonServer.sendJson">sendJson</a></td>
+<td>Public method to send a single command to a client.</td>
+</tr>
+<tr>
+<td><a href="#E5JsonServer.startClient">startClient</a></td>
+<td>Public method to start a client process.</td>
+</tr>
+<tr>
+<td><a href="#E5JsonServer.stopAllClients">stopAllClients</a></td>
+<td>Public method to stop all clients.</td>
+</tr>
+<tr>
+<td><a href="#E5JsonServer.stopClient">stopClient</a></td>
+<td>Public method to stop a client process.</td>
+</tr>
+</table>
+<h3>Static Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+
+<a NAME="E5JsonServer.__init__" ID="E5JsonServer.__init__"></a>
+<h4>E5JsonServer (Constructor)</h4>
+<b>E5JsonServer</b>(<i>name="", multiplex=False, parent=None</i>)
+
+<p>
+        Constructor
+</p>
+<dl>
+
+<dt><i>name</i> (str)</dt>
+<dd>
+name of the server (used for output only)
+</dd>
+<dt><i>multiplex</i> (bool)</dt>
+<dd>
+flag indicating a multiplexing server
+</dd>
+<dt><i>parent</i> (QObject)</dt>
+<dd>
+parent object
+</dd>
+</dl>
+<a NAME="E5JsonServer.__handleDisconnect" ID="E5JsonServer.__handleDisconnect"></a>
+<h4>E5JsonServer.__handleDisconnect</h4>
+<b>__handleDisconnect</b>(<i>idString</i>)
+
+<p>
+        Private slot handling a disconnect of the client.
+</p>
+<dl>
+
+<dt><i>idString</i> (str)</dt>
+<dd>
+id of the connection been disconnected
+</dd>
+</dl>
+<a NAME="E5JsonServer.__receiveJson" ID="E5JsonServer.__receiveJson"></a>
+<h4>E5JsonServer.__receiveJson</h4>
+<b>__receiveJson</b>(<i>idString</i>)
+
+<p>
+        Private slot handling received data from the client.
+</p>
+<dl>
+
+<dt><i>idString</i> (str)</dt>
+<dd>
+id of the connection been disconnected
+</dd>
+</dl>
+<a NAME="E5JsonServer.connectionNames" ID="E5JsonServer.connectionNames"></a>
+<h4>E5JsonServer.connectionNames</h4>
+<b>connectionNames</b>(<i></i>)
+
+<p>
+        Public method to get the list of active connection names.
+</p>
+<p>
+        If this is not a multiplexing server, an empty list is returned.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+list of active connection names
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+list of str
+</dd>
+</dl>
+<a NAME="E5JsonServer.handleCall" ID="E5JsonServer.handleCall"></a>
+<h4>E5JsonServer.handleCall</h4>
+<b>handleCall</b>(<i>method, params</i>)
+
+<p>
+        Public method to handle a method call from the client.
+</p>
+<p>
+        Note: This is an empty implementation that must be overridden in
+        derived classes.
+</p>
+<dl>
+
+<dt><i>method</i> (str)</dt>
+<dd>
+requested method name
+</dd>
+<dt><i>params</i> (dict)</dt>
+<dd>
+dictionary with method specific parameters
+</dd>
+</dl>
+<a NAME="E5JsonServer.handleNewConnection" ID="E5JsonServer.handleNewConnection"></a>
+<h4>E5JsonServer.handleNewConnection</h4>
+<b>handleNewConnection</b>(<i></i>)
+
+<p>
+        Public slot for new incoming connections from a client.
+</p>
+<a NAME="E5JsonServer.sendJson" ID="E5JsonServer.sendJson"></a>
+<h4>E5JsonServer.sendJson</h4>
+<b>sendJson</b>(<i>command, params, flush=False, idString=""</i>)
+
+<p>
+        Public method to send a single command to a client.
+</p>
+<dl>
+
+<dt><i>command</i> (str)</dt>
+<dd>
+command name to be sent
+</dd>
+<dt><i>params</i> (dict)</dt>
+<dd>
+dictionary of named parameters for the command
+</dd>
+<dt><i>flush</i> (bool)</dt>
+<dd>
+flag indicating to flush the data to the socket
+</dd>
+<dt><i>idString</i> (str)</dt>
+<dd>
+id of the connection to send data to
+</dd>
+</dl>
+<a NAME="E5JsonServer.startClient" ID="E5JsonServer.startClient"></a>
+<h4>E5JsonServer.startClient</h4>
+<b>startClient</b>(<i>interpreter, clientScript, clientArgs, idString="", environment=None</i>)
+
+<p>
+        Public method to start a client process.
+</p>
+<dl>
+
+<dt><i>interpreter</i> (str)</dt>
+<dd>
+interpreter to be used for the client
+</dd>
+<dt><i>clientScript</i> (str)</dt>
+<dd>
+path to the client script
+</dd>
+<dt><i>clientArgs</i></dt>
+<dd>
+list of arguments for the client
+</dd>
+<dt><i>idString</i> (str)</dt>
+<dd>
+id of the client to be started
+</dd>
+<dt><i>environment</i> (dict)</dt>
+<dd>
+dictionary of environment settings to pass
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+flag indicating a successful client start and the exit code
+            in case of an issue
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+bool, int
+</dd>
+</dl>
+<a NAME="E5JsonServer.stopAllClients" ID="E5JsonServer.stopAllClients"></a>
+<h4>E5JsonServer.stopAllClients</h4>
+<b>stopAllClients</b>(<i></i>)
+
+<p>
+        Public method to stop all clients.
+</p>
+<a NAME="E5JsonServer.stopClient" ID="E5JsonServer.stopClient"></a>
+<h4>E5JsonServer.stopClient</h4>
+<b>stopClient</b>(<i>idString=""</i>)
+
+<p>
+        Public method to stop a client process.
+</p>
+<dl>
+
+<dt><i>idString</i> (str)</dt>
+<dd>
+id of the client to be stopped
+</dd>
+</dl>
+<div align="right"><a href="#top">Up</a></div>
+<hr />
+</body></html>
\ No newline at end of file
--- a/eric6/Documentation/Source/eric6.Globals.__init__.html	Sat May 01 14:27:38 2021 +0200
+++ b/eric6/Documentation/Source/eric6.Globals.__init__.html	Thu Jun 03 11:39:23 2021 +0200
@@ -28,7 +28,7 @@
 <h3>Global Attributes</h3>
 
 <table>
-<tr><td>configDir</td></tr><tr><td>recentNameBreakpointConditions</td></tr><tr><td>recentNameBreakpointFiles</td></tr><tr><td>recentNameFiles</td></tr><tr><td>recentNameHexFiles</td></tr><tr><td>recentNameHosts</td></tr><tr><td>recentNameMultiProject</td></tr><tr><td>recentNameProject</td></tr><tr><td>settingsNameGlobal</td></tr><tr><td>settingsNameOrganization</td></tr><tr><td>settingsNameRecent</td></tr>
+<tr><td>configDir</td></tr><tr><td>getPythonModulesDirectory</td></tr><tr><td>recentNameBreakpointConditions</td></tr><tr><td>recentNameBreakpointFiles</td></tr><tr><td>recentNameFiles</td></tr><tr><td>recentNameHexFiles</td></tr><tr><td>recentNameHosts</td></tr><tr><td>recentNameMultiProject</td></tr><tr><td>recentNameProject</td></tr><tr><td>settingsNameGlobal</td></tr><tr><td>settingsNameOrganization</td></tr><tr><td>settingsNameRecent</td></tr>
 </table>
 <h3>Classes</h3>
 
@@ -64,8 +64,8 @@
 <td>Module function to get the path of the PyQt tools.</td>
 </tr>
 <tr>
-<td><a href="#getPythonModulesDirectory">getPythonModulesDirectory</a></td>
-<td>Function to determine the path to Python's modules directory.</td>
+<td><a href="#getPythonLibraryDirectory">getPythonLibraryDirectory</a></td>
+<td>Function to determine the path to Python's library directory.</td>
 </tr>
 <tr>
 <td><a href="#getQtBinariesPath">getQtBinariesPath</a></td>
@@ -277,17 +277,23 @@
 <div align="right"><a href="#top">Up</a></div>
 <hr />
 <hr />
-<a NAME="getPythonModulesDirectory" ID="getPythonModulesDirectory"></a>
-<h2>getPythonModulesDirectory</h2>
-<b>getPythonModulesDirectory</b>(<i></i>)
+<a NAME="getPythonLibraryDirectory" ID="getPythonLibraryDirectory"></a>
+<h2>getPythonLibraryDirectory</h2>
+<b>getPythonLibraryDirectory</b>(<i></i>)
 
 <p>
-    Function to determine the path to Python's modules directory.
+    Function to determine the path to Python's library directory.
 </p>
 <dl>
 <dt>Return:</dt>
 <dd>
-path to the Python modules directory (string)
+path to the Python library directory
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+str
 </dd>
 </dl>
 <div align="right"><a href="#top">Up</a></div>
--- a/eric6/Documentation/Source/eric6.Graphics.ApplicationDiagramBuilder.html	Sat May 01 14:27:38 2021 +0200
+++ b/eric6/Documentation/Source/eric6.Graphics.ApplicationDiagramBuilder.html	Thu Jun 03 11:39:23 2021 +0200
@@ -77,18 +77,30 @@
 <td>Private method to add a package to the diagram.</td>
 </tr>
 <tr>
+<td><a href="#ApplicationDiagramBuilder.__arrangeNodes">__arrangeNodes</a></td>
+<td>Private method to arrange the shapes on the canvas.</td>
+</tr>
+<tr>
 <td><a href="#ApplicationDiagramBuilder.__buildModulesDict">__buildModulesDict</a></td>
 <td>Private method to build a dictionary of modules contained in the application.</td>
 </tr>
 <tr>
 <td><a href="#ApplicationDiagramBuilder.__createAssociations">__createAssociations</a></td>
-<td>Private method to generate the associations between the package shapes.</td>
+<td>Private method to generate the associations between the module shapes.</td>
+</tr>
+<tr>
+<td><a href="#ApplicationDiagramBuilder.__findApplicationRoot">__findApplicationRoot</a></td>
+<td>Private method to find the application root path.</td>
 </tr>
 <tr>
 <td><a href="#ApplicationDiagramBuilder.buildDiagram">buildDiagram</a></td>
 <td>Public method to build the packages shapes of the diagram.</td>
 </tr>
 <tr>
+<td><a href="#ApplicationDiagramBuilder.fromDict">fromDict</a></td>
+<td>Public method to populate the class with data persisted by 'toDict()'.</td>
+</tr>
+<tr>
 <td><a href="#ApplicationDiagramBuilder.getPersistenceData">getPersistenceData</a></td>
 <td>Public method to get a string for data to be persisted.</td>
 </tr>
@@ -96,6 +108,10 @@
 <td><a href="#ApplicationDiagramBuilder.parsePersistenceData">parsePersistenceData</a></td>
 <td>Public method to parse persisted data.</td>
 </tr>
+<tr>
+<td><a href="#ApplicationDiagramBuilder.toDict">toDict</a></td>
+<td>Public method to collect data to be persisted.</td>
+</tr>
 </table>
 <h3>Static Methods</h3>
 
@@ -112,22 +128,22 @@
 </p>
 <dl>
 
-<dt><i>dialog</i></dt>
+<dt><i>dialog</i> (UMLDialog)</dt>
 <dd>
-reference to the UML dialog (UMLDialog)
+reference to the UML dialog
 </dd>
-<dt><i>view</i></dt>
+<dt><i>view</i> (UMLGraphicsView)</dt>
 <dd>
-reference to the view object (UMLGraphicsView)
+reference to the view object
 </dd>
-<dt><i>project</i></dt>
+<dt><i>project</i> (Project)</dt>
 <dd>
-reference to the project object (Project)
+reference to the project object
 </dd>
-<dt><i>noModules</i></dt>
+<dt><i>noModules</i> (bool)</dt>
 <dd>
 flag indicating, that no module names should be
-            shown (boolean)
+            shown
 </dd>
 </dl>
 <a NAME="ApplicationDiagramBuilder.__addPackage" ID="ApplicationDiagramBuilder.__addPackage"></a>
@@ -139,28 +155,59 @@
 </p>
 <dl>
 
-<dt><i>name</i></dt>
+<dt><i>name</i> (str)</dt>
 <dd>
-package name to be shown (string)
+package name to be shown
 </dd>
-<dt><i>modules</i></dt>
+<dt><i>modules</i> (list of str)</dt>
 <dd>
 list of module names contained in the package
-            (list of strings)
 </dd>
-<dt><i>x</i></dt>
+<dt><i>x</i> (float)</dt>
 <dd>
-x-coordinate (float)
+x-coordinate
 </dd>
-<dt><i>y</i></dt>
+<dt><i>y</i> (float)</dt>
 <dd>
-y-coordinate (float)
+y-coordinate
 </dd>
 </dl>
 <dl>
 <dt>Return:</dt>
 <dd>
-reference to the package item (PackageItem)
+reference to the package item
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+PackageItem
+</dd>
+</dl>
+<a NAME="ApplicationDiagramBuilder.__arrangeNodes" ID="ApplicationDiagramBuilder.__arrangeNodes"></a>
+<h4>ApplicationDiagramBuilder.__arrangeNodes</h4>
+<b>__arrangeNodes</b>(<i>nodes, routes, whiteSpaceFactor=1.2</i>)
+
+<p>
+        Private method to arrange the shapes on the canvas.
+</p>
+<p>
+        The algorithm is borrowed from Boa Constructor.
+</p>
+<dl>
+
+<dt><i>nodes</i> (list of str)</dt>
+<dd>
+list of nodes to arrange
+</dd>
+<dt><i>routes</i> (list of tuple of (str, str))</dt>
+<dd>
+list of routes
+</dd>
+<dt><i>whiteSpaceFactor</i> (float)</dt>
+<dd>
+factor to increase whitespace between
+            items
 </dd>
 </dl>
 <a NAME="ApplicationDiagramBuilder.__buildModulesDict" ID="ApplicationDiagramBuilder.__buildModulesDict"></a>
@@ -174,21 +221,46 @@
 <dl>
 <dt>Return:</dt>
 <dd>
-dictionary of modules contained in the application.
+dictionary of modules contained in the application
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+dict
 </dd>
 </dl>
 <a NAME="ApplicationDiagramBuilder.__createAssociations" ID="ApplicationDiagramBuilder.__createAssociations"></a>
 <h4>ApplicationDiagramBuilder.__createAssociations</h4>
-<b>__createAssociations</b>(<i>shapes</i>)
+<b>__createAssociations</b>(<i>routes</i>)
 
 <p>
-        Private method to generate the associations between the package shapes.
+        Private method to generate the associations between the module shapes.
 </p>
 <dl>
 
-<dt><i>shapes</i></dt>
+<dt><i>routes</i> (list of tuple of (str, str))</dt>
 <dd>
-list of shapes
+list of associations
+</dd>
+</dl>
+<a NAME="ApplicationDiagramBuilder.__findApplicationRoot" ID="ApplicationDiagramBuilder.__findApplicationRoot"></a>
+<h4>ApplicationDiagramBuilder.__findApplicationRoot</h4>
+<b>__findApplicationRoot</b>(<i></i>)
+
+<p>
+        Private method to find the application root path.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+application root path
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+str
 </dd>
 </dl>
 <a NAME="ApplicationDiagramBuilder.buildDiagram" ID="ApplicationDiagramBuilder.buildDiagram"></a>
@@ -198,6 +270,37 @@
 <p>
         Public method to build the packages shapes of the diagram.
 </p>
+<a NAME="ApplicationDiagramBuilder.fromDict" ID="ApplicationDiagramBuilder.fromDict"></a>
+<h4>ApplicationDiagramBuilder.fromDict</h4>
+<b>fromDict</b>(<i>version, data</i>)
+
+<p>
+        Public method to populate the class with data persisted by 'toDict()'.
+</p>
+<dl>
+
+<dt><i>version</i> (str)</dt>
+<dd>
+version of the data
+</dd>
+<dt><i>data</i> (dict)</dt>
+<dd>
+dictionary containing the persisted data
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+tuple containing a flag indicating success and an info
+            message in case the diagram belongs to a different project
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+tuple of (bool, str)
+</dd>
+</dl>
 <a NAME="ApplicationDiagramBuilder.getPersistenceData" ID="ApplicationDiagramBuilder.getPersistenceData"></a>
 <h4>ApplicationDiagramBuilder.getPersistenceData</h4>
 <b>getPersistenceData</b>(<i></i>)
@@ -208,7 +311,13 @@
 <dl>
 <dt>Return:</dt>
 <dd>
-persisted data string (string)
+persisted data string
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+str
 </dd>
 </dl>
 <a NAME="ApplicationDiagramBuilder.parsePersistenceData" ID="ApplicationDiagramBuilder.parsePersistenceData"></a>
@@ -220,19 +329,44 @@
 </p>
 <dl>
 
-<dt><i>version</i></dt>
+<dt><i>version</i> (str)</dt>
 <dd>
-version of the data (string)
+version of the data
 </dd>
-<dt><i>data</i></dt>
+<dt><i>data</i> (str)</dt>
 <dd>
-persisted data to be parsed (string)
+persisted data to be parsed
 </dd>
 </dl>
 <dl>
 <dt>Return:</dt>
 <dd>
-flag indicating success (boolean)
+flag indicating success
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+bool
+</dd>
+</dl>
+<a NAME="ApplicationDiagramBuilder.toDict" ID="ApplicationDiagramBuilder.toDict"></a>
+<h4>ApplicationDiagramBuilder.toDict</h4>
+<b>toDict</b>(<i></i>)
+
+<p>
+        Public method to collect data to be persisted.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+dictionary containing data to be persisted
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+dict
 </dd>
 </dl>
 <div align="right"><a href="#top">Up</a></div>
--- a/eric6/Documentation/Source/eric6.Graphics.AssociationItem.html	Sat May 01 14:27:38 2021 +0200
+++ b/eric6/Documentation/Source/eric6.Graphics.AssociationItem.html	Thu Jun 03 11:39:23 2021 +0200
@@ -76,6 +76,10 @@
 <table>
 
 <tr>
+<td><a href="#AssociationItem.fromDict">fromDict</a></td>
+<td>Class method to create an association item from persisted data.</td>
+</tr>
+<tr>
 <td><a href="#AssociationItem.parseAssociationItemDataString">parseAssociationItemDataString</a></td>
 <td>Class method to parse the given persistence data.</td>
 </tr>
@@ -110,7 +114,7 @@
 </tr>
 <tr>
 <td><a href="#AssociationItem.__findRectIntersectionPoint">__findRectIntersectionPoint</a></td>
-<td>Private method to find the intersetion point of a line with a rectangle.</td>
+<td>Private method to find the intersection point of a line with a rectangle.</td>
 </tr>
 <tr>
 <td><a href="#AssociationItem.__mapRectFromItem">__mapRectFromItem</a></td>
@@ -125,6 +129,10 @@
 <td>Public method to build a string to persist the specific item data.</td>
 </tr>
 <tr>
+<td><a href="#AssociationItem.toDict">toDict</a></td>
+<td>Public method to collect data to be persisted.</td>
+</tr>
+<tr>
 <td><a href="#AssociationItem.unassociate">unassociate</a></td>
 <td>Public method to unassociate from the widgets.</td>
 </tr>
@@ -139,6 +147,41 @@
 <tr><td>None</td></tr>
 </table>
 
+<a NAME="AssociationItem.fromDict" ID="AssociationItem.fromDict"></a>
+<h4>AssociationItem.fromDict (class method)</h4>
+<b>fromDict</b>(<i>data, umlItems, colors=None</i>)
+
+<p>
+        Class method to create an association item from persisted data.
+</p>
+<dl>
+
+<dt><i>data</i> (dict)</dt>
+<dd>
+dictionary containing the persisted data as generated
+            by toDict()
+</dd>
+<dt><i>umlItems</i> (list of UMLItem)</dt>
+<dd>
+list of UML items
+</dd>
+<dt><i>colors</i> (tuple of (QColor, QColor))</dt>
+<dd>
+tuple containing the foreground and background colors
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+created association item
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+AssociationItem
+</dd>
+</dl>
 <a NAME="AssociationItem.parseAssociationItemDataString" ID="AssociationItem.parseAssociationItemDataString"></a>
 <h4>AssociationItem.parseAssociationItemDataString (class method)</h4>
 <b>parseAssociationItemDataString</b>(<i>data</i>)
@@ -148,9 +191,9 @@
 </p>
 <dl>
 
-<dt><i>data</i></dt>
+<dt><i>data</i> (str)</dt>
 <dd>
-persisted data to be parsed (string)
+persisted data to be parsed
 </dd>
 </dl>
 <dl>
@@ -158,7 +201,13 @@
 <dd>
 tuple with the IDs of the source and destination items,
             the association type and a flag indicating to associate from top
-            to bottom (integer, integer, integer, boolean)
+            to bottom
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+tuple of (int, int, int, bool)
 </dd>
 </dl>
 <a NAME="AssociationItem.__init__" ID="AssociationItem.__init__"></a>
@@ -293,27 +342,33 @@
 </p>
 <dl>
 
-<dt><i>p1</i></dt>
+<dt><i>p1</i> (QPointF)</dt>
 <dd>
-first point of first line (QPointF)
+first point of first line
 </dd>
-<dt><i>p2</i></dt>
+<dt><i>p2</i> (QPointF)</dt>
 <dd>
-second point of first line (QPointF)
+second point of first line
 </dd>
-<dt><i>p3</i></dt>
+<dt><i>p3</i> (QPointF)</dt>
 <dd>
-first point of second line (QPointF)
+first point of second line
 </dd>
-<dt><i>p4</i></dt>
+<dt><i>p4</i> (QPointF)</dt>
 <dd>
-second point of second line (QPointF)
+second point of second line
 </dd>
 </dl>
 <dl>
 <dt>Return:</dt>
 <dd>
-the intersection point (QPointF)
+the intersection point
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+QPointF
 </dd>
 </dl>
 <a NAME="AssociationItem.__findPointRegion" ID="AssociationItem.__findPointRegion"></a>
@@ -326,17 +381,17 @@
 </p>
 <dl>
 
-<dt><i>rect</i></dt>
+<dt><i>rect</i> (QRectF)</dt>
 <dd>
-rectangle to calculate the region for (QRectF)
+rectangle to calculate the region for
 </dd>
-<dt><i>posX</i></dt>
+<dt><i>posX</i> (float)</dt>
 <dd>
-x position of point (float)
+x position of point
 </dd>
-<dt><i>posY</i></dt>
+<dt><i>posY</i> (float)</dt>
 <dd>
-y position of point (float)
+y position of point
 </dd>
 </dl>
 <dl>
@@ -354,33 +409,45 @@
             Center = On diagonal 1 and On diagonal 2 (the center)<br />
 </dd>
 </dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+AssociationPointRegion
+</dd>
+</dl>
 <a NAME="AssociationItem.__findRectIntersectionPoint" ID="AssociationItem.__findRectIntersectionPoint"></a>
 <h4>AssociationItem.__findRectIntersectionPoint</h4>
 <b>__findRectIntersectionPoint</b>(<i>item, p1, p2</i>)
 
 <p>
-        Private method to find the intersetion point of a line with a
+        Private method to find the intersection point of a line with a
         rectangle.
 </p>
 <dl>
 
-<dt><i>item</i></dt>
+<dt><i>item</i> (UMLItem)</dt>
 <dd>
 item to check against
 </dd>
-<dt><i>p1</i></dt>
+<dt><i>p1</i> (QPointF)</dt>
 <dd>
-first point of the line (QPointF)
+first point of the line
 </dd>
-<dt><i>p2</i></dt>
+<dt><i>p2</i> (QPointF)</dt>
 <dd>
-second point of the line (QPointF)
+second point of the line
 </dd>
 </dl>
 <dl>
 <dt>Return:</dt>
 <dd>
-the intersection point (QPointF)
+the intersection point
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+QPointF
 </dd>
 </dl>
 <a NAME="AssociationItem.__mapRectFromItem" ID="AssociationItem.__mapRectFromItem"></a>
@@ -393,15 +460,21 @@
 </p>
 <dl>
 
-<dt><i>item</i></dt>
+<dt><i>item</i> (QGraphicsRectItem)</dt>
 <dd>
-reference to the item to be mapped (QGraphicsRectItem)
+reference to the item to be mapped
 </dd>
 </dl>
 <dl>
 <dt>Return:</dt>
 <dd>
-item's rectangle in local coordinates (QRectF)
+item's rectangle in local coordinates
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+QRectF
 </dd>
 </dl>
 <a NAME="AssociationItem.__updateEndPoint" ID="AssociationItem.__updateEndPoint"></a>
@@ -413,13 +486,13 @@
 </p>
 <dl>
 
-<dt><i>region</i></dt>
+<dt><i>region</i> (AssociationPointRegion)</dt>
 <dd>
-the region for the endpoint (integer)
+the region for the endpoint
 </dd>
-<dt><i>isWidgetA</i></dt>
+<dt><i>isWidgetA</i> (bool)</dt>
 <dd>
-flag indicating update for itemA is done (boolean)
+flag indicating update for itemA is done
 </dd>
 </dl>
 <a NAME="AssociationItem.buildAssociationItemDataString" ID="AssociationItem.buildAssociationItemDataString"></a>
@@ -436,7 +509,32 @@
 <dl>
 <dt>Return:</dt>
 <dd>
-persistence data (string)
+persistence data
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+str
+</dd>
+</dl>
+<a NAME="AssociationItem.toDict" ID="AssociationItem.toDict"></a>
+<h4>AssociationItem.toDict</h4>
+<b>toDict</b>(<i></i>)
+
+<p>
+        Public method to collect data to be persisted.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+dictionary containing data to be persisted
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+dict
 </dd>
 </dl>
 <a NAME="AssociationItem.unassociate" ID="AssociationItem.unassociate"></a>
--- a/eric6/Documentation/Source/eric6.Graphics.ClassItem.html	Sat May 01 14:27:38 2021 +0200
+++ b/eric6/Documentation/Source/eric6.Graphics.ClassItem.html	Thu Jun 03 11:39:23 2021 +0200
@@ -66,7 +66,11 @@
 <h3>Class Methods</h3>
 
 <table>
-<tr><td>None</td></tr>
+
+<tr>
+<td><a href="#ClassItem.fromDict">fromDict</a></td>
+<td>Class method to create a class item from persisted data.</td>
+</tr>
 </table>
 <h3>Methods</h3>
 
@@ -104,6 +108,10 @@
 <td><a href="#ClassItem.setModel">setModel</a></td>
 <td>Public method to set the class model.</td>
 </tr>
+<tr>
+<td><a href="#ClassItem.toDict">toDict</a></td>
+<td>Public method to collect data to be persisted.</td>
+</tr>
 </table>
 <h3>Static Methods</h3>
 
@@ -111,6 +119,37 @@
 <tr><td>None</td></tr>
 </table>
 
+<a NAME="ClassItem.fromDict" ID="ClassItem.fromDict"></a>
+<h4>ClassItem.fromDict (class method)</h4>
+<b>fromDict</b>(<i>data, colors=None</i>)
+
+<p>
+        Class method to create a class item from persisted data.
+</p>
+<dl>
+
+<dt><i>data</i> (dict)</dt>
+<dd>
+dictionary containing the persisted data as generated
+            by toDict()
+</dd>
+<dt><i>colors</i> (tuple of (QColor, QColor))</dt>
+<dd>
+tuple containing the foreground and background colors
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+created class item
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+ClassItem
+</dd>
+</dl>
 <a NAME="ClassItem.__init__" ID="ClassItem.__init__"></a>
 <h4>ClassItem (Constructor)</h4>
 <b>ClassItem</b>(<i>model=None, external=False, x=0, y=0, rounded=False, noAttrs=False, colors=None, parent=None, scene=None</i>)
@@ -186,7 +225,13 @@
 <dl>
 <dt>Return:</dt>
 <dd>
-persistence data (string)
+persistence data
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+str
 </dd>
 </dl>
 <a NAME="ClassItem.isExternal" ID="ClassItem.isExternal"></a>
@@ -199,7 +244,13 @@
 <dl>
 <dt>Return:</dt>
 <dd>
-external state (boolean)
+external state
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+bool
 </dd>
 </dl>
 <a NAME="ClassItem.paint" ID="ClassItem.paint"></a>
@@ -211,17 +262,17 @@
 </p>
 <dl>
 
-<dt><i>painter</i></dt>
+<dt><i>painter</i> (QPainter)</dt>
 <dd>
-reference to the painter object (QPainter)
+reference to the painter object
 </dd>
-<dt><i>option</i></dt>
+<dt><i>option</i> (QStyleOptionGraphicsItem)</dt>
 <dd>
-style options (QStyleOptionGraphicsItem)
+style options
 </dd>
-<dt><i>widget</i></dt>
+<dt><i>widget</i> (QWidget)</dt>
 <dd>
-optional reference to the widget painted on (QWidget)
+optional reference to the widget painted on
 </dd>
 </dl>
 <a NAME="ClassItem.parseItemDataString" ID="ClassItem.parseItemDataString"></a>
@@ -233,19 +284,25 @@
 </p>
 <dl>
 
-<dt><i>version</i></dt>
+<dt><i>version</i> (str)</dt>
 <dd>
-version of the data (string)
+version of the data
 </dd>
-<dt><i>data</i></dt>
+<dt><i>data</i> (str)</dt>
 <dd>
-persisted data to be parsed (string)
+persisted data to be parsed
 </dd>
 </dl>
 <dl>
 <dt>Return:</dt>
 <dd>
-flag indicating success (boolean)
+flag indicating success
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+bool
 </dd>
 </dl>
 <a NAME="ClassItem.setModel" ID="ClassItem.setModel"></a>
@@ -257,9 +314,28 @@
 </p>
 <dl>
 
-<dt><i>model</i></dt>
+<dt><i>model</i> (ClassModel)</dt>
 <dd>
-class model containing the class data (ClassModel)
+class model containing the class data
+</dd>
+</dl>
+<a NAME="ClassItem.toDict" ID="ClassItem.toDict"></a>
+<h4>ClassItem.toDict</h4>
+<b>toDict</b>(<i></i>)
+
+<p>
+        Public method to collect data to be persisted.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+dictionary containing data to be persisted
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+dict
 </dd>
 </dl>
 <div align="right"><a href="#top">Up</a></div>
@@ -292,15 +368,23 @@
 <td>Constructor</td>
 </tr>
 <tr>
-<td><a href="#ClassModel.addAttribute">addAttribute</a></td>
-<td>Public method to add an attribute to the class model.</td>
+<td><a href="#ClassModel.addClassAttribute">addClassAttribute</a></td>
+<td>Public method to add a class attribute to the class model.</td>
+</tr>
+<tr>
+<td><a href="#ClassModel.addInstanceAttribute">addInstanceAttribute</a></td>
+<td>Public method to add an instance attribute to the class model.</td>
 </tr>
 <tr>
 <td><a href="#ClassModel.addMethod">addMethod</a></td>
 <td>Public method to add a method to the class model.</td>
 </tr>
 <tr>
-<td><a href="#ClassModel.getAttributes">getAttributes</a></td>
+<td><a href="#ClassModel.getClassAttributes">getClassAttributes</a></td>
+<td>Public method to retrieve the global attributes of the class.</td>
+</tr>
+<tr>
+<td><a href="#ClassModel.getInstanceAttributes">getInstanceAttributes</a></td>
 <td>Public method to retrieve the attributes of the class.</td>
 </tr>
 <tr>
@@ -316,40 +400,56 @@
 
 <a NAME="ClassModel.__init__" ID="ClassModel.__init__"></a>
 <h4>ClassModel (Constructor)</h4>
-<b>ClassModel</b>(<i>name, methods=None, attributes=None</i>)
+<b>ClassModel</b>(<i>name, methods=None, instanceAttributes=None, classAttributes=None</i>)
 
 <p>
         Constructor
 </p>
 <dl>
 
-<dt><i>name</i></dt>
+<dt><i>name</i> (str)</dt>
 <dd>
-the class name (string)
+the class name
 </dd>
-<dt><i>methods</i></dt>
+<dt><i>methods</i> (list of str)</dt>
 <dd>
 list of method names of the class
-            (list of strings)
 </dd>
-<dt><i>attributes</i></dt>
+<dt><i>instanceAttributes</i> (list of str)</dt>
 <dd>
-list of attribute names of the class
-            (list of strings)
+list of instance attribute names of the class
+</dd>
+<dt><i>classAttributes</i> (list of str)</dt>
+<dd>
+list of class attribute names of the class
 </dd>
 </dl>
-<a NAME="ClassModel.addAttribute" ID="ClassModel.addAttribute"></a>
-<h4>ClassModel.addAttribute</h4>
-<b>addAttribute</b>(<i>attribute</i>)
+<a NAME="ClassModel.addClassAttribute" ID="ClassModel.addClassAttribute"></a>
+<h4>ClassModel.addClassAttribute</h4>
+<b>addClassAttribute</b>(<i>attribute</i>)
 
 <p>
-        Public method to add an attribute to the class model.
+        Public method to add a class attribute to the class model.
 </p>
 <dl>
 
-<dt><i>attribute</i></dt>
+<dt><i>attribute</i> (str)</dt>
 <dd>
-attribute name to be added (string)
+class attribute name to be added
+</dd>
+</dl>
+<a NAME="ClassModel.addInstanceAttribute" ID="ClassModel.addInstanceAttribute"></a>
+<h4>ClassModel.addInstanceAttribute</h4>
+<b>addInstanceAttribute</b>(<i>attribute</i>)
+
+<p>
+        Public method to add an instance attribute to the class model.
+</p>
+<dl>
+
+<dt><i>attribute</i> (str)</dt>
+<dd>
+instance attribute name to be added
 </dd>
 </dl>
 <a NAME="ClassModel.addMethod" ID="ClassModel.addMethod"></a>
@@ -361,14 +461,33 @@
 </p>
 <dl>
 
-<dt><i>method</i></dt>
+<dt><i>method</i> (str)</dt>
 <dd>
-method name to be added (string)
+method name to be added
 </dd>
 </dl>
-<a NAME="ClassModel.getAttributes" ID="ClassModel.getAttributes"></a>
-<h4>ClassModel.getAttributes</h4>
-<b>getAttributes</b>(<i></i>)
+<a NAME="ClassModel.getClassAttributes" ID="ClassModel.getClassAttributes"></a>
+<h4>ClassModel.getClassAttributes</h4>
+<b>getClassAttributes</b>(<i></i>)
+
+<p>
+        Public method to retrieve the global attributes of the class.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+list of class attributes
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+list of str
+</dd>
+</dl>
+<a NAME="ClassModel.getInstanceAttributes" ID="ClassModel.getInstanceAttributes"></a>
+<h4>ClassModel.getInstanceAttributes</h4>
+<b>getInstanceAttributes</b>(<i></i>)
 
 <p>
         Public method to retrieve the attributes of the class.
@@ -376,7 +495,13 @@
 <dl>
 <dt>Return:</dt>
 <dd>
-list of class attributes (list of strings)
+list of instance attributes
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+list of str
 </dd>
 </dl>
 <a NAME="ClassModel.getMethods" ID="ClassModel.getMethods"></a>
@@ -389,7 +514,13 @@
 <dl>
 <dt>Return:</dt>
 <dd>
-list of class methods (list of strings)
+list of class methods
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+list of str
 </dd>
 </dl>
 <div align="right"><a href="#top">Up</a></div>
--- a/eric6/Documentation/Source/eric6.Graphics.GraphicsUtilities.html	Sat May 01 14:27:38 2021 +0200
+++ b/eric6/Documentation/Source/eric6.Graphics.GraphicsUtilities.html	Thu Jun 03 11:39:23 2021 +0200
@@ -98,7 +98,7 @@
 </p>
 <dl>
 
-<dt><i>routes</i></dt>
+<dt><i>routes</i> (list of tuple of (str, str))</dt>
 <dd>
 list of routes between nodes
 </dd>
@@ -109,6 +109,12 @@
 dictionary of child and dictionary of parent relationships
 </dd>
 </dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+tuple of (dict, dict)
+</dd>
+</dl>
 <div align="right"><a href="#top">Up</a></div>
 <hr />
 <hr />
@@ -128,15 +134,15 @@
 </p>
 <dl>
 
-<dt><i>nodes</i></dt>
+<dt><i>nodes</i> (str)</dt>
 <dd>
 list of nodes to be sorted
 </dd>
-<dt><i>routes</i></dt>
+<dt><i>routes</i> (list of tuple of (str, str))</dt>
 <dd>
 list of routes between the nodes
 </dd>
-<dt><i>noRecursion</i></dt>
+<dt><i>noRecursion</i> (bool)</dt>
 <dd>
 flag indicating, if recursion errors should be raised
 </dd>
@@ -148,6 +154,12 @@
 </dd>
 </dl>
 <dl>
+<dt>Return Type:</dt>
+<dd>
+list of lists of str
+</dd>
+</dl>
+<dl>
 
 <dt>Raises <b>RecursionError</b>:</dt>
 <dd>
--- a/eric6/Documentation/Source/eric6.Graphics.ImportsDiagramBuilder.html	Sat May 01 14:27:38 2021 +0200
+++ b/eric6/Documentation/Source/eric6.Graphics.ImportsDiagramBuilder.html	Thu Jun 03 11:39:23 2021 +0200
@@ -81,6 +81,10 @@
 <td>Private method to add a module to the diagram.</td>
 </tr>
 <tr>
+<td><a href="#ImportsDiagramBuilder.__arrangeNodes">__arrangeNodes</a></td>
+<td>Private method to arrange the shapes on the canvas.</td>
+</tr>
+<tr>
 <td><a href="#ImportsDiagramBuilder.__buildModulesDict">__buildModulesDict</a></td>
 <td>Private method to build a dictionary of modules contained in the package.</td>
 </tr>
@@ -93,6 +97,10 @@
 <td>Public method to build the modules shapes of the diagram.</td>
 </tr>
 <tr>
+<td><a href="#ImportsDiagramBuilder.fromDict">fromDict</a></td>
+<td>Public method to populate the class with data persisted by 'toDict()'.</td>
+</tr>
+<tr>
 <td><a href="#ImportsDiagramBuilder.getPersistenceData">getPersistenceData</a></td>
 <td>Public method to get a string for data to be persisted.</td>
 </tr>
@@ -104,6 +112,10 @@
 <td><a href="#ImportsDiagramBuilder.parsePersistenceData">parsePersistenceData</a></td>
 <td>Public method to parse persisted data.</td>
 </tr>
+<tr>
+<td><a href="#ImportsDiagramBuilder.toDict">toDict</a></td>
+<td>Public method to collect data to be persisted.</td>
+</tr>
 </table>
 <h3>Static Methods</h3>
 
@@ -120,27 +132,27 @@
 </p>
 <dl>
 
-<dt><i>dialog</i></dt>
+<dt><i>dialog</i> (UMLDialog)</dt>
 <dd>
-reference to the UML dialog (UMLDialog)
+reference to the UML dialog
 </dd>
-<dt><i>view</i></dt>
+<dt><i>view</i> (UMLGraphicsView)</dt>
 <dd>
-reference to the view object (UMLGraphicsView)
+reference to the view object
 </dd>
-<dt><i>project</i></dt>
+<dt><i>project</i> (Project)</dt>
 <dd>
-reference to the project object (Project)
+reference to the project object
 </dd>
-<dt><i>package</i></dt>
+<dt><i>package</i> (str)</dt>
 <dd>
 name of a python package to show the import
-            relationships (string)
+            relationships
 </dd>
-<dt><i>showExternalImports</i></dt>
+<dt><i>showExternalImports</i> (bool)</dt>
 <dd>
 flag indicating to show exports from
-            outside the package (boolean)
+            outside the package
 </dd>
 </dl>
 <a NAME="ImportsDiagramBuilder.__addModule" ID="ImportsDiagramBuilder.__addModule"></a>
@@ -152,28 +164,59 @@
 </p>
 <dl>
 
-<dt><i>name</i></dt>
+<dt><i>name</i> (str)</dt>
 <dd>
-module name to be shown (string)
+module name to be shown
 </dd>
-<dt><i>classes</i></dt>
+<dt><i>classes</i> (list of str)</dt>
 <dd>
 list of class names contained in the module
-            (list of strings)
 </dd>
-<dt><i>x</i></dt>
+<dt><i>x</i> (float)</dt>
 <dd>
-x-coordinate (float)
+x-coordinate
 </dd>
-<dt><i>y</i></dt>
+<dt><i>y</i> (float)</dt>
 <dd>
-y-coordinate (float)
+y-coordinate
 </dd>
 </dl>
 <dl>
 <dt>Return:</dt>
 <dd>
-reference to the imports item (ModuleItem)
+reference to the imports item
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+ModuleItem
+</dd>
+</dl>
+<a NAME="ImportsDiagramBuilder.__arrangeNodes" ID="ImportsDiagramBuilder.__arrangeNodes"></a>
+<h4>ImportsDiagramBuilder.__arrangeNodes</h4>
+<b>__arrangeNodes</b>(<i>nodes, routes, whiteSpaceFactor=1.2</i>)
+
+<p>
+        Private method to arrange the shapes on the canvas.
+</p>
+<p>
+        The algorithm is borrowed from Boa Constructor.
+</p>
+<dl>
+
+<dt><i>nodes</i> (list of str)</dt>
+<dd>
+list of nodes to arrange
+</dd>
+<dt><i>routes</i> (list of tuple of (str, str))</dt>
+<dd>
+list of routes
+</dd>
+<dt><i>whiteSpaceFactor</i> (float)</dt>
+<dd>
+factor to increase whitespace between
+            items
 </dd>
 </dl>
 <a NAME="ImportsDiagramBuilder.__buildModulesDict" ID="ImportsDiagramBuilder.__buildModulesDict"></a>
@@ -187,21 +230,27 @@
 <dl>
 <dt>Return:</dt>
 <dd>
-dictionary of modules contained in the package.
+dictionary of modules contained in the package
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+dict
 </dd>
 </dl>
 <a NAME="ImportsDiagramBuilder.__createAssociations" ID="ImportsDiagramBuilder.__createAssociations"></a>
 <h4>ImportsDiagramBuilder.__createAssociations</h4>
-<b>__createAssociations</b>(<i>shapes</i>)
+<b>__createAssociations</b>(<i>routes</i>)
 
 <p>
         Private method to generate the associations between the module shapes.
 </p>
 <dl>
 
-<dt><i>shapes</i></dt>
+<dt><i>routes</i> (list of tuple of (str, str))</dt>
 <dd>
-list of shapes
+list of associations
 </dd>
 </dl>
 <a NAME="ImportsDiagramBuilder.buildDiagram" ID="ImportsDiagramBuilder.buildDiagram"></a>
@@ -211,6 +260,37 @@
 <p>
         Public method to build the modules shapes of the diagram.
 </p>
+<a NAME="ImportsDiagramBuilder.fromDict" ID="ImportsDiagramBuilder.fromDict"></a>
+<h4>ImportsDiagramBuilder.fromDict</h4>
+<b>fromDict</b>(<i>version, data</i>)
+
+<p>
+        Public method to populate the class with data persisted by 'toDict()'.
+</p>
+<dl>
+
+<dt><i>version</i> (str)</dt>
+<dd>
+version of the data
+</dd>
+<dt><i>data</i> (dict)</dt>
+<dd>
+dictionary containing the persisted data
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+tuple containing a flag indicating success and an info
+            message in case the diagram belongs to a different project
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+tuple of (bool, str)
+</dd>
+</dl>
 <a NAME="ImportsDiagramBuilder.getPersistenceData" ID="ImportsDiagramBuilder.getPersistenceData"></a>
 <h4>ImportsDiagramBuilder.getPersistenceData</h4>
 <b>getPersistenceData</b>(<i></i>)
@@ -221,7 +301,13 @@
 <dl>
 <dt>Return:</dt>
 <dd>
-persisted data string (string)
+persisted data string
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+str
 </dd>
 </dl>
 <a NAME="ImportsDiagramBuilder.initialize" ID="ImportsDiagramBuilder.initialize"></a>
@@ -240,19 +326,44 @@
 </p>
 <dl>
 
-<dt><i>version</i></dt>
+<dt><i>version</i> (str)</dt>
 <dd>
-version of the data (string)
+version of the data
 </dd>
-<dt><i>data</i></dt>
+<dt><i>data</i> (str)</dt>
 <dd>
-persisted data to be parsed (string)
+persisted data to be parsed
 </dd>
 </dl>
 <dl>
 <dt>Return:</dt>
 <dd>
-flag indicating success (boolean)
+flag indicating success
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+bool
+</dd>
+</dl>
+<a NAME="ImportsDiagramBuilder.toDict" ID="ImportsDiagramBuilder.toDict"></a>
+<h4>ImportsDiagramBuilder.toDict</h4>
+<b>toDict</b>(<i></i>)
+
+<p>
+        Public method to collect data to be persisted.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+dictionary containing data to be persisted
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+dict
 </dd>
 </dl>
 <div align="right"><a href="#top">Up</a></div>
--- a/eric6/Documentation/Source/eric6.Graphics.ModuleItem.html	Sat May 01 14:27:38 2021 +0200
+++ b/eric6/Documentation/Source/eric6.Graphics.ModuleItem.html	Thu Jun 03 11:39:23 2021 +0200
@@ -66,7 +66,11 @@
 <h3>Class Methods</h3>
 
 <table>
-<tr><td>None</td></tr>
+
+<tr>
+<td><a href="#ModuleItem.fromDict">fromDict</a></td>
+<td>Class method to create a class item from persisted data.</td>
+</tr>
 </table>
 <h3>Methods</h3>
 
@@ -100,6 +104,10 @@
 <td><a href="#ModuleItem.setModel">setModel</a></td>
 <td>Public method to set the module model.</td>
 </tr>
+<tr>
+<td><a href="#ModuleItem.toDict">toDict</a></td>
+<td>Public method to collect data to be persisted.</td>
+</tr>
 </table>
 <h3>Static Methods</h3>
 
@@ -107,6 +115,37 @@
 <tr><td>None</td></tr>
 </table>
 
+<a NAME="ModuleItem.fromDict" ID="ModuleItem.fromDict"></a>
+<h4>ModuleItem.fromDict (class method)</h4>
+<b>fromDict</b>(<i>data, colors=None</i>)
+
+<p>
+        Class method to create a class item from persisted data.
+</p>
+<dl>
+
+<dt><i>data</i> (dict)</dt>
+<dd>
+dictionary containing the persisted data as generated
+            by toDict()
+</dd>
+<dt><i>colors</i> (tuple of (QColor, QColor))</dt>
+<dd>
+tuple containing the foreground and background colors
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+created class item
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+ClassItem
+</dd>
+</dl>
 <a NAME="ModuleItem.__init__" ID="ModuleItem.__init__"></a>
 <h4>ModuleItem (Constructor)</h4>
 <b>ModuleItem</b>(<i>model=None, x=0, y=0, rounded=False, colors=None, parent=None, scene=None</i>)
@@ -174,7 +213,13 @@
 <dl>
 <dt>Return:</dt>
 <dd>
-persistence data (string)
+persistence data
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+str
 </dd>
 </dl>
 <a NAME="ModuleItem.paint" ID="ModuleItem.paint"></a>
@@ -186,17 +231,17 @@
 </p>
 <dl>
 
-<dt><i>painter</i></dt>
+<dt><i>painter</i> (QPainter)</dt>
 <dd>
-reference to the painter object (QPainter)
+reference to the painter object
 </dd>
-<dt><i>option</i></dt>
+<dt><i>option</i> (QStyleOptionGraphicsItem)</dt>
 <dd>
-style options (QStyleOptionGraphicsItem)
+style options
 </dd>
-<dt><i>widget</i></dt>
+<dt><i>widget</i> (QWidget)</dt>
 <dd>
-optional reference to the widget painted on (QWidget)
+optional reference to the widget painted on
 </dd>
 </dl>
 <a NAME="ModuleItem.parseItemDataString" ID="ModuleItem.parseItemDataString"></a>
@@ -208,19 +253,25 @@
 </p>
 <dl>
 
-<dt><i>version</i></dt>
+<dt><i>version</i> (str)</dt>
 <dd>
-version of the data (string)
+version of the data
 </dd>
-<dt><i>data</i></dt>
+<dt><i>data</i> (str)</dt>
 <dd>
-persisted data to be parsed (string)
+persisted data to be parsed
 </dd>
 </dl>
 <dl>
 <dt>Return:</dt>
 <dd>
-flag indicating success (boolean)
+flag indicating success
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+bool
 </dd>
 </dl>
 <a NAME="ModuleItem.setModel" ID="ModuleItem.setModel"></a>
@@ -232,9 +283,28 @@
 </p>
 <dl>
 
-<dt><i>model</i></dt>
+<dt><i>model</i> (ModuleModel)</dt>
 <dd>
-module model containing the module data (ModuleModel)
+module model containing the module data
+</dd>
+</dl>
+<a NAME="ModuleItem.toDict" ID="ModuleItem.toDict"></a>
+<h4>ModuleItem.toDict</h4>
+<b>toDict</b>(<i></i>)
+
+<p>
+        Public method to collect data to be persisted.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+dictionary containing data to be persisted
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+dict
 </dd>
 </dl>
 <div align="right"><a href="#top">Up</a></div>
@@ -290,13 +360,13 @@
 </p>
 <dl>
 
-<dt><i>name</i></dt>
+<dt><i>name</i> (str)</dt>
 <dd>
-the module name (string)
+the module name
 </dd>
-<dt><i>classlist</i></dt>
+<dt><i>classlist</i> (list of str)</dt>
 <dd>
-list of class names (list of strings)
+list of class names
 </dd>
 </dl>
 <a NAME="ModuleModel.addClass" ID="ModuleModel.addClass"></a>
@@ -308,9 +378,9 @@
 </p>
 <dl>
 
-<dt><i>classname</i></dt>
+<dt><i>classname</i> (str)</dt>
 <dd>
-class name to be added (string)
+class name to be added
 </dd>
 </dl>
 <a NAME="ModuleModel.getClasses" ID="ModuleModel.getClasses"></a>
@@ -323,7 +393,13 @@
 <dl>
 <dt>Return:</dt>
 <dd>
-list of class names (list of strings)
+list of class names
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+list of str
 </dd>
 </dl>
 <div align="right"><a href="#top">Up</a></div>
--- a/eric6/Documentation/Source/eric6.Graphics.PackageDiagramBuilder.html	Sat May 01 14:27:38 2021 +0200
+++ b/eric6/Documentation/Source/eric6.Graphics.PackageDiagramBuilder.html	Thu Jun 03 11:39:23 2021 +0200
@@ -23,7 +23,7 @@
 <h1>eric6.Graphics.PackageDiagramBuilder</h1>
 
 <p>
-Module implementing a dialog showing a UML like class diagram of a package.
+Module implementing a dialog showing an UML like class diagram of a package.
 </p>
 <h3>Global Attributes</h3>
 
@@ -109,6 +109,10 @@
 <td>Public method to build the class shapes of the package diagram.</td>
 </tr>
 <tr>
+<td><a href="#PackageDiagramBuilder.fromDict">fromDict</a></td>
+<td>Public method to populate the class with data persisted by 'toDict()'.</td>
+</tr>
+<tr>
 <td><a href="#PackageDiagramBuilder.getPersistenceData">getPersistenceData</a></td>
 <td>Public method to get a string for data to be persisted.</td>
 </tr>
@@ -120,6 +124,10 @@
 <td><a href="#PackageDiagramBuilder.parsePersistenceData">parsePersistenceData</a></td>
 <td>Public method to parse persisted data.</td>
 </tr>
+<tr>
+<td><a href="#PackageDiagramBuilder.toDict">toDict</a></td>
+<td>Public method to collect data to be persisted.</td>
+</tr>
 </table>
 <h3>Static Methods</h3>
 
@@ -136,26 +144,25 @@
 </p>
 <dl>
 
-<dt><i>dialog</i></dt>
+<dt><i>dialog</i> (UMLDialog)</dt>
 <dd>
-reference to the UML dialog (UMLDialog)
+reference to the UML dialog
 </dd>
-<dt><i>view</i></dt>
+<dt><i>view</i> (UMLGraphicsView)</dt>
 <dd>
-reference to the view object (UMLGraphicsView)
+reference to the view object
 </dd>
-<dt><i>project</i></dt>
+<dt><i>project</i> (Project)</dt>
 <dd>
-reference to the project object (Project)
+reference to the project object
 </dd>
-<dt><i>package</i></dt>
+<dt><i>package</i> (str)</dt>
 <dd>
-name of a python package to be shown (string)
+name of a python package to be shown
 </dd>
-<dt><i>noAttrs</i></dt>
+<dt><i>noAttrs</i> (bool)</dt>
 <dd>
 flag indicating, that no attributes should be shown
-            (boolean)
 </dd>
 </dl>
 <a NAME="PackageDiagramBuilder.__addExternalClass" ID="PackageDiagramBuilder.__addExternalClass"></a>
@@ -171,17 +178,17 @@
 </p>
 <dl>
 
-<dt><i>_class</i></dt>
+<dt><i>_class</i> (ModuleParser.Class)</dt>
 <dd>
-class to be shown (string)
+class to be shown
 </dd>
-<dt><i>x</i></dt>
+<dt><i>x</i> (float)</dt>
 <dd>
-x-coordinate (float)
+x-coordinate
 </dd>
-<dt><i>y</i></dt>
+<dt><i>y</i> (float)</dt>
 <dd>
-y-coordinate (float)
+y-coordinate
 </dd>
 </dl>
 <a NAME="PackageDiagramBuilder.__addLocalClass" ID="PackageDiagramBuilder.__addLocalClass"></a>
@@ -193,25 +200,25 @@
 </p>
 <dl>
 
-<dt><i>className</i></dt>
+<dt><i>className</i> (str)</dt>
 <dd>
-name of the class to be as a dictionary key (string)
+name of the class to be as a dictionary key
 </dd>
-<dt><i>_class</i></dt>
+<dt><i>_class</i> (ModuleParser.Class)</dt>
 <dd>
-class to be shown (ModuleParser.Class)
+class to be shown
 </dd>
-<dt><i>x</i></dt>
+<dt><i>x</i> (float)</dt>
 <dd>
-x-coordinate (float)
+x-coordinate
 </dd>
-<dt><i>y</i></dt>
+<dt><i>y</i> (float)</dt>
 <dd>
-y-coordinate (float)
+y-coordinate
 </dd>
-<dt><i>isRbModule</i></dt>
+<dt><i>isRbModule</i> (bool)</dt>
 <dd>
-flag indicating a Ruby module (boolean)
+flag indicating a Ruby module
 </dd>
 </dl>
 <a NAME="PackageDiagramBuilder.__addPackage" ID="PackageDiagramBuilder.__addPackage"></a>
@@ -223,22 +230,21 @@
 </p>
 <dl>
 
-<dt><i>name</i></dt>
+<dt><i>name</i> (str)</dt>
 <dd>
-package name to be shown (string)
+package name to be shown
 </dd>
-<dt><i>modules</i></dt>
+<dt><i>modules</i> (list of str)</dt>
 <dd>
 list of module names contained in the package
-            (list of strings)
 </dd>
-<dt><i>x</i></dt>
+<dt><i>x</i> (float)</dt>
 <dd>
-x-coordinate (float)
+x-coordinate
 </dd>
-<dt><i>y</i></dt>
+<dt><i>y</i> (float)</dt>
 <dd>
-y-coordinate (float)
+y-coordinate
 </dd>
 </dl>
 <a NAME="PackageDiagramBuilder.__arrangeClasses" ID="PackageDiagramBuilder.__arrangeClasses"></a>
@@ -253,18 +259,18 @@
 </p>
 <dl>
 
-<dt><i>nodes</i></dt>
+<dt><i>nodes</i> (list of str)</dt>
 <dd>
 list of nodes to arrange
 </dd>
-<dt><i>routes</i></dt>
+<dt><i>routes</i> (list of tuple of (str, str))</dt>
 <dd>
 list of routes
 </dd>
-<dt><i>whiteSpaceFactor</i></dt>
+<dt><i>whiteSpaceFactor</i> (float)</dt>
 <dd>
 factor to increase whitespace between
-            items (float)
+            items
 </dd>
 </dl>
 <a NAME="PackageDiagramBuilder.__buildModulesDict" ID="PackageDiagramBuilder.__buildModulesDict"></a>
@@ -278,7 +284,13 @@
 <dl>
 <dt>Return:</dt>
 <dd>
-dictionary of modules contained in the package.
+dictionary of modules contained in the package
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+dict
 </dd>
 </dl>
 <a NAME="PackageDiagramBuilder.__buildSubpackagesDict" ID="PackageDiagramBuilder.__buildSubpackagesDict"></a>
@@ -295,6 +307,12 @@
 dictionary of sub-packages contained in this package
 </dd>
 </dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+dict
+</dd>
+</dl>
 <a NAME="PackageDiagramBuilder.__createAssociations" ID="PackageDiagramBuilder.__createAssociations"></a>
 <h4>PackageDiagramBuilder.__createAssociations</h4>
 <b>__createAssociations</b>(<i>routes</i>)
@@ -304,7 +322,7 @@
 </p>
 <dl>
 
-<dt><i>routes</i></dt>
+<dt><i>routes</i> (list of tuple of (str, str))</dt>
 <dd>
 list of relationsships
 </dd>
@@ -318,15 +336,21 @@
 </p>
 <dl>
 
-<dt><i>name</i></dt>
+<dt><i>name</i> (str)</dt>
 <dd>
-name of the shape (string)
+name of the shape
 </dd>
 </dl>
 <dl>
 <dt>Return:</dt>
 <dd>
-shape (QCanvasItem)
+shape
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+QCanvasItem
 </dd>
 </dl>
 <a NAME="PackageDiagramBuilder.buildDiagram" ID="PackageDiagramBuilder.buildDiagram"></a>
@@ -339,6 +363,37 @@
 <p>
         The algorithm is borrowed from Boa Constructor.
 </p>
+<a NAME="PackageDiagramBuilder.fromDict" ID="PackageDiagramBuilder.fromDict"></a>
+<h4>PackageDiagramBuilder.fromDict</h4>
+<b>fromDict</b>(<i>version, data</i>)
+
+<p>
+        Public method to populate the class with data persisted by 'toDict()'.
+</p>
+<dl>
+
+<dt><i>version</i> (str)</dt>
+<dd>
+version of the data
+</dd>
+<dt><i>data</i> (dict)</dt>
+<dd>
+dictionary containing the persisted data
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+tuple containing a flag indicating success and an info
+            message in case the diagram belongs to a different project
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+tuple of (bool, str)
+</dd>
+</dl>
 <a NAME="PackageDiagramBuilder.getPersistenceData" ID="PackageDiagramBuilder.getPersistenceData"></a>
 <h4>PackageDiagramBuilder.getPersistenceData</h4>
 <b>getPersistenceData</b>(<i></i>)
@@ -349,7 +404,13 @@
 <dl>
 <dt>Return:</dt>
 <dd>
-persisted data string (string)
+persisted data string
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+str
 </dd>
 </dl>
 <a NAME="PackageDiagramBuilder.initialize" ID="PackageDiagramBuilder.initialize"></a>
@@ -368,19 +429,44 @@
 </p>
 <dl>
 
-<dt><i>version</i></dt>
+<dt><i>version</i> (str)</dt>
 <dd>
-version of the data (string)
+version of the data
 </dd>
-<dt><i>data</i></dt>
+<dt><i>data</i> (str)</dt>
 <dd>
-persisted data to be parsed (string)
+persisted data to be parsed
 </dd>
 </dl>
 <dl>
 <dt>Return:</dt>
 <dd>
-flag indicating success (boolean)
+flag indicating success
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+bool
+</dd>
+</dl>
+<a NAME="PackageDiagramBuilder.toDict" ID="PackageDiagramBuilder.toDict"></a>
+<h4>PackageDiagramBuilder.toDict</h4>
+<b>toDict</b>(<i></i>)
+
+<p>
+        Public method to collect data to be persisted.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+dictionary containing data to be persisted
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+dict
 </dd>
 </dl>
 <div align="right"><a href="#top">Up</a></div>
--- a/eric6/Documentation/Source/eric6.Graphics.PackageItem.html	Sat May 01 14:27:38 2021 +0200
+++ b/eric6/Documentation/Source/eric6.Graphics.PackageItem.html	Thu Jun 03 11:39:23 2021 +0200
@@ -66,7 +66,11 @@
 <h3>Class Methods</h3>
 
 <table>
-<tr><td>None</td></tr>
+
+<tr>
+<td><a href="#PackageItem.fromDict">fromDict</a></td>
+<td>Class method to create a class item from persisted data.</td>
+</tr>
 </table>
 <h3>Methods</h3>
 
@@ -100,6 +104,10 @@
 <td><a href="#PackageItem.setModel">setModel</a></td>
 <td>Public method to set the package model.</td>
 </tr>
+<tr>
+<td><a href="#PackageItem.toDict">toDict</a></td>
+<td>Public method to collect data to be persisted.</td>
+</tr>
 </table>
 <h3>Static Methods</h3>
 
@@ -107,6 +115,37 @@
 <tr><td>None</td></tr>
 </table>
 
+<a NAME="PackageItem.fromDict" ID="PackageItem.fromDict"></a>
+<h4>PackageItem.fromDict (class method)</h4>
+<b>fromDict</b>(<i>data, colors=None</i>)
+
+<p>
+        Class method to create a class item from persisted data.
+</p>
+<dl>
+
+<dt><i>data</i> (dict)</dt>
+<dd>
+dictionary containing the persisted data as generated
+            by toDict()
+</dd>
+<dt><i>colors</i> (tuple of (QColor, QColor))</dt>
+<dd>
+tuple containing the foreground and background colors
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+created class item
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+ClassItem
+</dd>
+</dl>
 <a NAME="PackageItem.__init__" ID="PackageItem.__init__"></a>
 <h4>PackageItem (Constructor)</h4>
 <b>PackageItem</b>(<i>model=None, x=0, y=0, rounded=False, noModules=False, colors=None, parent=None, scene=None</i>)
@@ -179,7 +218,13 @@
 <dl>
 <dt>Return:</dt>
 <dd>
-persistence data (string)
+persistence data
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+str
 </dd>
 </dl>
 <a NAME="PackageItem.paint" ID="PackageItem.paint"></a>
@@ -191,17 +236,17 @@
 </p>
 <dl>
 
-<dt><i>painter</i></dt>
+<dt><i>painter</i> (QPainter)</dt>
 <dd>
-reference to the painter object (QPainter)
+reference to the painter object
 </dd>
-<dt><i>option</i></dt>
+<dt><i>option</i> (QStyleOptionGraphicsItem)</dt>
 <dd>
-style options (QStyleOptionGraphicsItem)
+style options
 </dd>
-<dt><i>widget</i></dt>
+<dt><i>widget</i> (QWidget)</dt>
 <dd>
-optional reference to the widget painted on (QWidget)
+optional reference to the widget painted on
 </dd>
 </dl>
 <a NAME="PackageItem.parseItemDataString" ID="PackageItem.parseItemDataString"></a>
@@ -213,19 +258,25 @@
 </p>
 <dl>
 
-<dt><i>version</i></dt>
+<dt><i>version</i> (str)</dt>
 <dd>
-version of the data (string)
+version of the data
 </dd>
-<dt><i>data</i></dt>
+<dt><i>data</i> (str)</dt>
 <dd>
-persisted data to be parsed (string)
+persisted data to be parsed
 </dd>
 </dl>
 <dl>
 <dt>Return:</dt>
 <dd>
-flag indicating success (boolean)
+flag indicating success
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+bool
 </dd>
 </dl>
 <a NAME="PackageItem.setModel" ID="PackageItem.setModel"></a>
@@ -237,9 +288,28 @@
 </p>
 <dl>
 
-<dt><i>model</i></dt>
+<dt><i>model</i> (PackageModel)</dt>
 <dd>
-package model containing the package data (PackageModel)
+package model containing the package data
+</dd>
+</dl>
+<a NAME="PackageItem.toDict" ID="PackageItem.toDict"></a>
+<h4>PackageItem.toDict</h4>
+<b>toDict</b>(<i></i>)
+
+<p>
+        Public method to collect data to be persisted.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+dictionary containing data to be persisted
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+dict
 </dd>
 </dl>
 <div align="right"><a href="#top">Up</a></div>
@@ -295,13 +365,13 @@
 </p>
 <dl>
 
-<dt><i>name</i></dt>
+<dt><i>name</i> (str)</dt>
 <dd>
-package name (string)
+package name
 </dd>
-<dt><i>moduleslist</i></dt>
+<dt><i>moduleslist</i> (list of str)</dt>
 <dd>
-list of module names (list of strings)
+list of module names
 </dd>
 </dl>
 <a NAME="PackageModel.addModule" ID="PackageModel.addModule"></a>
@@ -313,9 +383,9 @@
 </p>
 <dl>
 
-<dt><i>modulename</i></dt>
+<dt><i>modulename</i> (str)</dt>
 <dd>
-module name to be added (string)
+module name to be added
 </dd>
 </dl>
 <a NAME="PackageModel.getModules" ID="PackageModel.getModules"></a>
@@ -328,7 +398,13 @@
 <dl>
 <dt>Return:</dt>
 <dd>
-list of module names (list of strings)
+list of module names
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+list of str
 </dd>
 </dl>
 <div align="right"><a href="#top">Up</a></div>
--- a/eric6/Documentation/Source/eric6.Graphics.PixmapDiagram.html	Sat May 01 14:27:38 2021 +0200
+++ b/eric6/Documentation/Source/eric6.Graphics.PixmapDiagram.html	Thu Jun 03 11:39:23 2021 +0200
@@ -168,17 +168,17 @@
 </p>
 <dl>
 
-<dt><i>pixmap</i></dt>
+<dt><i>pixmap</i> (str)</dt>
 <dd>
-filename of a graphics file to show (string)
+filename of a graphics file to show
 </dd>
-<dt><i>parent</i></dt>
+<dt><i>parent</i> (QWidget)</dt>
 <dd>
-parent widget of the view (QWidget)
+parent widget of the view
 </dd>
-<dt><i>name</i></dt>
+<dt><i>name</i> (str)</dt>
 <dd>
-name of the view widget (string)
+name of the view widget
 </dd>
 </dl>
 <a NAME="PixmapDiagram.__adjustScrollBar" ID="PixmapDiagram.__adjustScrollBar"></a>
@@ -190,13 +190,13 @@
 </p>
 <dl>
 
-<dt><i>scrollBar</i></dt>
+<dt><i>scrollBar</i> (QScrollBar)</dt>
 <dd>
-reference to the scrollbar object (QScrollBar)
+reference to the scrollbar object
 </dd>
-<dt><i>factor</i></dt>
+<dt><i>factor</i> (float)</dt>
 <dd>
-factor to adjust by (float)
+factor to adjust by
 </dd>
 </dl>
 <a NAME="PixmapDiagram.__doZoom" ID="PixmapDiagram.__doZoom"></a>
@@ -208,9 +208,9 @@
 </p>
 <dl>
 
-<dt><i>value</i></dt>
+<dt><i>value</i> (int)</dt>
 <dd>
-zoom value in percent (integer)
+zoom value in percent
 </dd>
 </dl>
 <a NAME="PixmapDiagram.__initActions" ID="PixmapDiagram.__initActions"></a>
@@ -243,15 +243,21 @@
 </p>
 <dl>
 
-<dt><i>zoom</i></dt>
+<dt><i>zoom</i> (int)</dt>
 <dd>
-zoom factor (integer)
+zoom factor
 </dd>
 </dl>
 <dl>
 <dt>Return:</dt>
 <dd>
-index of zoom factor (integer)
+index of zoom factor
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+int
 </dd>
 </dl>
 <a NAME="PixmapDiagram.__print" ID="PixmapDiagram.__print"></a>
@@ -263,9 +269,9 @@
 </p>
 <dl>
 
-<dt><i>printer</i></dt>
+<dt><i>printer</i> (QPrinter)</dt>
 <dd>
-reference to the printer object (QPrinter)
+reference to the printer object
 </dd>
 </dl>
 <a NAME="PixmapDiagram.__printDiagram" ID="PixmapDiagram.__printDiagram"></a>
@@ -291,9 +297,9 @@
 </p>
 <dl>
 
-<dt><i>coord</i></dt>
+<dt><i>coord</i> (QPoint)</dt>
 <dd>
-the position of the mouse pointer (QPoint)
+the position of the mouse pointer
 </dd>
 </dl>
 <a NAME="PixmapDiagram.__showPixmap" ID="PixmapDiagram.__showPixmap"></a>
@@ -305,15 +311,21 @@
 </p>
 <dl>
 
-<dt><i>filename</i></dt>
+<dt><i>filename</i> (str)</dt>
 <dd>
-name of the file to be shown (string)
+name of the file to be shown
 </dd>
 </dl>
 <dl>
 <dt>Return:</dt>
 <dd>
-flag indicating success (boolean)
+flag indicating success
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+bool
 </dd>
 </dl>
 <a NAME="PixmapDiagram.__zoom" ID="PixmapDiagram.__zoom"></a>
@@ -326,7 +338,13 @@
 <dl>
 <dt>Return:</dt>
 <dd>
-current zoom factor in percent (integer)
+current zoom factor in percent
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+int
 </dd>
 </dl>
 <a NAME="PixmapDiagram.__zoomIn" ID="PixmapDiagram.__zoomIn"></a>
@@ -359,15 +377,21 @@
 </p>
 <dl>
 
-<dt><i>evt</i></dt>
+<dt><i>evt</i> (QEvent)</dt>
 <dd>
-reference to the event (QEvent)
+reference to the event
 </dd>
 </dl>
 <dl>
 <dt>Return:</dt>
 <dd>
-flag indicating, if the event was handled (boolean)
+flag indicating, if the event was handled
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+bool
 </dd>
 </dl>
 <a NAME="PixmapDiagram.gestureEvent" ID="PixmapDiagram.gestureEvent"></a>
@@ -379,9 +403,9 @@
 </p>
 <dl>
 
-<dt><i>evt</i></dt>
+<dt><i>evt</i> (QGestureEvent)</dt>
 <dd>
-reference to the gesture event (QGestureEvent
+reference to the gesture event
 </dd>
 </dl>
 <a NAME="PixmapDiagram.getDiagramName" ID="PixmapDiagram.getDiagramName"></a>
@@ -397,6 +421,12 @@
 name for the diagram
 </dd>
 </dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+str
+</dd>
+</dl>
 <a NAME="PixmapDiagram.getStatus" ID="PixmapDiagram.getStatus"></a>
 <h4>PixmapDiagram.getStatus</h4>
 <b>getStatus</b>(<i></i>)
@@ -407,7 +437,13 @@
 <dl>
 <dt>Return:</dt>
 <dd>
-flag indicating a successful pixmap loading (boolean)
+flag indicating a successful pixmap loading
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+bool
 </dd>
 </dl>
 <a NAME="PixmapDiagram.wheelEvent" ID="PixmapDiagram.wheelEvent"></a>
@@ -419,9 +455,9 @@
 </p>
 <dl>
 
-<dt><i>evt</i></dt>
+<dt><i>evt</i> (QWheelEvent)</dt>
 <dd>
-reference to the wheel event (QWheelEvent)
+reference to the wheel event
 </dd>
 </dl>
 <div align="right"><a href="#top">Up</a></div>
--- a/eric6/Documentation/Source/eric6.Graphics.SvgDiagram.html	Sat May 01 14:27:38 2021 +0200
+++ b/eric6/Documentation/Source/eric6.Graphics.SvgDiagram.html	Thu Jun 03 11:39:23 2021 +0200
@@ -160,17 +160,17 @@
 </p>
 <dl>
 
-<dt><i>svgFile</i></dt>
+<dt><i>svgFile</i> (str)</dt>
 <dd>
-filename of a SVG graphics file to show (string)
+filename of a SVG graphics file to show
 </dd>
-<dt><i>parent</i></dt>
+<dt><i>parent</i> (QWidget)</dt>
 <dd>
-parent widget of the view (QWidget)
+parent widget of the view
 </dd>
-<dt><i>name</i></dt>
+<dt><i>name</i> (str)</dt>
 <dd>
-name of the view widget (string)
+name of the view widget
 </dd>
 </dl>
 <a NAME="SvgDiagram.__adjustScrollBar" ID="SvgDiagram.__adjustScrollBar"></a>
@@ -182,13 +182,13 @@
 </p>
 <dl>
 
-<dt><i>scrollBar</i></dt>
+<dt><i>scrollBar</i> (QScrollBar)</dt>
 <dd>
-reference to the scrollbar object (QScrollBar)
+reference to the scrollbar object
 </dd>
-<dt><i>factor</i></dt>
+<dt><i>factor</i> (float)</dt>
 <dd>
-factor to adjust by (float)
+factor to adjust by
 </dd>
 </dl>
 <a NAME="SvgDiagram.__doZoom" ID="SvgDiagram.__doZoom"></a>
@@ -200,9 +200,9 @@
 </p>
 <dl>
 
-<dt><i>value</i></dt>
+<dt><i>value</i> (int)</dt>
 <dd>
-zoom value in percent (integer)
+zoom value in percent
 </dd>
 </dl>
 <a NAME="SvgDiagram.__initActions" ID="SvgDiagram.__initActions"></a>
@@ -235,15 +235,21 @@
 </p>
 <dl>
 
-<dt><i>zoom</i></dt>
+<dt><i>zoom</i> (int)</dt>
 <dd>
-zoom factor (integer)
+zoom factor
 </dd>
 </dl>
 <dl>
 <dt>Return:</dt>
 <dd>
-index of zoom factor (integer)
+index of zoom factor
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+int
 </dd>
 </dl>
 <a NAME="SvgDiagram.__print" ID="SvgDiagram.__print"></a>
@@ -255,9 +261,9 @@
 </p>
 <dl>
 
-<dt><i>printer</i></dt>
+<dt><i>printer</i> (QPrinter)</dt>
 <dd>
-reference to the printer object (QPrinter)
+reference to the printer object
 </dd>
 </dl>
 <a NAME="SvgDiagram.__printDiagram" ID="SvgDiagram.__printDiagram"></a>
@@ -283,9 +289,9 @@
 </p>
 <dl>
 
-<dt><i>coord</i></dt>
+<dt><i>coord</i> (QPoint)</dt>
 <dd>
-the position of the mouse pointer (QPoint)
+the position of the mouse pointer
 </dd>
 </dl>
 <a NAME="SvgDiagram.__zoom" ID="SvgDiagram.__zoom"></a>
@@ -298,7 +304,13 @@
 <dl>
 <dt>Return:</dt>
 <dd>
-current zoom factor in percent (integer)
+current zoom factor in percent
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+int
 </dd>
 </dl>
 <a NAME="SvgDiagram.__zoomIn" ID="SvgDiagram.__zoomIn"></a>
@@ -331,15 +343,21 @@
 </p>
 <dl>
 
-<dt><i>evt</i></dt>
+<dt><i>evt</i> (QEvent)</dt>
 <dd>
-reference to the event (QEvent)
+reference to the event
 </dd>
 </dl>
 <dl>
 <dt>Return:</dt>
 <dd>
-flag indicating, if the event was handled (boolean)
+flag indicating, if the event was handled
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+bool
 </dd>
 </dl>
 <a NAME="SvgDiagram.gestureEvent" ID="SvgDiagram.gestureEvent"></a>
@@ -351,9 +369,9 @@
 </p>
 <dl>
 
-<dt><i>evt</i></dt>
+<dt><i>evt</i> (QGestureEvent)</dt>
 <dd>
-reference to the gesture event (QGestureEvent
+reference to the gesture event
 </dd>
 </dl>
 <a NAME="SvgDiagram.getDiagramName" ID="SvgDiagram.getDiagramName"></a>
@@ -369,6 +387,12 @@
 name for the diagram
 </dd>
 </dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+str
+</dd>
+</dl>
 <a NAME="SvgDiagram.wheelEvent" ID="SvgDiagram.wheelEvent"></a>
 <h4>SvgDiagram.wheelEvent</h4>
 <b>wheelEvent</b>(<i>evt</i>)
@@ -378,9 +402,9 @@
 </p>
 <dl>
 
-<dt><i>evt</i></dt>
+<dt><i>evt</i> (QWheelEvent)</dt>
 <dd>
-reference to the wheel event (QWheelEvent)
+reference to the wheel event
 </dd>
 </dl>
 <div align="right"><a href="#top">Up</a></div>
--- a/eric6/Documentation/Source/eric6.Graphics.UMLClassDiagramBuilder.html	Sat May 01 14:27:38 2021 +0200
+++ b/eric6/Documentation/Source/eric6.Graphics.UMLClassDiagramBuilder.html	Thu Jun 03 11:39:23 2021 +0200
@@ -97,6 +97,10 @@
 <td>Public method to build the class shapes of the class diagram.</td>
 </tr>
 <tr>
+<td><a href="#UMLClassDiagramBuilder.fromDict">fromDict</a></td>
+<td>Public method to populate the class with data persisted by 'toDict()'.</td>
+</tr>
+<tr>
 <td><a href="#UMLClassDiagramBuilder.getPersistenceData">getPersistenceData</a></td>
 <td>Public method to get a string for data to be persisted.</td>
 </tr>
@@ -108,6 +112,10 @@
 <td><a href="#UMLClassDiagramBuilder.parsePersistenceData">parsePersistenceData</a></td>
 <td>Public method to parse persisted data.</td>
 </tr>
+<tr>
+<td><a href="#UMLClassDiagramBuilder.toDict">toDict</a></td>
+<td>Public method to collect data to be persisted.</td>
+</tr>
 </table>
 <h3>Static Methods</h3>
 
@@ -124,26 +132,25 @@
 </p>
 <dl>
 
-<dt><i>dialog</i></dt>
+<dt><i>dialog</i> (UMLDialog)</dt>
 <dd>
-reference to the UML dialog (UMLDialog)
+reference to the UML dialog
 </dd>
-<dt><i>view</i></dt>
+<dt><i>view</i> (UMLGraphicsView)</dt>
 <dd>
-reference to the view object (UMLGraphicsView)
+reference to the view object
 </dd>
-<dt><i>project</i></dt>
+<dt><i>project</i> (Project)</dt>
 <dd>
-reference to the project object (Project)
+reference to the project object
 </dd>
-<dt><i>file</i></dt>
+<dt><i>file</i> (str)</dt>
 <dd>
-file name of a python module to be shown (string)
+file name of a python module to be shown
 </dd>
-<dt><i>noAttrs</i></dt>
+<dt><i>noAttrs</i> (bool)</dt>
 <dd>
 flag indicating, that no attributes should be shown
-            (boolean)
 </dd>
 </dl>
 <a NAME="UMLClassDiagramBuilder.__addExternalClass" ID="UMLClassDiagramBuilder.__addExternalClass"></a>
@@ -159,17 +166,17 @@
 </p>
 <dl>
 
-<dt><i>_class</i></dt>
+<dt><i>_class</i> (ModuleParser.Class)</dt>
 <dd>
-class to be shown (string)
+class to be shown
 </dd>
-<dt><i>x</i></dt>
+<dt><i>x</i> (float)</dt>
 <dd>
-x-coordinate (float)
+x-coordinate
 </dd>
-<dt><i>y</i></dt>
+<dt><i>y</i> (float)</dt>
 <dd>
-y-coordinate (float)
+y-coordinate
 </dd>
 </dl>
 <a NAME="UMLClassDiagramBuilder.__addLocalClass" ID="UMLClassDiagramBuilder.__addLocalClass"></a>
@@ -181,25 +188,25 @@
 </p>
 <dl>
 
-<dt><i>className</i></dt>
+<dt><i>className</i> (str)</dt>
 <dd>
-name of the class to be as a dictionary key (string)
+name of the class to be as a dictionary key
 </dd>
-<dt><i>_class</i></dt>
+<dt><i>_class</i> (ModuleParser.Class)</dt>
 <dd>
-class to be shown (ModuleParser.Class)
+class to be shown
 </dd>
-<dt><i>x</i></dt>
+<dt><i>x</i> (float)</dt>
 <dd>
-x-coordinate (float)
+x-coordinate
 </dd>
-<dt><i>y</i></dt>
+<dt><i>y</i> (float)</dt>
 <dd>
-y-coordinate (float)
+y-coordinate
 </dd>
-<dt><i>isRbModule</i></dt>
+<dt><i>isRbModule</i> (bool)</dt>
 <dd>
-flag indicating a Ruby module (boolean)
+flag indicating a Ruby module
 </dd>
 </dl>
 <a NAME="UMLClassDiagramBuilder.__arrangeClasses" ID="UMLClassDiagramBuilder.__arrangeClasses"></a>
@@ -214,18 +221,18 @@
 </p>
 <dl>
 
-<dt><i>nodes</i></dt>
+<dt><i>nodes</i> (list of str)</dt>
 <dd>
 list of nodes to arrange
 </dd>
-<dt><i>routes</i></dt>
+<dt><i>routes</i> (list of tuple of (str, str))</dt>
 <dd>
 list of routes
 </dd>
-<dt><i>whiteSpaceFactor</i></dt>
+<dt><i>whiteSpaceFactor</i> (float)</dt>
 <dd>
 factor to increase whitespace between
-            items (float)
+            items
 </dd>
 </dl>
 <a NAME="UMLClassDiagramBuilder.__createAssociations" ID="UMLClassDiagramBuilder.__createAssociations"></a>
@@ -237,7 +244,7 @@
 </p>
 <dl>
 
-<dt><i>routes</i></dt>
+<dt><i>routes</i> (list of tuple of (str, str))</dt>
 <dd>
 list of relationsships
 </dd>
@@ -251,15 +258,21 @@
 </p>
 <dl>
 
-<dt><i>name</i></dt>
+<dt><i>name</i> (str)</dt>
 <dd>
-name of the shape (string)
+name of the shape
 </dd>
 </dl>
 <dl>
 <dt>Return:</dt>
 <dd>
-shape (QGraphicsItem)
+shape
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+QGraphicsItem
 </dd>
 </dl>
 <a NAME="UMLClassDiagramBuilder.buildDiagram" ID="UMLClassDiagramBuilder.buildDiagram"></a>
@@ -272,6 +285,37 @@
 <p>
         The algorithm is borrowed from Boa Constructor.
 </p>
+<a NAME="UMLClassDiagramBuilder.fromDict" ID="UMLClassDiagramBuilder.fromDict"></a>
+<h4>UMLClassDiagramBuilder.fromDict</h4>
+<b>fromDict</b>(<i>version, data</i>)
+
+<p>
+        Public method to populate the class with data persisted by 'toDict()'.
+</p>
+<dl>
+
+<dt><i>version</i> (str)</dt>
+<dd>
+version of the data
+</dd>
+<dt><i>data</i> (dict)</dt>
+<dd>
+dictionary containing the persisted data
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+tuple containing a flag indicating success and an info
+            message in case the diagram belongs to a different project
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+tuple of (bool, str)
+</dd>
+</dl>
 <a NAME="UMLClassDiagramBuilder.getPersistenceData" ID="UMLClassDiagramBuilder.getPersistenceData"></a>
 <h4>UMLClassDiagramBuilder.getPersistenceData</h4>
 <b>getPersistenceData</b>(<i></i>)
@@ -282,7 +326,13 @@
 <dl>
 <dt>Return:</dt>
 <dd>
-persisted data string (string)
+persisted data string
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+str
 </dd>
 </dl>
 <a NAME="UMLClassDiagramBuilder.initialize" ID="UMLClassDiagramBuilder.initialize"></a>
@@ -301,19 +351,44 @@
 </p>
 <dl>
 
-<dt><i>version</i></dt>
+<dt><i>version</i> (str)</dt>
 <dd>
-version of the data (string)
+version of the data
 </dd>
-<dt><i>data</i></dt>
+<dt><i>data</i> (str)</dt>
 <dd>
-persisted data to be parsed (string)
+persisted data to be parsed
 </dd>
 </dl>
 <dl>
 <dt>Return:</dt>
 <dd>
-flag indicating success (boolean)
+flag indicating success
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+bool
+</dd>
+</dl>
+<a NAME="UMLClassDiagramBuilder.toDict" ID="UMLClassDiagramBuilder.toDict"></a>
+<h4>UMLClassDiagramBuilder.toDict</h4>
+<b>toDict</b>(<i></i>)
+
+<p>
+        Public method to collect data to be persisted.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+dictionary containing data to be persisted
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+dict
 </dd>
 </dl>
 <div align="right"><a href="#top">Up</a></div>
--- a/eric6/Documentation/Source/eric6.Graphics.UMLDiagramBuilder.html	Sat May 01 14:27:38 2021 +0200
+++ b/eric6/Documentation/Source/eric6.Graphics.UMLDiagramBuilder.html	Thu Jun 03 11:39:23 2021 +0200
@@ -77,6 +77,14 @@
 <td>Public method to build the diagram.</td>
 </tr>
 <tr>
+<td><a href="#UMLDiagramBuilder.buildErrorMessage">buildErrorMessage</a></td>
+<td>Public method to build an error string to be included in the scene.</td>
+</tr>
+<tr>
+<td><a href="#UMLDiagramBuilder.fromDict">fromDict</a></td>
+<td>Public method to populate the class with data persisted by 'toDict()'.</td>
+</tr>
+<tr>
 <td><a href="#UMLDiagramBuilder.getPersistenceData">getPersistenceData</a></td>
 <td>Public method to get a string for data to be persisted.</td>
 </tr>
@@ -88,6 +96,10 @@
 <td><a href="#UMLDiagramBuilder.parsePersistenceData">parsePersistenceData</a></td>
 <td>Public method to parse persisted data.</td>
 </tr>
+<tr>
+<td><a href="#UMLDiagramBuilder.toDict">toDict</a></td>
+<td>Public method to collect data to be persisted.</td>
+</tr>
 </table>
 <h3>Static Methods</h3>
 
@@ -104,17 +116,17 @@
 </p>
 <dl>
 
-<dt><i>dialog</i></dt>
+<dt><i>dialog</i> (UMLDialog)</dt>
 <dd>
-reference to the UML dialog (UMLDialog)
+reference to the UML dialog
 </dd>
-<dt><i>view</i></dt>
+<dt><i>view</i> (UMLGraphicsView)</dt>
 <dd>
-reference to the view object (UMLGraphicsView)
+reference to the view object
 </dd>
-<dt><i>project</i></dt>
+<dt><i>project</i> (Project)</dt>
 <dd>
-reference to the project object (Project)
+reference to the project object
 </dd>
 </dl>
 <a NAME="UMLDiagramBuilder.buildDiagram" ID="UMLDiagramBuilder.buildDiagram"></a>
@@ -135,6 +147,63 @@
             must be subclassed
 </dd>
 </dl>
+<a NAME="UMLDiagramBuilder.buildErrorMessage" ID="UMLDiagramBuilder.buildErrorMessage"></a>
+<h4>UMLDiagramBuilder.buildErrorMessage</h4>
+<b>buildErrorMessage</b>(<i>msg</i>)
+
+<p>
+        Public method to build an error string to be included in the scene.
+</p>
+<dl>
+
+<dt><i>msg</i> (str)</dt>
+<dd>
+error message
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+prepared error string
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+str
+</dd>
+</dl>
+<a NAME="UMLDiagramBuilder.fromDict" ID="UMLDiagramBuilder.fromDict"></a>
+<h4>UMLDiagramBuilder.fromDict</h4>
+<b>fromDict</b>(<i>version, data</i>)
+
+<p>
+        Public method to populate the class with data persisted by 'toDict()'.
+</p>
+<dl>
+
+<dt><i>version</i> (str)</dt>
+<dd>
+version of the data
+</dd>
+<dt><i>data</i> (dict)</dt>
+<dd>
+dictionary containing the persisted data
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+tuple containing a flag indicating success and an info
+            message in case the diagram belongs to a different project
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+tuple of (bool, str)
+</dd>
+</dl>
 <a NAME="UMLDiagramBuilder.getPersistenceData" ID="UMLDiagramBuilder.getPersistenceData"></a>
 <h4>UMLDiagramBuilder.getPersistenceData</h4>
 <b>getPersistenceData</b>(<i></i>)
@@ -145,7 +214,13 @@
 <dl>
 <dt>Return:</dt>
 <dd>
-persisted data string (string)
+persisted data string
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+str
 </dd>
 </dl>
 <a NAME="UMLDiagramBuilder.initialize" ID="UMLDiagramBuilder.initialize"></a>
@@ -164,19 +239,44 @@
 </p>
 <dl>
 
-<dt><i>version</i></dt>
+<dt><i>version</i> (str)</dt>
 <dd>
-version of the data (string)
+version of the data
 </dd>
-<dt><i>data</i></dt>
+<dt><i>data</i> (str)</dt>
 <dd>
-persisted data to be parsed (string)
+persisted data to be parsed
 </dd>
 </dl>
 <dl>
 <dt>Return:</dt>
 <dd>
-flag indicating success (boolean)
+flag indicating success
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+bool
+</dd>
+</dl>
+<a NAME="UMLDiagramBuilder.toDict" ID="UMLDiagramBuilder.toDict"></a>
+<h4>UMLDiagramBuilder.toDict</h4>
+<b>toDict</b>(<i></i>)
+
+<p>
+        Public method to collect data to be persisted.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+dictionary containing data to be persisted
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+dict
 </dd>
 </dl>
 <div align="right"><a href="#top">Up</a></div>
--- a/eric6/Documentation/Source/eric6.Graphics.UMLDialog.html	Sat May 01 14:27:38 2021 +0200
+++ b/eric6/Documentation/Source/eric6.Graphics.UMLDialog.html	Thu Jun 03 11:39:23 2021 +0200
@@ -38,6 +38,10 @@
 <td><a href="#UMLDialog">UMLDialog</a></td>
 <td>Class implementing a dialog showing UML like diagrams.</td>
 </tr>
+<tr>
+<td><a href="#UMLDialogType">UMLDialogType</a></td>
+<td>Class defining the UML dialog types.</td>
+</tr>
 </table>
 <h3>Functions</h3>
 
@@ -57,7 +61,7 @@
 <h3>Class Attributes</h3>
 
 <table>
-<tr><td>ApplicationDiagram</td></tr><tr><td>ClassDiagram</td></tr><tr><td>FileVersions</td></tr><tr><td>ImportsDiagram</td></tr><tr><td>NoDiagram</td></tr><tr><td>PackageDiagram</td></tr>
+<tr><td>FileVersions</td></tr><tr><td>JsonFileVersions</td></tr><tr><td>UMLDialogType2String</td></tr>
 </table>
 <h3>Class Methods</h3>
 
@@ -77,6 +81,10 @@
 <td>Private method to instantiate a diagram builder object.</td>
 </tr>
 <tr>
+<td><a href="#UMLDialog.__getDiagramTitel">__getDiagramTitel</a></td>
+<td>Private method to get a textual description for the diagram type.</td>
+</tr>
+<tr>
 <td><a href="#UMLDialog.__initActions">__initActions</a></td>
 <td>Private slot to initialize the actions.</td>
 </tr>
@@ -85,8 +93,16 @@
 <td>Private slot to initialize the toolbars.</td>
 </tr>
 <tr>
+<td><a href="#UMLDialog.__readJsonGraphicsFile">__readJsonGraphicsFile</a></td>
+<td>Private method to read an eric graphics file using the JSON based file format.</td>
+</tr>
+<tr>
+<td><a href="#UMLDialog.__readLineBasedGraphicsFile">__readLineBasedGraphicsFile</a></td>
+<td>Private method to read an eric graphics file using the old line based file format.</td>
+</tr>
+<tr>
 <td><a href="#UMLDialog.__relayout">__relayout</a></td>
-<td>Private method to relayout the diagram.</td>
+<td>Private method to re-layout the diagram.</td>
 </tr>
 <tr>
 <td><a href="#UMLDialog.__save">__save</a></td>
@@ -101,6 +117,14 @@
 <td>Private slot to show a message dialog indicating an invalid data file.</td>
 </tr>
 <tr>
+<td><a href="#UMLDialog.__writeJsonGraphicsFile">__writeJsonGraphicsFile</a></td>
+<td>Private method to write an eric graphics file using the JSON based file format.</td>
+</tr>
+<tr>
+<td><a href="#UMLDialog.__writeLineBasedGraphicsFile">__writeLineBasedGraphicsFile</a></td>
+<td>Private method to write an eric graphics file using the old line based file format.</td>
+</tr>
+<tr>
 <td><a href="#UMLDialog.load">load</a></td>
 <td>Public method to load a diagram from a file.</td>
 </tr>
@@ -124,29 +148,28 @@
 </p>
 <dl>
 
-<dt><i>diagramType</i></dt>
+<dt><i>diagramType</i> (UMLDialogType)</dt>
 <dd>
-type of the diagram (one of ApplicationDiagram,
-            ClassDiagram, ImportsDiagram, NoDiagram, PackageDiagram)
+type of the diagram
 </dd>
-<dt><i>project</i></dt>
+<dt><i>project</i> (Project)</dt>
 <dd>
-reference to the project object (Project)
+reference to the project object
 </dd>
-<dt><i>path</i></dt>
+<dt><i>path</i> (str)</dt>
 <dd>
-file or directory path to build the diagram from (string)
+file or directory path to build the diagram from
 </dd>
-<dt><i>parent</i></dt>
+<dt><i>parent</i> (QWidget)</dt>
 <dd>
-parent widget of the dialog (QWidget)
+parent widget of the dialog
 </dd>
-<dt><i>initBuilder</i></dt>
+<dt><i>initBuilder</i> (bool)</dt>
 <dd>
 flag indicating to initialize the diagram
-            builder (boolean)
+            builder
 </dd>
-<dt><i>kwargs=</i></dt>
+<dt><i>kwargs=</i> (dict)</dt>
 <dd>
 diagram specific data
 </dd>
@@ -160,17 +183,15 @@
 </p>
 <dl>
 
-<dt><i>diagramType</i></dt>
+<dt><i>diagramType</i> (UMLDialogType)</dt>
 <dd>
 type of the diagram
-            (one of ApplicationDiagram, ClassDiagram, ImportsDiagram,
-            PackageDiagram)
 </dd>
-<dt><i>path</i></dt>
+<dt><i>path</i> (str)</dt>
 <dd>
-file or directory path to build the diagram from (string)
+file or directory path to build the diagram from
 </dd>
-<dt><i>kwargs=</i></dt>
+<dt><i>kwargs=</i> (dict)</dt>
 <dd>
 diagram specific data
 </dd>
@@ -182,10 +203,35 @@
 </dd>
 </dl>
 <dl>
+<dt>Return Type:</dt>
+<dd>
+UMLDiagramBuilder
+</dd>
+</dl>
+<a NAME="UMLDialog.__getDiagramTitel" ID="UMLDialog.__getDiagramTitel"></a>
+<h4>UMLDialog.__getDiagramTitel</h4>
+<b>__getDiagramTitel</b>(<i>diagramType</i>)
 
-<dt>Raises <b>ValueError</b>:</dt>
+<p>
+        Private method to get a textual description for the diagram type.
+</p>
+<dl>
+
+<dt><i>diagramType</i> (str)</dt>
 <dd>
-raised to indicate an illegal diagram type
+diagram type string
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+titel of the diagram
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+str
 </dd>
 </dl>
 <a NAME="UMLDialog.__initActions" ID="UMLDialog.__initActions"></a>
@@ -202,12 +248,66 @@
 <p>
         Private slot to initialize the toolbars.
 </p>
+<a NAME="UMLDialog.__readJsonGraphicsFile" ID="UMLDialog.__readJsonGraphicsFile"></a>
+<h4>UMLDialog.__readJsonGraphicsFile</h4>
+<b>__readJsonGraphicsFile</b>(<i>filename</i>)
+
+<p>
+        Private method to read an eric graphics file using the JSON based
+        file format.
+</p>
+<dl>
+
+<dt><i>filename</i> (str)</dt>
+<dd>
+name of the file to be read
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+flag indicating a successful read
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+bool
+</dd>
+</dl>
+<a NAME="UMLDialog.__readLineBasedGraphicsFile" ID="UMLDialog.__readLineBasedGraphicsFile"></a>
+<h4>UMLDialog.__readLineBasedGraphicsFile</h4>
+<b>__readLineBasedGraphicsFile</b>(<i>filename</i>)
+
+<p>
+        Private method to read an eric graphics file using the old line
+        based file format.
+</p>
+<dl>
+
+<dt><i>filename</i> (str)</dt>
+<dd>
+name of the file to be read
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+flag indicating success
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+bool
+</dd>
+</dl>
 <a NAME="UMLDialog.__relayout" ID="UMLDialog.__relayout"></a>
 <h4>UMLDialog.__relayout</h4>
 <b>__relayout</b>(<i></i>)
 
 <p>
-        Private method to relayout the diagram.
+        Private method to re-layout the diagram.
 </p>
 <a NAME="UMLDialog.__save" ID="UMLDialog.__save"></a>
 <h4>UMLDialog.__save</h4>
@@ -225,9 +325,9 @@
 </p>
 <dl>
 
-<dt><i>filename</i></dt>
+<dt><i>filename</i> (str)</dt>
 <dd>
-name of the file to write to (string)
+name of the file to write to
 </dd>
 </dl>
 <a NAME="UMLDialog.__showInvalidDataMessage" ID="UMLDialog.__showInvalidDataMessage"></a>
@@ -239,26 +339,93 @@
 </p>
 <dl>
 
-<dt><i>filename</i></dt>
+<dt><i>filename</i> (str)</dt>
+<dd>
+name of the file containing the invalid data
+</dd>
+<dt><i>linenum</i> (int)</dt>
 <dd>
-name of the file containing the invalid data (string)
+number of the invalid line
+</dd>
+</dl>
+<a NAME="UMLDialog.__writeJsonGraphicsFile" ID="UMLDialog.__writeJsonGraphicsFile"></a>
+<h4>UMLDialog.__writeJsonGraphicsFile</h4>
+<b>__writeJsonGraphicsFile</b>(<i>filename</i>)
+
+<p>
+        Private method to write an eric graphics file using the JSON based
+        file format.
+</p>
+<dl>
+
+<dt><i>filename</i> (str)</dt>
+<dd>
+name of the file to write to
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+flag indicating a successful write
 </dd>
-<dt><i>linenum</i></dt>
+</dl>
+<dl>
+<dt>Return Type:</dt>
 <dd>
-number of the invalid line (integer)
+bool
+</dd>
+</dl>
+<a NAME="UMLDialog.__writeLineBasedGraphicsFile" ID="UMLDialog.__writeLineBasedGraphicsFile"></a>
+<h4>UMLDialog.__writeLineBasedGraphicsFile</h4>
+<b>__writeLineBasedGraphicsFile</b>(<i>filename</i>)
+
+<p>
+        Private method to write an eric graphics file using the old line
+        based file format.
+</p>
+<dl>
+
+<dt><i>filename</i> (str)</dt>
+<dd>
+name of the file to write to
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+flag indicating a successful write
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+bool
 </dd>
 </dl>
 <a NAME="UMLDialog.load" ID="UMLDialog.load"></a>
 <h4>UMLDialog.load</h4>
-<b>load</b>(<i></i>)
+<b>load</b>(<i>filename=""</i>)
 
 <p>
         Public method to load a diagram from a file.
 </p>
 <dl>
+
+<dt><i>filename</i> (str)</dt>
+<dd>
+name of the file to be loaded
+</dd>
+</dl>
+<dl>
 <dt>Return:</dt>
 <dd>
-flag indicating success (boolean)
+flag indicating success
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+bool
 </dd>
 </dl>
 <a NAME="UMLDialog.show" ID="UMLDialog.show"></a>
@@ -270,12 +437,44 @@
 </p>
 <dl>
 
-<dt><i>fromFile</i></dt>
+<dt><i>fromFile</i> (bool)</dt>
 <dd>
 flag indicating, that the diagram was loaded
-            from file (boolean)
+            from file
 </dd>
 </dl>
 <div align="right"><a href="#top">Up</a></div>
 <hr />
+<hr />
+<a NAME="UMLDialogType" ID="UMLDialogType"></a>
+<h2>UMLDialogType</h2>
+
+<p>
+    Class defining the UML dialog types.
+</p>
+<h3>Derived from</h3>
+enum.Enum
+<h3>Class Attributes</h3>
+
+<table>
+<tr><td>APPLICATION_DIAGRAM</td></tr><tr><td>CLASS_DIAGRAM</td></tr><tr><td>IMPORTS_DIAGRAM</td></tr><tr><td>NO_DIAGRAM</td></tr><tr><td>PACKAGE_DIAGRAM</td></tr>
+</table>
+<h3>Class Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Static Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+
+<div align="right"><a href="#top">Up</a></div>
+<hr />
 </body></html>
\ No newline at end of file
--- a/eric6/Documentation/Source/eric6.Graphics.UMLGraphicsView.html	Sat May 01 14:27:38 2021 +0200
+++ b/eric6/Documentation/Source/eric6.Graphics.UMLGraphicsView.html	Thu Jun 03 11:39:23 2021 +0200
@@ -158,6 +158,10 @@
 <td>Public method to find an UML item based on its name.</td>
 </tr>
 <tr>
+<td><a href="#UMLGraphicsView.fromDict">fromDict</a></td>
+<td>Public method to populate the class with data persisted by 'toDict()'.</td>
+</tr>
+<tr>
 <td><a href="#UMLGraphicsView.gestureEvent">gestureEvent</a></td>
 <td>Protected method handling gesture events.</td>
 </tr>
@@ -206,6 +210,14 @@
 <td>Public slot to set the diagram name.</td>
 </tr>
 <tr>
+<td><a href="#UMLGraphicsView.setLayoutActionsEnabled">setLayoutActionsEnabled</a></td>
+<td>Public method to enable or disable the layout related actions.</td>
+</tr>
+<tr>
+<td><a href="#UMLGraphicsView.toDict">toDict</a></td>
+<td>Public method to collect data to be persisted.</td>
+</tr>
+<tr>
 <td><a href="#UMLGraphicsView.wheelEvent">wheelEvent</a></td>
 <td>Protected method to handle wheel events.</td>
 </tr>
@@ -225,13 +237,13 @@
 </p>
 <dl>
 
-<dt><i>scene</i></dt>
+<dt><i>scene</i> (QGraphicsScene)</dt>
 <dd>
-reference to the scene object (QGraphicsScene)
+reference to the scene object
 </dd>
-<dt><i>parent</i></dt>
+<dt><i>parent</i> (QWidget)</dt>
 <dd>
-parent widget of the view (QWidget)
+parent widget of the view
 </dd>
 </dl>
 <a NAME="UMLGraphicsView.__alignShapes" ID="UMLGraphicsView.__alignShapes"></a>
@@ -243,9 +255,9 @@
 </p>
 <dl>
 
-<dt><i>alignment</i></dt>
+<dt><i>alignment</i> (Qt.AlignmentFlag)</dt>
 <dd>
-alignment type (Qt.AlignmentFlag)
+alignment type
 </dd>
 </dl>
 <a NAME="UMLGraphicsView.__checkSizeActions" ID="UMLGraphicsView.__checkSizeActions"></a>
@@ -306,15 +318,21 @@
 </p>
 <dl>
 
-<dt><i>items</i></dt>
+<dt><i>items</i> (list of UMLItem)</dt>
 <dd>
-list of items to operate on (list of UMLItem)
+list of items to operate on
 </dd>
 </dl>
 <dl>
 <dt>Return:</dt>
 <dd>
-bounding rectangle (QRectF)
+bounding rectangle
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+QRectF
 </dd>
 </dl>
 <a NAME="UMLGraphicsView.__printPreviewPrint" ID="UMLGraphicsView.__printPreviewPrint"></a>
@@ -326,9 +344,9 @@
 </p>
 <dl>
 
-<dt><i>printer</i></dt>
+<dt><i>printer</i> (QPrinter)</dt>
 <dd>
-reference to the printer object (QPrinter)
+reference to the printer object
 </dd>
 </dl>
 <a NAME="UMLGraphicsView.__relayout" ID="UMLGraphicsView.__relayout"></a>
@@ -354,9 +372,9 @@
 </p>
 <dl>
 
-<dt><i>areas</i></dt>
+<dt><i>areas</i> (list of QRectF)</dt>
 <dd>
-list of rectangles that contain changes (list of QRectF)
+list of rectangles that contain changes
 </dd>
 </dl>
 <a NAME="UMLGraphicsView.__setSize" ID="UMLGraphicsView.__setSize"></a>
@@ -375,10 +393,10 @@
 </p>
 <dl>
 
-<dt><i>limit</i></dt>
+<dt><i>limit</i> (bool)</dt>
 <dd>
 flag indicating to limit the scene to the
-            initial size (boolean)
+            initial size
 </dd>
 </dl>
 <a NAME="UMLGraphicsView.event" ID="UMLGraphicsView.event"></a>
@@ -390,15 +408,21 @@
 </p>
 <dl>
 
-<dt><i>evt</i></dt>
+<dt><i>evt</i> (QEvent)</dt>
 <dd>
-reference to the event (QEvent)
+reference to the event
 </dd>
 </dl>
 <dl>
 <dt>Return:</dt>
 <dd>
-flag indicating, if the event was handled (boolean)
+flag indicating, if the event was handled
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+bool
 </dd>
 </dl>
 <a NAME="UMLGraphicsView.filteredItems" ID="UMLGraphicsView.filteredItems"></a>
@@ -410,20 +434,25 @@
 </p>
 <dl>
 
-<dt><i>items</i></dt>
+<dt><i>items</i> (QGraphicsItem)</dt>
 <dd>
 list of items as returned by the scene object
-            (QGraphicsItem)
 </dd>
-<dt><i>itemType</i></dt>
+<dt><i>itemType</i> (class)</dt>
 <dd>
-type to be filtered (class)
+type to be filtered
 </dd>
 </dl>
 <dl>
 <dt>Return:</dt>
 <dd>
-list of interesting collision items (QGraphicsItem)
+list of interesting collision items
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+QGraphicsItem
 </dd>
 </dl>
 <a NAME="UMLGraphicsView.findItem" ID="UMLGraphicsView.findItem"></a>
@@ -435,15 +464,21 @@
 </p>
 <dl>
 
-<dt><i>itemId</i></dt>
+<dt><i>itemId</i> (int)</dt>
 <dd>
-of the item to search for (integer)
+of the item to search for
 </dd>
 </dl>
 <dl>
 <dt>Return:</dt>
 <dd>
-item found (UMLItem) or None
+item found or None
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+UMLItem
 </dd>
 </dl>
 <a NAME="UMLGraphicsView.findItemByName" ID="UMLGraphicsView.findItemByName"></a>
@@ -455,15 +490,51 @@
 </p>
 <dl>
 
-<dt><i>name</i></dt>
+<dt><i>name</i> (str)</dt>
 <dd>
-name to look for (string)
+name to look for
 </dd>
 </dl>
 <dl>
 <dt>Return:</dt>
 <dd>
-item found (UMLItem) or None
+item found or None
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+UMLItem
+</dd>
+</dl>
+<a NAME="UMLGraphicsView.fromDict" ID="UMLGraphicsView.fromDict"></a>
+<h4>UMLGraphicsView.fromDict</h4>
+<b>fromDict</b>(<i>version, data</i>)
+
+<p>
+        Public method to populate the class with data persisted by 'toDict()'.
+</p>
+<dl>
+
+<dt><i>version</i> (str)</dt>
+<dd>
+version of the data
+</dd>
+<dt><i>data</i> (dict)</dt>
+<dd>
+dictionary containing the persisted data
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+flag indicating success
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+bool
 </dd>
 </dl>
 <a NAME="UMLGraphicsView.gestureEvent" ID="UMLGraphicsView.gestureEvent"></a>
@@ -475,9 +546,9 @@
 </p>
 <dl>
 
-<dt><i>evt</i></dt>
+<dt><i>evt</i> (QGestureEvent)</dt>
 <dd>
-reference to the gesture event (QGestureEvent
+reference to the gesture event
 </dd>
 </dl>
 <a NAME="UMLGraphicsView.getItemId" ID="UMLGraphicsView.getItemId"></a>
@@ -490,7 +561,13 @@
 <dl>
 <dt>Return:</dt>
 <dd>
-item ID (integer)
+item ID
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+int
 </dd>
 </dl>
 <a NAME="UMLGraphicsView.getPersistenceData" ID="UMLGraphicsView.getPersistenceData"></a>
@@ -503,7 +580,13 @@
 <dl>
 <dt>Return:</dt>
 <dd>
-list of data to be persisted (list of strings)
+list of data to be persisted
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+list of str
 </dd>
 </dl>
 <a NAME="UMLGraphicsView.initToolBar" ID="UMLGraphicsView.initToolBar"></a>
@@ -516,7 +599,13 @@
 <dl>
 <dt>Return:</dt>
 <dd>
-the populated toolBar (QToolBar)
+the populated toolBar
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+QToolBar
 </dd>
 </dl>
 <a NAME="UMLGraphicsView.keyPressEvent" ID="UMLGraphicsView.keyPressEvent"></a>
@@ -528,9 +617,9 @@
 </p>
 <dl>
 
-<dt><i>evt</i></dt>
+<dt><i>evt</i> (QKeyEvent)</dt>
 <dd>
-reference to the key event (QKeyEvent)
+reference to the key event
 </dd>
 </dl>
 <a NAME="UMLGraphicsView.parsePersistenceData" ID="UMLGraphicsView.parsePersistenceData"></a>
@@ -542,20 +631,26 @@
 </p>
 <dl>
 
-<dt><i>version</i></dt>
+<dt><i>version</i> (str)</dt>
 <dd>
-version of the data (string)
+version of the data
 </dd>
-<dt><i>data</i></dt>
+<dt><i>data</i> (list of str)</dt>
 <dd>
-persisted data to be parsed (list of string)
+persisted data to be parsed
 </dd>
 </dl>
 <dl>
 <dt>Return:</dt>
 <dd>
 tuple of flag indicating success (boolean) and faulty line
-            number (integer)
+            number
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+int
 </dd>
 </dl>
 <a NAME="UMLGraphicsView.printDiagram" ID="UMLGraphicsView.printDiagram"></a>
@@ -588,9 +683,9 @@
 </p>
 <dl>
 
-<dt><i>item</i></dt>
+<dt><i>item</i> (QGraphicsItemItem)</dt>
 <dd>
-item to be selected (QGraphicsItemItem)
+item to be selected
 </dd>
 </dl>
 <a NAME="UMLGraphicsView.selectItems" ID="UMLGraphicsView.selectItems"></a>
@@ -602,9 +697,9 @@
 </p>
 <dl>
 
-<dt><i>items</i></dt>
+<dt><i>items</i> (list of QGraphicsItemItem)</dt>
 <dd>
-list of items to be selected (list of QGraphicsItemItem)
+list of items to be selected
 </dd>
 </dl>
 <a NAME="UMLGraphicsView.setDiagramName" ID="UMLGraphicsView.setDiagramName"></a>
@@ -616,9 +711,42 @@
 </p>
 <dl>
 
-<dt><i>name</i></dt>
+<dt><i>name</i> (str)</dt>
+<dd>
+diagram name
+</dd>
+</dl>
+<a NAME="UMLGraphicsView.setLayoutActionsEnabled" ID="UMLGraphicsView.setLayoutActionsEnabled"></a>
+<h4>UMLGraphicsView.setLayoutActionsEnabled</h4>
+<b>setLayoutActionsEnabled</b>(<i>enable</i>)
+
+<p>
+        Public method to enable or disable the layout related actions.
+</p>
+<dl>
+
+<dt><i>enable</i> (bool)</dt>
 <dd>
-diagram name (string)
+flag indicating the desired enable state
+</dd>
+</dl>
+<a NAME="UMLGraphicsView.toDict" ID="UMLGraphicsView.toDict"></a>
+<h4>UMLGraphicsView.toDict</h4>
+<b>toDict</b>(<i></i>)
+
+<p>
+        Public method to collect data to be persisted.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+dictionary containing data to be persisted
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+dict
 </dd>
 </dl>
 <a NAME="UMLGraphicsView.wheelEvent" ID="UMLGraphicsView.wheelEvent"></a>
@@ -630,9 +758,9 @@
 </p>
 <dl>
 
-<dt><i>evt</i></dt>
+<dt><i>evt</i> (QWheelEvent)</dt>
 <dd>
-reference to the wheel event (QWheelEvent)
+reference to the wheel event
 </dd>
 </dl>
 <div align="right"><a href="#top">Up</a></div>
--- a/eric6/Documentation/Source/eric6.Graphics.UMLItem.html	Sat May 01 14:27:38 2021 +0200
+++ b/eric6/Documentation/Source/eric6.Graphics.UMLItem.html	Thu Jun 03 11:39:23 2021 +0200
@@ -66,7 +66,11 @@
 <h3>Class Methods</h3>
 
 <table>
-<tr><td>None</td></tr>
+
+<tr>
+<td><a href="#UMLItem.fromDict">fromDict</a></td>
+<td>Class method to create a generic UML item from persisted data.</td>
+</tr>
 </table>
 <h3>Methods</h3>
 
@@ -136,6 +140,10 @@
 <td><a href="#UMLItem.setSize">setSize</a></td>
 <td>Public method to set the rectangles size.</td>
 </tr>
+<tr>
+<td><a href="#UMLItem.toDict">toDict</a></td>
+<td>Public method to collect data to be persisted.</td>
+</tr>
 </table>
 <h3>Static Methods</h3>
 
@@ -143,6 +151,37 @@
 <tr><td>None</td></tr>
 </table>
 
+<a NAME="UMLItem.fromDict" ID="UMLItem.fromDict"></a>
+<h4>UMLItem.fromDict (class method)</h4>
+<b>fromDict</b>(<i>data, colors=None</i>)
+
+<p>
+        Class method to create a generic UML item from persisted data.
+</p>
+<dl>
+
+<dt><i>data</i> (dict)</dt>
+<dd>
+dictionary containing the persisted data as generated
+            by toDict()
+</dd>
+<dt><i>colors</i> (tuple of (QColor, QColor))</dt>
+<dd>
+tuple containing the foreground and background colors
+</dd>
+</dl>
+<dl>
+<dt>Return:</dt>
+<dd>
+created UML item
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+UMLItem
+</dd>
+</dl>
 <a NAME="UMLItem.__init__" ID="UMLItem.__init__"></a>
 <h4>UMLItem (Constructor)</h4>
 <b>UMLItem</b>(<i>model=None, x=0, y=0, rounded=False, colors=None, parent=None</i>)
@@ -186,9 +225,9 @@
 </p>
 <dl>
 
-<dt><i>assoc</i></dt>
+<dt><i>assoc</i> (AssociationWidget)</dt>
 <dd>
-association to be added (AssociationWidget)
+association to be added
 </dd>
 </dl>
 <a NAME="UMLItem.adjustAssociations" ID="UMLItem.adjustAssociations"></a>
@@ -213,7 +252,13 @@
 <dl>
 <dt>Return:</dt>
 <dd>
-persistence data (string)
+persistence data
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+str
 </dd>
 </dl>
 <a NAME="UMLItem.getId" ID="UMLItem.getId"></a>
@@ -226,7 +271,13 @@
 <dl>
 <dt>Return:</dt>
 <dd>
-ID of the item (integer)
+ID of the item
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+int
 </dd>
 </dl>
 <a NAME="UMLItem.getItemType" ID="UMLItem.getItemType"></a>
@@ -239,7 +290,13 @@
 <dl>
 <dt>Return:</dt>
 <dd>
-item type (string)
+item type
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+str
 </dd>
 </dl>
 <a NAME="UMLItem.getName" ID="UMLItem.getName"></a>
@@ -252,7 +309,13 @@
 <dl>
 <dt>Return:</dt>
 <dd>
-item name (string)
+item name
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+str
 </dd>
 </dl>
 <a NAME="UMLItem.itemChange" ID="UMLItem.itemChange"></a>
@@ -264,9 +327,9 @@
 </p>
 <dl>
 
-<dt><i>change</i></dt>
+<dt><i>change</i> (QGraphicsItem.GraphicsItemChange)</dt>
 <dd>
-the item's change (QGraphicsItem.GraphicsItemChange)
+the item's change
 </dd>
 <dt><i>value</i></dt>
 <dd>
@@ -288,13 +351,13 @@
 </p>
 <dl>
 
-<dt><i>dx</i></dt>
+<dt><i>dx</i> (float)</dt>
 <dd>
-relative movement in x-direction (float)
+relative movement in x-direction
 </dd>
-<dt><i>dy</i></dt>
+<dt><i>dy</i> (float)</dt>
 <dd>
-relative movement in y-direction (float)
+relative movement in y-direction
 </dd>
 </dl>
 <a NAME="UMLItem.paint" ID="UMLItem.paint"></a>
@@ -306,17 +369,17 @@
 </p>
 <dl>
 
-<dt><i>painter</i></dt>
+<dt><i>painter</i> (QPainter)</dt>
 <dd>
-reference to the painter object (QPainter)
+reference to the painter object
 </dd>
-<dt><i>option</i></dt>
+<dt><i>option</i> (QStyleOptionGraphicsItem)</dt>
 <dd>
-style options (QStyleOptionGraphicsItem)
+style options
 </dd>
-<dt><i>widget</i></dt>
+<dt><i>widget</i> (QWidget)</dt>
 <dd>
-optional reference to the widget painted on (QWidget)
+optional reference to the widget painted on
 </dd>
 </dl>
 <a NAME="UMLItem.parseItemDataString" ID="UMLItem.parseItemDataString"></a>
@@ -328,19 +391,25 @@
 </p>
 <dl>
 
-<dt><i>version</i></dt>
+<dt><i>version</i> (str)</dt>
 <dd>
-version of the data (string)
+version of the data
 </dd>
-<dt><i>data</i></dt>
+<dt><i>data</i> (str)</dt>
 <dd>
-persisted data to be parsed (string)
+persisted data to be parsed
 </dd>
 </dl>
 <dl>
 <dt>Return:</dt>
 <dd>
-flag indicating success (boolean)
+flag indicating success
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+bool
 </dd>
 </dl>
 <a NAME="UMLItem.removeAssociation" ID="UMLItem.removeAssociation"></a>
@@ -352,9 +421,9 @@
 </p>
 <dl>
 
-<dt><i>assoc</i></dt>
+<dt><i>assoc</i> (AssociationWidget)</dt>
 <dd>
-association to be removed (AssociationWidget)
+association to be removed
 </dd>
 </dl>
 <a NAME="UMLItem.removeAssociations" ID="UMLItem.removeAssociations"></a>
@@ -373,9 +442,9 @@
 </p>
 <dl>
 
-<dt><i>itemId</i></dt>
+<dt><i>itemId</i> (int)</dt>
 <dd>
-assigned ID (integer)
+assigned ID
 </dd>
 </dl>
 <a NAME="UMLItem.setPos" ID="UMLItem.setPos"></a>
@@ -387,13 +456,13 @@
 </p>
 <dl>
 
-<dt><i>x</i></dt>
+<dt><i>x</i> (float)</dt>
 <dd>
-absolute x-position (float)
+absolute x-position
 </dd>
-<dt><i>y</i></dt>
+<dt><i>y</i> (float)</dt>
 <dd>
-absolute y-position (float)
+absolute y-position
 </dd>
 </dl>
 <a NAME="UMLItem.setSize" ID="UMLItem.setSize"></a>
@@ -405,13 +474,32 @@
 </p>
 <dl>
 
-<dt><i>width</i></dt>
+<dt><i>width</i> (float)</dt>
 <dd>
-width of the rectangle (float)
+width of the rectangle
+</dd>
+<dt><i>height</i> (float)</dt>
+<dd>
+height of the rectangle
 </dd>
-<dt><i>height</i></dt>
+</dl>
+<a NAME="UMLItem.toDict" ID="UMLItem.toDict"></a>
+<h4>UMLItem.toDict</h4>
+<b>toDict</b>(<i></i>)
+
+<p>
+        Public method to collect data to be persisted.
+</p>
+<dl>
+<dt>Return:</dt>
 <dd>
-height of the rectangle (float)
+dictionary containing data to be persisted
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+dict
 </dd>
 </dl>
 <div align="right"><a href="#top">Up</a></div>
@@ -463,9 +551,9 @@
 </p>
 <dl>
 
-<dt><i>name</i></dt>
+<dt><i>name</i> (str)</dt>
 <dd>
-package name (string)
+package name
 </dd>
 </dl>
 <a NAME="UMLModel.getName" ID="UMLModel.getName"></a>
@@ -478,7 +566,13 @@
 <dl>
 <dt>Return:</dt>
 <dd>
-model name (string)
+model name
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+str
 </dd>
 </dl>
 <div align="right"><a href="#top">Up</a></div>
--- a/eric6/Documentation/Source/eric6.Graphics.UMLSceneSizeDialog.html	Sat May 01 14:27:38 2021 +0200
+++ b/eric6/Documentation/Source/eric6.Graphics.UMLSceneSizeDialog.html	Thu Jun 03 11:39:23 2021 +0200
@@ -92,29 +92,29 @@
 </p>
 <dl>
 
-<dt><i>w</i></dt>
+<dt><i>w</i> (int)</dt>
 <dd>
-current width of scene (integer)
+current width of scene
 </dd>
-<dt><i>h</i></dt>
+<dt><i>h</i> (int)</dt>
 <dd>
-current height of scene (integer)
+current height of scene
 </dd>
-<dt><i>minW</i></dt>
+<dt><i>minW</i> (int)</dt>
 <dd>
-minimum width allowed (integer)
+minimum width allowed
 </dd>
-<dt><i>minH</i></dt>
+<dt><i>minH</i> (int)</dt>
 <dd>
-minimum height allowed (integer)
+minimum height allowed
 </dd>
-<dt><i>parent</i></dt>
+<dt><i>parent</i> (QWidget)</dt>
 <dd>
-parent widget of this dialog (QWidget)
+parent widget of this dialog
 </dd>
-<dt><i>name</i></dt>
+<dt><i>name</i> (str)</dt>
 <dd>
-name of this widget (string)
+name of this widget
 </dd>
 </dl>
 <a NAME="UMLSceneSizeDialog.getData" ID="UMLSceneSizeDialog.getData"></a>
@@ -128,7 +128,12 @@
 <dt>Return:</dt>
 <dd>
 tuple giving the selected width and height
-            (integer, integer)
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+tuple of (int, int)
 </dd>
 </dl>
 <div align="right"><a href="#top">Up</a></div>
--- a/eric6/Documentation/Source/eric6.PluginManager.PluginManager.html	Sat May 01 14:27:38 2021 +0200
+++ b/eric6/Documentation/Source/eric6.PluginManager.PluginManager.html	Thu Jun 03 11:39:23 2021 +0200
@@ -266,6 +266,10 @@
 <td>Public method to load a plugin module.</td>
 </tr>
 <tr>
+<td><a href="#PluginManager.pipInstall">pipInstall</a></td>
+<td>Public method to install the given package via pip.</td>
+</tr>
+<tr>
 <td><a href="#PluginManager.preferencesChanged">preferencesChanged</a></td>
 <td>Public slot to react to changes in configuration.</td>
 </tr>
@@ -1092,7 +1096,7 @@
 </dl>
 <a NAME="PluginManager.loadPlugin" ID="PluginManager.loadPlugin"></a>
 <h4>PluginManager.loadPlugin</h4>
-<b>loadPlugin</b>(<i>name, directory, reload_=False</i>)
+<b>loadPlugin</b>(<i>name, directory, reload_=False, install=False</i>)
 
 <p>
         Public method to load a plugin module.
@@ -1105,17 +1109,22 @@
 </p>
 <dl>
 
-<dt><i>name</i></dt>
+<dt><i>name</i> (str)</dt>
 <dd>
-name of the module to be loaded (string)
+name of the module to be loaded
 </dd>
-<dt><i>directory</i></dt>
+<dt><i>directory</i> (str)</dt>
 <dd>
-name of the plugin directory (string)
+name of the plugin directory
 </dd>
-<dt><i>reload_</i></dt>
+<dt><i>reload_</i> (bool)</dt>
 <dd>
-flag indicating to reload the module (boolean)
+flag indicating to reload the module
+</dd>
+<dt><i>install</i> (bool)</dt>
+<dd>
+flag indicating a load operation as part of an
+            installation process
 </dd>
 </dl>
 <dl>
@@ -1126,6 +1135,20 @@
             the plug-in
 </dd>
 </dl>
+<a NAME="PluginManager.pipInstall" ID="PluginManager.pipInstall"></a>
+<h4>PluginManager.pipInstall</h4>
+<b>pipInstall</b>(<i>packages</i>)
+
+<p>
+        Public method to install the given package via pip.
+</p>
+<dl>
+
+<dt><i>packages</i> (list of str)</dt>
+<dd>
+list of packages to install
+</dd>
+</dl>
 <a NAME="PluginManager.preferencesChanged" ID="PluginManager.preferencesChanged"></a>
 <h4>PluginManager.preferencesChanged</h4>
 <b>preferencesChanged</b>(<i></i>)
--- a/eric6/Documentation/Source/eric6.Plugins.PluginVcsGit.html	Sat May 01 14:27:38 2021 +0200
+++ b/eric6/Documentation/Source/eric6.Plugins.PluginVcsGit.html	Thu Jun 03 11:39:23 2021 +0200
@@ -109,10 +109,6 @@
 <td>Constructor</td>
 </tr>
 <tr>
-<td><a href="#VcsGitPlugin.__loadTranslator">__loadTranslator</a></td>
-<td>Private method to load the translation file.</td>
-</tr>
-<tr>
 <td><a href="#VcsGitPlugin.activate">activate</a></td>
 <td>Public method to activate this plugin.</td>
 </tr>
@@ -199,13 +195,6 @@
 reference to the user interface object (UI.UserInterface)
 </dd>
 </dl>
-<a NAME="VcsGitPlugin.__loadTranslator" ID="VcsGitPlugin.__loadTranslator"></a>
-<h4>VcsGitPlugin.__loadTranslator</h4>
-<b>__loadTranslator</b>(<i></i>)
-
-<p>
-        Private method to load the translation file.
-</p>
 <a NAME="VcsGitPlugin.activate" ID="VcsGitPlugin.activate"></a>
 <h4>VcsGitPlugin.activate</h4>
 <b>activate</b>(<i></i>)
--- a/eric6/Documentation/Source/eric6.Plugins.VcsPlugins.vcsMercurial.HgUtilities.html	Sat May 01 14:27:38 2021 +0200
+++ b/eric6/Documentation/Source/eric6.Plugins.VcsPlugins.vcsMercurial.HgUtilities.html	Thu Jun 03 11:39:23 2021 +0200
@@ -41,7 +41,11 @@
 
 <tr>
 <td><a href="#getConfigPath">getConfigPath</a></td>
-<td>Public function to get the filename of the config file.</td>
+<td>Function to get the filename of the config file.</td>
+</tr>
+<tr>
+<td><a href="#getHgExecutable">getHgExecutable</a></td>
+<td>Function to get the full path of the Mercurial executable.</td>
 </tr>
 <tr>
 <td><a href="#hgVersion">hgVersion</a></td>
@@ -49,7 +53,7 @@
 </tr>
 <tr>
 <td><a href="#prepareProcess">prepareProcess</a></td>
-<td>Public function to prepare the given process.</td>
+<td>Function to prepare the given process.</td>
 </tr>
 </table>
 <hr />
@@ -59,12 +63,40 @@
 <b>getConfigPath</b>(<i></i>)
 
 <p>
-    Public function to get the filename of the config file.
+    Function to get the filename of the config file.
 </p>
 <dl>
 <dt>Return:</dt>
 <dd>
-filename of the config file (string)
+filename of the config file
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+str
+</dd>
+</dl>
+<div align="right"><a href="#top">Up</a></div>
+<hr />
+<hr />
+<a NAME="getHgExecutable" ID="getHgExecutable"></a>
+<h2>getHgExecutable</h2>
+<b>getHgExecutable</b>(<i></i>)
+
+<p>
+    Function to get the full path of the Mercurial executable.
+</p>
+<dl>
+<dt>Return:</dt>
+<dd>
+path of the Mercurial executable
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+str
 </dd>
 </dl>
 <div align="right"><a href="#top">Up</a></div>
@@ -105,21 +137,21 @@
 <b>prepareProcess</b>(<i>proc, encoding="", language=""</i>)
 
 <p>
-    Public function to prepare the given process.
+    Function to prepare the given process.
 </p>
 <dl>
 
-<dt><i>proc</i></dt>
+<dt><i>proc</i> (QProcess)</dt>
 <dd>
-reference to the process to be prepared (QProcess)
+reference to the process to be prepared
 </dd>
-<dt><i>encoding</i></dt>
+<dt><i>encoding</i> (str)</dt>
 <dd>
-encoding to be used by the process (string)
+encoding to be used by the process
 </dd>
-<dt><i>language</i></dt>
+<dt><i>language</i> (str)</dt>
 <dd>
-language to be set (string)
+language to be set
 </dd>
 </dl>
 <div align="right"><a href="#top">Up</a></div>
--- a/eric6/Documentation/Source/eric6.Tasks.Task.html	Sat May 01 14:27:38 2021 +0200
+++ b/eric6/Documentation/Source/eric6.Tasks.Task.html	Thu Jun 03 11:39:23 2021 +0200
@@ -38,6 +38,14 @@
 <td><a href="#Task">Task</a></td>
 <td>Class implementing the task data structure.</td>
 </tr>
+<tr>
+<td><a href="#TaskPriority">TaskPriority</a></td>
+<td>Class defining the task priorities.</td>
+</tr>
+<tr>
+<td><a href="#TaskType">TaskType</a></td>
+<td>Class defining the task types.</td>
+</tr>
 </table>
 <h3>Functions</h3>
 
@@ -57,7 +65,7 @@
 <h3>Class Attributes</h3>
 
 <table>
-<tr><td>TaskType2ColorName</td></tr><tr><td>TaskType2IconName</td></tr><tr><td>TaskType2MarkersName</td></tr><tr><td>TypeDocu</td></tr><tr><td>TypeFixme</td></tr><tr><td>TypeNone</td></tr><tr><td>TypeNote</td></tr><tr><td>TypeTest</td></tr><tr><td>TypeTodo</td></tr><tr><td>TypeWarning</td></tr>
+<tr><td>TaskType2ColorName</td></tr><tr><td>TaskType2IconName</td></tr><tr><td>TaskType2MarkersName</td></tr>
 </table>
 <h3>Class Methods</h3>
 
@@ -129,6 +137,10 @@
 <td>Public slot to update the description.</td>
 </tr>
 <tr>
+<td><a href="#Task.setTaskType">setTaskType</a></td>
+<td>Public method to update the task type.</td>
+</tr>
+<tr>
 <td><a href="#Task.toDict">toDict</a></td>
 <td>Public method to convert the task data to a dictionary.</td>
 </tr>
@@ -141,62 +153,61 @@
 
 <a NAME="Task.__init__" ID="Task.__init__"></a>
 <h4>Task (Constructor)</h4>
-<b>Task</b>(<i>summary, priority=1, filename="", lineno=0, completed=False, _time=0, isProjectTask=False, taskType=TypeTodo, project=None, description="", uid="", parentUid=""</i>)
+<b>Task</b>(<i>summary, priority=TaskPriority.NORMAL, filename="", lineno=0, completed=False, _time=0, isProjectTask=False, taskType=TaskType.TODO, project=None, description="", uid="", parentUid=""</i>)
 
 <p>
         Constructor
 </p>
 <dl>
 
-<dt><i>summary</i></dt>
+<dt><i>summary</i> (str)</dt>
 <dd>
-summary text of the task (string)
+summary text of the task
 </dd>
-<dt><i>priority</i></dt>
+<dt><i>priority</i> (TaskPriority)</dt>
 <dd>
-priority of the task (0=high, 1=normal, 2=low)
+priority of the task
 </dd>
-<dt><i>filename</i></dt>
+<dt><i>filename</i> (str)</dt>
 <dd>
-filename containing the task (string)
+filename containing the task
 </dd>
-<dt><i>lineno</i></dt>
+<dt><i>lineno</i> (int)</dt>
 <dd>
-line number containing the task (integer)
+line number containing the task
 </dd>
-<dt><i>completed</i></dt>
+<dt><i>completed</i> (bool)</dt>
 <dd>
-flag indicating completion status (boolean)
+flag indicating completion status
 </dd>
-<dt><i>_time</i></dt>
+<dt><i>_time</i> (float)</dt>
 <dd>
-creation time of the task (float, if 0 use current time)
+creation time of the task (if 0 use current time)
 </dd>
-<dt><i>isProjectTask</i></dt>
+<dt><i>isProjectTask</i> (bool)</dt>
 <dd>
 flag indicating a task related to the current
-            project (boolean)
+            project
 </dd>
-<dt><i>taskType</i></dt>
+<dt><i>taskType</i> (TaskType)</dt>
 <dd>
-type of the task (one of TypeFixme, TypeTodo,
-            TypeWarning, TypeNote, TypeTest, TypeDocu)
+type of the task
 </dd>
-<dt><i>project</i></dt>
+<dt><i>project</i> (Project)</dt>
 <dd>
-reference to the project object (Project)
+reference to the project object
 </dd>
-<dt><i>description</i></dt>
+<dt><i>description</i> (str)</dt>
 <dd>
-explanatory text of the task (string)
+explanatory text of the task
 </dd>
-<dt><i>uid</i></dt>
+<dt><i>uid</i> (str)</dt>
 <dd>
-unique id of the task (string)
+unique id of the task
 </dd>
-<dt><i>parentUid</i></dt>
+<dt><i>parentUid</i> (str)</dt>
 <dd>
-unique id of the parent task (string)
+unique id of the parent task
 </dd>
 </dl>
 <a NAME="Task.colorizeTask" ID="Task.colorizeTask"></a>
@@ -334,9 +345,9 @@
 </p>
 <dl>
 
-<dt><i>description</i></dt>
+<dt><i>description</i> (str)</dt>
 <dd>
-descriptive text of the task (string)
+descriptive text of the task
 </dd>
 </dl>
 <a NAME="Task.setPriority" ID="Task.setPriority"></a>
@@ -348,9 +359,9 @@
 </p>
 <dl>
 
-<dt><i>priority</i></dt>
+<dt><i>priority</i> (TaskPriority)</dt>
 <dd>
-priority of the task (0=high, 1=normal, 2=low)
+priority of the task
 </dd>
 </dl>
 <a NAME="Task.setProjectTask" ID="Task.setProjectTask"></a>
@@ -381,6 +392,20 @@
 summary text of the task (string)
 </dd>
 </dl>
+<a NAME="Task.setTaskType" ID="Task.setTaskType"></a>
+<h4>Task.setTaskType</h4>
+<b>setTaskType</b>(<i>taskType</i>)
+
+<p>
+        Public method to update the task type.
+</p>
+<dl>
+
+<dt><i>taskType</i> (TaskType)</dt>
+<dd>
+type of the task
+</dd>
+</dl>
 <a NAME="Task.toDict" ID="Task.toDict"></a>
 <h4>Task.toDict</h4>
 <b>toDict</b>(<i></i>)
@@ -402,4 +427,68 @@
 </dl>
 <div align="right"><a href="#top">Up</a></div>
 <hr />
+<hr />
+<a NAME="TaskPriority" ID="TaskPriority"></a>
+<h2>TaskPriority</h2>
+
+<p>
+    Class defining the task priorities.
+</p>
+<h3>Derived from</h3>
+enum.IntEnum
+<h3>Class Attributes</h3>
+
+<table>
+<tr><td>HIGH</td></tr><tr><td>LOW</td></tr><tr><td>NORMAL</td></tr>
+</table>
+<h3>Class Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Static Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+
+<div align="right"><a href="#top">Up</a></div>
+<hr />
+<hr />
+<a NAME="TaskType" ID="TaskType"></a>
+<h2>TaskType</h2>
+
+<p>
+    Class defining the task types.
+</p>
+<h3>Derived from</h3>
+enum.IntEnum
+<h3>Class Attributes</h3>
+
+<table>
+<tr><td>DOCU</td></tr><tr><td>FIXME</td></tr><tr><td>NONE</td></tr><tr><td>NOTE</td></tr><tr><td>TEST</td></tr><tr><td>TODO</td></tr><tr><td>WARNING</td></tr>
+</table>
+<h3>Class Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+<h3>Static Methods</h3>
+
+<table>
+<tr><td>None</td></tr>
+</table>
+
+<div align="right"><a href="#top">Up</a></div>
+<hr />
 </body></html>
\ No newline at end of file
--- a/eric6/Documentation/Source/eric6.Tasks.TaskFilter.html	Sat May 01 14:27:38 2021 +0200
+++ b/eric6/Documentation/Source/eric6.Tasks.TaskFilter.html	Thu Jun 03 11:39:23 2021 +0200
@@ -173,9 +173,9 @@
 </p>
 <dl>
 
-<dt><i>priorities</i></dt>
+<dt><i>priorities</i> (list of TaskPriority or None)</dt>
 <dd>
-list of task priorities (list of integer) or None
+list of task priorities or None
 </dd>
 </dl>
 <a NAME="TaskFilter.setScopeFilter" ID="TaskFilter.setScopeFilter"></a>
@@ -230,10 +230,9 @@
 </p>
 <dl>
 
-<dt><i>taskType</i></dt>
+<dt><i>taskType</i> (TaskType)</dt>
 <dd>
-type of the task (one of Task.TypeNone, Task.TypeFixme,
-            Task.TypeTodo, Task.TypeWarning, Task.TypeNote)
+type of the task
 </dd>
 </dl>
 <a NAME="TaskFilter.showTask" ID="TaskFilter.showTask"></a>
--- a/eric6/Documentation/Source/eric6.Tasks.TaskPropertiesDialog.html	Sat May 01 14:27:38 2021 +0200
+++ b/eric6/Documentation/Source/eric6.Tasks.TaskPropertiesDialog.html	Thu Jun 03 11:39:23 2021 +0200
@@ -73,12 +73,16 @@
 <td>Constructor</td>
 </tr>
 <tr>
+<td><a href="#TaskPropertiesDialog.__setMode">__setMode</a></td>
+<td>Private method to show or hide dialog elements depending on the task kind.</td>
+</tr>
+<tr>
 <td><a href="#TaskPropertiesDialog.getData">getData</a></td>
 <td>Public method to retrieve the dialogs data.</td>
 </tr>
 <tr>
-<td><a href="#TaskPropertiesDialog.setReadOnly">setReadOnly</a></td>
-<td>Public slot to set the dialog to read only mode.</td>
+<td><a href="#TaskPropertiesDialog.isManualTaskMode">isManualTaskMode</a></td>
+<td>Public method to check, if the dialog is in manual task mode.</td>
 </tr>
 <tr>
 <td><a href="#TaskPropertiesDialog.setSubTaskMode">setSubTaskMode</a></td>
@@ -100,17 +104,36 @@
 </p>
 <dl>
 
-<dt><i>task</i></dt>
+<dt><i>task</i> (Task)</dt>
 <dd>
 the task object to be shown
 </dd>
-<dt><i>parent</i></dt>
+<dt><i>parent</i> (QWidget)</dt>
 <dd>
-the parent widget (QWidget)
+the parent widget
+</dd>
+<dt><i>projectOpen</i> (bool)</dt>
+<dd>
+flag indicating status of the project
 </dd>
-<dt><i>projectOpen</i></dt>
+</dl>
+<a NAME="TaskPropertiesDialog.__setMode" ID="TaskPropertiesDialog.__setMode"></a>
+<h4>TaskPropertiesDialog.__setMode</h4>
+<b>__setMode</b>(<i>isFileTask, projectOpen</i>)
+
+<p>
+        Private method to show or hide dialog elements depending on the task
+        kind.
+</p>
+<dl>
+
+<dt><i>isFileTask</i> (bool)</dt>
 <dd>
-flag indicating status of the project (boolean)
+flag indicating a file task (i.e. extracted task)
+</dd>
+<dt><i>projectOpen</i> (bool)</dt>
+<dd>
+flag indicating status of the project
 </dd>
 </dl>
 <a NAME="TaskPropertiesDialog.getData" ID="TaskPropertiesDialog.getData"></a>
@@ -123,18 +146,35 @@
 <dl>
 <dt>Return:</dt>
 <dd>
-tuple of description, priority, completion flag,
-                project flag and long text (string, string, boolean,
-                boolean, string)
+tuple of description, priority, type, completion flag,
+                project flag and long text
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+tuple of (str, TaskPriority, TaskType, bool, bool, str)
 </dd>
 </dl>
-<a NAME="TaskPropertiesDialog.setReadOnly" ID="TaskPropertiesDialog.setReadOnly"></a>
-<h4>TaskPropertiesDialog.setReadOnly</h4>
-<b>setReadOnly</b>(<i></i>)
+<a NAME="TaskPropertiesDialog.isManualTaskMode" ID="TaskPropertiesDialog.isManualTaskMode"></a>
+<h4>TaskPropertiesDialog.isManualTaskMode</h4>
+<b>isManualTaskMode</b>(<i></i>)
 
 <p>
-        Public slot to set the dialog to read only mode.
+        Public method to check, if the dialog is in manual task mode.
 </p>
+<dl>
+<dt>Return:</dt>
+<dd>
+flag indicating manual task mode
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+bool
+</dd>
+</dl>
 <a NAME="TaskPropertiesDialog.setSubTaskMode" ID="TaskPropertiesDialog.setSubTaskMode"></a>
 <h4>TaskPropertiesDialog.setSubTaskMode</h4>
 <b>setSubTaskMode</b>(<i>projectTask</i>)
--- a/eric6/Documentation/Source/eric6.Tasks.TaskViewer.html	Sat May 01 14:27:38 2021 +0200
+++ b/eric6/Documentation/Source/eric6.Tasks.TaskViewer.html	Thu Jun 03 11:39:23 2021 +0200
@@ -64,11 +64,11 @@
 <h3>Signals</h3>
 <dl>
 
-<dt>taskFound(str, str, int, int)</dt>
+<dt>taskFound(str, str, int, TaskType)</dt>
 <dd>
-emitted with the task description,
-        the file name, the line number and task type to signal the presence of
-        a task
+emitted with the task
+        description, the file name, the line number and task type to signal
+        the presence of a task
 </dd>
 </dl>
 <h3>Derived from</h3>
@@ -561,96 +561,100 @@
 </dl>
 <a NAME="TaskViewer.addFileTask" ID="TaskViewer.addFileTask"></a>
 <h4>TaskViewer.addFileTask</h4>
-<b>addFileTask</b>(<i>summary, filename, lineno, taskType=Task.TypeTodo, description=""</i>)
+<b>addFileTask</b>(<i>summary, filename, lineno, taskType=TaskType.TODO, description=""</i>)
 
 <p>
         Public slot to add a file related task.
 </p>
 <dl>
 
-<dt><i>summary</i></dt>
+<dt><i>summary</i> (str)</dt>
 <dd>
-summary text of the task (string)
+summary text of the task
 </dd>
-<dt><i>filename</i></dt>
+<dt><i>filename</i> (str)</dt>
 <dd>
-filename containing the task (string)
+filename containing the task
 </dd>
-<dt><i>lineno</i></dt>
+<dt><i>lineno</i> (int)</dt>
 <dd>
-line number containing the task (integer)
+line number containing the task
 </dd>
-<dt><i>taskType</i></dt>
+<dt><i>taskType</i> (TaskType)</dt>
 <dd>
-type of the task (one of Task.TypeFixme, Task.TypeTodo,
-            Task.TypeWarning, Task.TypeNote)
+type of the task
 </dd>
-<dt><i>description</i></dt>
+<dt><i>description</i> (str)</dt>
 <dd>
-explanatory text of the task (string)
+explanatory text of the task
 </dd>
 </dl>
 <a NAME="TaskViewer.addTask" ID="TaskViewer.addTask"></a>
 <h4>TaskViewer.addTask</h4>
-<b>addTask</b>(<i>summary, priority=1, filename="", lineno=0, completed=False, _time=0, isProjectTask=False, taskType=Task.TypeTodo, description="", uid="", parentTask=None</i>)
+<b>addTask</b>(<i>summary, priority=TaskPriority.NORMAL, filename="", lineno=0, completed=False, _time=0, isProjectTask=False, taskType=TaskType.TODO, description="", uid="", parentTask=None</i>)
 
 <p>
         Public slot to add a task.
 </p>
 <dl>
 
-<dt><i>summary</i></dt>
+<dt><i>summary</i> (str)</dt>
 <dd>
-summary text of the task (string)
+summary text of the task
 </dd>
-<dt><i>priority</i></dt>
+<dt><i>priority</i> (TaskPriority)</dt>
 <dd>
-priority of the task (0=high, 1=normal, 2=low)
+priority of the task
 </dd>
-<dt><i>filename</i></dt>
+<dt><i>filename</i> (str)</dt>
 <dd>
-filename containing the task (string)
+filename containing the task
 </dd>
-<dt><i>lineno</i></dt>
+<dt><i>lineno</i> (int)</dt>
 <dd>
-line number containing the task (integer)
+line number containing the task
 </dd>
-<dt><i>completed</i></dt>
+<dt><i>completed</i> (bool)</dt>
 <dd>
-flag indicating completion status (boolean)
+flag indicating completion status
 </dd>
-<dt><i>_time</i></dt>
+<dt><i>_time</i> (float)</dt>
 <dd>
-creation time of the task (float, if 0 use current time)
+creation time of the task (if 0 use current time)
 </dd>
-<dt><i>isProjectTask</i></dt>
+<dt><i>isProjectTask</i> (bool)</dt>
 <dd>
 flag indicating a task related to the current
-            project (boolean)
+            project
 </dd>
-<dt><i>taskType</i></dt>
+<dt><i>taskType</i> (TaskType)</dt>
 <dd>
-type of the task (one of Task.TypeFixme, Task.TypeTodo,
-            Task.TypeWarning, Task.TypeNote)
+type of the task
 </dd>
-<dt><i>description</i></dt>
+<dt><i>description</i> (str)</dt>
 <dd>
-explanatory text of the task (string)
+explanatory text of the task
 </dd>
-<dt><i>uid</i></dt>
+<dt><i>uid</i> (str)</dt>
 <dd>
-unique id of the task (string)
+unique id of the task
 </dd>
-<dt><i>parentTask</i></dt>
+<dt><i>parentTask</i> (Task or str)</dt>
 <dd>
-reference to the parent task item (Task) or the
-            UID of the parent task
+reference to the parent task item or the UID of the
+            parent task
 </dd>
 </dl>
 <dl>
 <dt>Return:</dt>
 <dd>
-reference to the task item (Task)
+reference to the task item
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+Task
 </dd>
 </dl>
 <a NAME="TaskViewer.clearFileTasks" ID="TaskViewer.clearFileTasks"></a>
--- a/eric6/Documentation/Source/eric6.UI.Browser.html	Sat May 01 14:27:38 2021 +0200
+++ b/eric6/Documentation/Source/eric6.UI.Browser.html	Thu Jun 03 11:39:23 2021 +0200
@@ -124,6 +124,10 @@
         files indicating whether non-existent files shall be ignored
         (list of str, bool)
 </dd>
+<dt>umlFile(filename)</dt>
+<dd>
+emitted to open an eric UML file (str)
+</dd>
 <dt>unittestOpen(filename)</dt>
 <dd>
 emitted to open a Python file for a
--- a/eric6/Documentation/Source/eric6.UI.UserInterface.html	Sat May 01 14:27:38 2021 +0200
+++ b/eric6/Documentation/Source/eric6.UI.UserInterface.html	Thu Jun 03 11:39:23 2021 +0200
@@ -526,6 +526,10 @@
 <td>Private method to open the last file, project or multiproject.</td>
 </tr>
 <tr>
+<td><a href="#UserInterface.__pluginInstallFinished">__pluginInstallFinished</a></td>
+<td>Private slot to handle the finishing of the plugin install dialog.</td>
+</tr>
+<tr>
 <td><a href="#UserInterface.__pluginsConfigure">__pluginsConfigure</a></td>
 <td>Private slot to show the plugin manager configuration page.</td>
 </tr>
@@ -706,6 +710,10 @@
 <td>Private slot to display the Toolbars menu.</td>
 </tr>
 <tr>
+<td><a href="#UserInterface.__showUml">__showUml</a></td>
+<td>Private slot to show an eric graphics file in a dialog.</td>
+</tr>
+<tr>
 <td><a href="#UserInterface.__showUserToolsMenu">__showUserToolsMenu</a></td>
 <td>Private slot to display the User Tools menu.</td>
 </tr>
@@ -1911,6 +1919,13 @@
             "Nothing", "File", "Project", "MultiProject" or "Session")
 </dd>
 </dl>
+<a NAME="UserInterface.__pluginInstallFinished" ID="UserInterface.__pluginInstallFinished"></a>
+<h4>UserInterface.__pluginInstallFinished</h4>
+<b>__pluginInstallFinished</b>(<i></i>)
+
+<p>
+        Private slot to handle the finishing of the plugin install dialog.
+</p>
 <a NAME="UserInterface.__pluginsConfigure" ID="UserInterface.__pluginsConfigure"></a>
 <h4>UserInterface.__pluginsConfigure</h4>
 <b>__pluginsConfigure</b>(<i></i>)
@@ -2390,6 +2405,20 @@
 <p>
         Private slot to display the Toolbars menu.
 </p>
+<a NAME="UserInterface.__showUml" ID="UserInterface.__showUml"></a>
+<h4>UserInterface.__showUml</h4>
+<b>__showUml</b>(<i>fn</i>)
+
+<p>
+        Private slot to show an eric graphics file in a dialog.
+</p>
+<dl>
+
+<dt><i>fn</i> (str)</dt>
+<dd>
+name of the file to be shown
+</dd>
+</dl>
 <a NAME="UserInterface.__showUserToolsMenu" ID="UserInterface.__showUserToolsMenu"></a>
 <h4>UserInterface.__showUserToolsMenu</h4>
 <b>__showUserToolsMenu</b>(<i></i>)
--- a/eric6/Documentation/Source/index-eric6.E5Network.html	Sat May 01 14:27:38 2021 +0200
+++ b/eric6/Documentation/Source/index-eric6.E5Network.html	Thu Jun 03 11:39:23 2021 +0200
@@ -50,6 +50,14 @@
 <td>Module implementing some helpers for Google mail.</td>
 </tr>
 <tr>
+<td><a href="eric6.E5Network.E5JsonClient.html">E5JsonClient</a></td>
+<td>Module implementing the JSON based client base class.</td>
+</tr>
+<tr>
+<td><a href="eric6.E5Network.E5JsonServer.html">E5JsonServer</a></td>
+<td>Module implementing the JSON based server base class.</td>
+</tr>
+<tr>
 <td><a href="eric6.E5Network.E5NetworkHeaderDetailsDialog.html">E5NetworkHeaderDetailsDialog</a></td>
 <td>Module implementing a dialog to show the data of a response or reply header.</td>
 </tr>
--- a/eric6/Documentation/Source/index-eric6.Graphics.html	Sat May 01 14:27:38 2021 +0200
+++ b/eric6/Documentation/Source/index-eric6.Graphics.html	Thu Jun 03 11:39:23 2021 +0200
@@ -58,7 +58,7 @@
 </tr>
 <tr>
 <td><a href="eric6.Graphics.PackageDiagramBuilder.html">PackageDiagramBuilder</a></td>
-<td>Module implementing a dialog showing a UML like class diagram of a package.</td>
+<td>Module implementing a dialog showing an UML like class diagram of a package.</td>
 </tr>
 <tr>
 <td><a href="eric6.Graphics.PackageItem.html">PackageItem</a></td>
--- a/eric6/E5Graphics/E5GraphicsView.py	Sat May 01 14:27:38 2021 +0200
+++ b/eric6/E5Graphics/E5GraphicsView.py	Thu Jun 03 11:39:23 2021 +0200
@@ -283,10 +283,14 @@
         Private method to retrieve the diagram from the scene fitting it
         in the minimum rectangle.
         
-        @param rect minimum rectangle fitting the diagram (QRectF)
-        @param imageFormat format for the image file (string)
-        @param filename name of the file for non pixmaps (string)
-        @return diagram pixmap to receive the diagram (QPixmap)
+        @param rect minimum rectangle fitting the diagram
+        @type QRectF
+        @param imageFormat format for the image file
+        @type str
+        @param filename name of the file for non pixmaps
+        str
+        @return paint device containing the diagram
+        @rtype QPixmap or QSvgGenerator
         """
         selectedItems = self.scene().selectedItems()
         
@@ -341,22 +345,24 @@
             (QPrinter)
         @param diagramName name of the diagram (string)
         """
-        painter = QPainter()
-        painter.begin(printer)
-        offsetX = 0
-        offsetY = 0
-        widthX = 0
-        heightY = 0
+        painter = QPainter(printer)
+        
         font = QFont("times", 10)
         painter.setFont(font)
         fm = painter.fontMetrics()
         fontHeight = fm.lineSpacing()
-        marginX = printer.pageRect().x() - printer.paperRect().x()
+        marginX = (
+            printer.pageLayout().paintRectPixels(printer.resolution()).x() -
+            printer.pageLayout().fullRectPixels(printer.resolution()).x()
+        )
         marginX = (
             Preferences.getPrinter("LeftMargin") *
             int(printer.resolution() / 2.54) - marginX
         )
-        marginY = printer.pageRect().y() - printer.paperRect().y()
+        marginY = (
+            printer.pageLayout().paintRectPixels(printer.resolution()).y() -
+            printer.pageLayout().fullRectPixels(printer.resolution()).y()
+        )
         marginY = (
             Preferences.getPrinter("TopMargin") *
             int(printer.resolution() / 2.54) - marginY
@@ -373,59 +379,18 @@
             int(printer.resolution() / 2.54)
         )
         
-        border = self.border == 0 and 5 or self.border
-        rect = self._getDiagramRect(border)
-        diagram = self.__getDiagram(rect)
+        self.scene().render(painter,
+                            target=QRectF(marginX, marginY, width, height))
         
-        finishX = False
-        finishY = False
-        page = 0
-        pageX = 0
-        pageY = 1
-        while not finishX or not finishY:
-            if not finishX:
-                offsetX = pageX * width
-                pageX += 1
-            elif not finishY:
-                offsetY = pageY * height
-                offsetX = 0
-                pageY += 1
-                finishX = False
-                pageX = 1
-            if (width + offsetX) > diagram.width():
-                finishX = True
-                widthX = diagram.width() - offsetX
-            else:
-                widthX = width
-            if diagram.width() < width:
-                widthX = diagram.width()
-                finishX = True
-                offsetX = 0
-            if (height + offsetY) > diagram.height():
-                finishY = True
-                heightY = diagram.height() - offsetY
-            else:
-                heightY = height
-            if diagram.height() < height:
-                finishY = True
-                heightY = diagram.height()
-                offsetY = 0
-            
-            painter.drawPixmap(marginX, marginY, diagram,
-                               offsetX, offsetY, widthX, heightY)
-            # write a foot note
-            s = self.tr("{0}, Page {1}").format(diagramName, page + 1)
-            tc = QColor(50, 50, 50)
-            painter.setPen(tc)
-            painter.drawRect(marginX, marginY, width, height)
-            painter.drawLine(marginX, marginY + height + 2,
-                             marginX + width, marginY + height + 2)
-            painter.setFont(font)
-            painter.drawText(marginX, marginY + height + 4, width,
-                             fontHeight, Qt.AlignmentFlag.AlignRight, s)
-            if not finishX or not finishY:
-                printer.newPage()
-                page += 1
+        # write a foot note
+        tc = QColor(50, 50, 50)
+        painter.setPen(tc)
+        painter.drawRect(marginX, marginY, width, height)
+        painter.drawLine(marginX, marginY + height + 2,
+                         marginX + width, marginY + height + 2)
+        painter.setFont(font)
+        painter.drawText(marginX, marginY + height + 4, width,
+                         fontHeight, Qt.AlignmentFlag.AlignRight, diagramName)
         
         painter.end()
     
--- a/eric6/E5Gui/E5PathPicker.py	Sat May 01 14:27:38 2021 +0200
+++ b/eric6/E5Gui/E5PathPicker.py	Thu Jun 03 11:39:23 2021 +0200
@@ -25,8 +25,8 @@
     """
     Class implementing the path picker modes.
     """
-    # TODO: convert these to all uppercase without "Mode" when doing
-    #       the port to PyQt6 (i.e. eric7)
+    # TODO: eric7: convert these to all uppercase without "Mode" when doing
+    #       the port to PyQt6
     OpenFileMode = 0
     OpenFilesMode = 1
     SaveFileMode = 2
--- a/eric6/E5Network/E5Ftp.py	Sat May 01 14:27:38 2021 +0200
+++ b/eric6/E5Network/E5Ftp.py	Thu Jun 03 11:39:23 2021 +0200
@@ -8,6 +8,7 @@
 proxies.
 """
 
+import enum
 import ftplib           # secok
 from socket import _GLOBAL_DEFAULT_TIMEOUT
 
@@ -39,22 +40,20 @@
     pass
 
 
-# TODO: convert to Enum
-#       note: it is used as a preference item as well => IntEnum
-class E5FtpProxyType:
+class E5FtpProxyType(enum.Enum):
     """
     Class defining the supported FTP proxy types.
     """
-    NoProxy = 0                     # no proxy
-    NonAuthorizing = 1              # non authorizing proxy
-    UserAtServer = 2                # proxy login first, than user@remote.host
-    Site = 3                        # proxy login first, than use SITE command
-    Open = 4                        # proxy login first, than use OPEN command
-    UserAtProxyuserAtServer = 5     # one login for both
-    ProxyuserAtServer = 6
+    NO_PROXY = 0                    # no proxy
+    NON_AUTHORIZING = 1             # non authorizing proxy
+    USER_SERVER = 2                 # proxy login first, than user@remote.host
+    SITE = 3                        # proxy login first, than use SITE command
+    OPEN = 4                        # proxy login first, than use OPEN command
+    USER_PROXYUSER_SERVER = 5       # one login for both
+    PROXYUSER_SERVER = 6
     # proxy login with remote host given, than normal remote login
-    AuthResp = 7  # authenticate to proxy with AUTH and RESP commands
-    Bluecoat = 8                    # bluecoat proxy
+    AUTH_RESP = 7  # authenticate to proxy with AUTH and RESP commands
+    BLUECOAT = 8                    # bluecoat proxy
 
 
 class E5Ftp(ftplib.FTP):
@@ -63,23 +62,34 @@
     proxies.
     """
     def __init__(self, host="", user="", password="", acct="",          # secok
-                 proxyType=E5FtpProxyType.NoProxy, proxyHost="",
+                 proxyType=E5FtpProxyType.NO_PROXY, proxyHost="",
                  proxyPort=ftplib.FTP_PORT, proxyUser="", proxyPassword="",
                  proxyAccount="", timeout=_GLOBAL_DEFAULT_TIMEOUT):
         """
         Constructor
         
-        @param host name of the FTP host (string)
-        @param user user name for login to FTP host (string)
-        @param password password for login to FTP host (string)
-        @param acct account for login to FTP host (string)
-        @param proxyType type of the FTP proxy (integer 0 to 8)
-        @param proxyHost name of the FTP proxy (string)
-        @param proxyPort port of the FTP proxy (integer)
-        @param proxyUser user name for login to the proxy (string)
-        @param proxyPassword password for login to the proxy (string)
-        @param proxyAccount accounting info for the proxy (string)
-        @param timeout timeout in seconds for blocking operations (integer)
+        @param host name of the FTP host
+        @type str
+        @param user user name for login to FTP host
+        @type str
+        @param password password for login to FTP host
+        @type str
+        @param acct account for login to FTP host
+        @type str
+        @param proxyType type of the FTP proxy
+        @type E5FtpProxyType
+        @param proxyHost name of the FTP proxy
+        @type str
+        @param proxyPort port of the FTP proxy
+        @type int
+        @param proxyUser user name for login to the proxy
+        @type str
+        @param proxyPassword password for login to the proxy
+        @type str
+        @param proxyAccount accounting info for the proxy
+        @type str
+        @param timeout timeout in seconds for blocking operations
+        @type int
         """
         super().__init__()
         
@@ -103,18 +113,24 @@
             if user:
                 self.login(user, password, acct)
     
-    def setProxy(self, proxyType=E5FtpProxyType.NoProxy, proxyHost="",
+    def setProxy(self, proxyType=E5FtpProxyType.NO_PROXY, proxyHost="",
                  proxyPort=ftplib.FTP_PORT, proxyUser="", proxyPassword="",
                  proxyAccount=""):
         """
         Public method to set the proxy configuration.
         
-        @param proxyType type of the FTP proxy (integer 0 to 8)
-        @param proxyHost name of the FTP proxy (string)
-        @param proxyPort port of the FTP proxy (integer)
-        @param proxyUser user name for login to the proxy (string)
-        @param proxyPassword password  for login to the proxy (string)
-        @param proxyAccount accounting info for the proxy (string)
+        @param proxyType type of the FTP proxy
+        @type E5FtpProxyType
+        @param proxyHost name of the FTP proxy
+        @type str
+        @param proxyPort port of the FTP proxy
+        @type int
+        @param proxyUser user name for login to the proxy
+        @type str
+        @param proxyPassword password  for login to the proxy
+        @type str
+        @param proxyAccount accounting info for the proxy
+        @type str
         """
         self.__proxyType = proxyType
         self.__proxyHost = proxyHost
@@ -128,9 +144,12 @@
         """
         Public method to set the proxy authentication info.
         
-        @param proxyUser user name for login to the proxy (string)
-        @param proxyPassword password  for login to the proxy (string)
-        @param proxyAccount accounting info for the proxy (string)
+        @param proxyUser user name for login to the proxy
+        @type str
+        @param proxyPassword password  for login to the proxy
+        @type str
+        @param proxyAccount accounting info for the proxy
+        @type str
         """
         self.__proxyUser = proxyUser
         self.__proxyPassword = proxyPassword
@@ -144,10 +163,14 @@
         if a proxy is to be used. It throws an exception, if the proxy data
         is incomplete.
         
-        @param host name of the FTP host (string)
-        @param port port of the FTP host (integer)
-        @param timeout timeout in seconds for blocking operations (integer)
-        @return welcome message of the server (string)
+        @param host name of the FTP host
+        @type str
+        @param port port of the FTP host
+        @type int
+        @param timeout timeout in seconds for blocking operations
+        @type int
+        @return welcome message of the server
+        @rtype str
         @exception E5FtpProxyError raised to indicate a proxy related issue
         """
         if host:
@@ -157,7 +180,7 @@
         if timeout != -999:
             self.__timeout = timeout
         
-        if self.__proxyType != E5FtpProxyType.NoProxy:
+        if self.__proxyType != E5FtpProxyType.NO_PROXY:
             if not self.__proxyHost:
                 raise E5FtpProxyError(
                     "990 Proxy usage requested, but no proxy host given.")
@@ -187,24 +210,24 @@
         </table>
         
         <dl>
-          <dt>E5FtpProxyType.NoProxy:</dt>
+          <dt>E5FtpProxyType.NO_PROXY:</dt>
           <dd>
             USER user<br/>
             PASS pass
           </dd>
-          <dt>E5FtpProxyType.NonAuthorizing:</dt>
+          <dt>E5FtpProxyType.NON_AUTHORIZING:</dt>
           <dd>
             USER user@remote.host<br/>
             PASS pass
           </dd>
-          <dt>E5FtpProxyType.UserAtServer:</dt>
+          <dt>E5FtpProxyType.USER_SERVER:</dt>
           <dd>
             USER pruser<br/>
             PASS prpass<br/>
             USER user@remote.host<br/>
             PASS pass
           </dd>
-          <dt>E5FtpProxyType.Site:</dt>
+          <dt>E5FtpProxyType.SITE:</dt>
           <dd>
             USER pruser<br/>
             PASS prpass<br/>
@@ -212,7 +235,7 @@
             USER user<br/>
             PASS pass
           </dd>
-          <dt>E5FtpProxyType.Open:</dt>
+          <dt>E5FtpProxyType.OPEN:</dt>
           <dd>
             USER pruser<br/>
             PASS prpass<br/>
@@ -220,26 +243,26 @@
             USER user<br/>
             PASS pass
           </dd>
-          <dt>E5FtpProxyType.UserAtProxyuserAtServer:</dt>
+          <dt>E5FtpProxyType.USER_PROXYUSER_SERVER:</dt>
           <dd>
             USER user@pruser@remote.host<br/>
             PASS pass@prpass
           </dd>
-          <dt>E5FtpProxyType.ProxyuserAtServer:</dt>
+          <dt>E5FtpProxyType.PROXYUSER_SERVER:</dt>
           <dd>
             USER pruser@remote.host<br/>
             PASS prpass<br/>
             USER user<br/>
             PASS pass
           </dd>
-          <dt>E5FtpProxyType.AuthResp:</dt>
+          <dt>E5FtpProxyType.AUTH_RESP:</dt>
           <dd>
             USER user@remote.host<br/>
             PASS pass<br/>
             AUTH pruser<br/>
             RESP prpass
           </dd>
-          <dt>E5FtpProxyType.Bluecoat:</dt>
+          <dt>E5FtpProxyType.BLUECOAT:</dt>
           <dd>
             USER user@remote.host pruser<br/>
             PASS pass<br/>
@@ -247,10 +270,14 @@
           </dd>
         </dl>
         
-        @param user username for the remote host (string)
-        @param password password for the remote host (string)
-        @param acct accounting information for the remote host (string)
-        @return response sent by the remote host (string)
+        @param user username for the remote host
+        @type str
+        @param password password for the remote host
+        @type str
+        @param acct accounting information for the remote host
+        @type str
+        @return response sent by the remote host
+        @rtype str
         @exception E5FtpProxyError raised to indicate a proxy related issue
         @exception ftplib.error_reply raised to indicate an FTP error reply
         """
@@ -265,8 +292,8 @@
         if user == "anonymous" and password in {'', '-'}:
             password += "anonymous@"
         
-        if self.__proxyType != E5FtpProxyType.NoProxy:
-            if self.__proxyType != E5FtpProxyType.NonAuthorizing:
+        if self.__proxyType != E5FtpProxyType.NO_PROXY:
+            if self.__proxyType != E5FtpProxyType.NON_AUTHORIZING:
                 # check, if a valid proxy configuration is known
                 if not self.__proxyUser:
                     raise E5FtpProxyError(
@@ -276,22 +303,22 @@
                         "992 Proxy usage requested, but no proxy password"
                         " given")
             
-            if self.__proxyType in [E5FtpProxyType.NonAuthorizing,
-                                    E5FtpProxyType.AuthResp,
-                                    E5FtpProxyType.Bluecoat]:
+            if self.__proxyType in [E5FtpProxyType.NON_AUTHORIZING,
+                                    E5FtpProxyType.AUTH_RESP,
+                                    E5FtpProxyType.BLUECOAT]:
                 user += "@" + self.__host
-                if self.__proxyType == E5FtpProxyType.Bluecoat:
+                if self.__proxyType == E5FtpProxyType.BLUECOAT:
                     user += " " + self.__proxyUser
                     acct = self.__proxyPassword
-            elif self.__proxyType == E5FtpProxyType.UserAtProxyuserAtServer:
+            elif self.__proxyType == E5FtpProxyType.USER_PROXYUSER_SERVER:
                 user = "{0}@{1}@{2}".format(
                     user, self.__proxyUser, self.__host)
                 password = "{0}@{1}".format(password, self.__proxyPassword)
             else:
                 pruser = self.__proxyUser
-                if self.__proxyType == E5FtpProxyType.UserAtServer:
+                if self.__proxyType == E5FtpProxyType.USER_SERVER:
                     user += "@" + self.__host
-                elif self.__proxyType == E5FtpProxyType.ProxyuserAtServer:
+                elif self.__proxyType == E5FtpProxyType.PROXYUSER_SERVER:
                     pruser += "@" + self.__host
                 
                 # authenticate to the proxy first
@@ -305,14 +332,14 @@
                         "9{0}0 Error authorizing at proxy\n{1}".format(
                             presp[0], presp))
                 
-                if self.__proxyType == E5FtpProxyType.Site:
+                if self.__proxyType == E5FtpProxyType.SITE:
                     # send SITE command
                     presp = self.sendcmd("SITE " + self.__host)
                     if presp[0] != "2":
                         raise E5FtpProxyError(
                             "9{0}0 Error sending SITE command\n{1}".format(
                                 presp[0], presp))
-                elif self.__proxyType == E5FtpProxyType.Open:
+                elif self.__proxyType == E5FtpProxyType.OPEN:
                     # send OPEN command
                     presp = self.sendcmd("OPEN " + self.__host)
                     if presp[0] != "2":
@@ -329,7 +356,7 @@
         if resp[0] != "2":
             raise ftplib.error_reply(resp)          # secok
         
-        if self.__proxyType == E5FtpProxyType.AuthResp:
+        if self.__proxyType == E5FtpProxyType.AUTH_RESP:
             # authorize to the FTP proxy
             presp = self.sendcmd("AUTH " + self.__proxyUser)
             if presp[0] == "3":
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eric6/E5Network/E5JsonClient.py	Thu Jun 03 11:39:23 2021 +0200
@@ -0,0 +1,203 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2017 - 2021 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing the JSON based client base class.
+"""
+
+import io
+import sys
+import socket
+import select
+import traceback
+import json
+import contextlib
+
+
+class E5JsonClient:
+    """
+    Class implementing a JSON based client base class.
+    """
+    def __init__(self, host, port, idString=""):
+        """
+        Constructor
+        
+        @param host ip address the background service is listening
+        @type str
+        @param port port of the background service
+        @type int
+        @param idString assigned client id to be sent back to the server in
+            order to identify the connection
+        @type str
+        """
+        self.__connection = socket.create_connection((host, port))
+        if idString:
+            reply = idString + '\n'
+            self.__connection.sendall(reply.encode('utf8', 'backslashreplace'))
+    
+    def sendJson(self, command, params):
+        """
+        Public method to send a single refactoring command to the server.
+        
+        @param command command name to be sent
+        @type str
+        @param params dictionary of named parameters for the command
+        @type dict
+        """
+        commandDict = {
+            "jsonrpc": "2.0",
+            "method": command,
+            "params": params,
+        }
+        cmd = json.dumps(commandDict) + '\n'
+        self.__connection.sendall(cmd.encode('utf8', 'backslashreplace'))
+    
+    def __receiveJson(self):
+        """
+        Private method to receive a JSON encode command and data from the
+        server.
+        
+        @return tuple containing the received command and a dictionary
+            containing the associated data
+        @rtype tuple of (str, dict)
+        """
+        # step 1: receive the data
+        # The JSON RPC string is prefixed by a 9 character long length field.
+        length = self.__connection.recv(9)
+        if len(length) < 9:
+            # invalid length string received
+            return None, None
+        
+        length = int(length)
+        data = b''
+        while len(data) < length:
+            newData = self.__connection.recv(length - len(data))
+            if not newData:
+                return None, None
+            
+            data += newData
+        
+        # step 2: decode and convert the data
+        line = data.decode(
+            'utf8', 'backslashreplace')
+        try:
+            commandDict = json.loads(line.strip())
+        except (TypeError, ValueError) as err:
+            self.sendJson("ClientException", {
+                "ExceptionType": "ProtocolError",
+                "ExceptionValue": str(err),
+                "ProtocolData": line.strip(),
+            })
+            return None, None
+        
+        method = commandDict["method"]
+        params = commandDict["params"]
+        
+        return method, params
+    
+    def handleCall(self, method, params):
+        """
+        Public method to handle a method call from the server.
+        
+        Note: This is an empty implementation that must be overridden in
+        derived classes.
+        
+        @param method requested method name
+        @type str
+        @param params dictionary with method specific parameters
+        @type dict
+        """
+        pass
+    
+    def run(self):
+        """
+        Public method implementing the main loop of the client.
+        """
+        try:
+            selectErrors = 0
+            while selectErrors <= 10:  # selected arbitrarily
+                try:
+                    rrdy, wrdy, xrdy = select.select(
+                        [self.__connection], [], [])
+                    
+                    # Just waiting for self.__connection. Therefor no check
+                    # needed.
+                    method, params = self.__receiveJson()
+                    if method is None:
+                        selectErrors += 1
+                    elif method == "Exit":
+                        break
+                    else:
+                        self.handleCall(method, params)
+                        
+                        # reset select errors
+                        selectErrors = 0
+                
+                except (select.error, KeyboardInterrupt, socket.error):
+                    selectErrors += 1
+        
+        except Exception:
+            exctype, excval, exctb = sys.exc_info()
+            tbinfofile = io.StringIO()
+            traceback.print_tb(exctb, None, tbinfofile)
+            tbinfofile.seek(0)
+            tbinfo = tbinfofile.read()
+            del exctb
+            self.sendJson("ClientException", {
+                "ExceptionType": str(exctype),
+                "ExceptionValue": str(excval),
+                "Traceback": tbinfo,
+            })
+
+        # Give time to process latest response on server side
+        with contextlib.suppress(socket.error, OSError):
+            self.__connection.shutdown(socket.SHUT_RDWR)
+            self.__connection.close()
+    
+    def poll(self, waitMethod=""):
+        """
+        Public method to check and receive one message (if available).
+        
+        @param waitMethod name of a method to wait for
+        @type str
+        @return dictionary containing the data of the waited for method
+        @rtype dict
+        """
+        try:
+            if waitMethod:
+                rrdy, wrdy, xrdy = select.select(
+                    [self.__connection], [], [])
+            else:
+                rrdy, wrdy, xrdy = select.select(
+                    [self.__connection], [], [], 0)
+            
+            if self.__connection in rrdy:
+                method, params = self.__receiveJson()
+                if method is not None:
+                    if method == "Exit":
+                        self.__exitClient = True
+                    elif method == waitMethod:
+                        return params
+                    else:
+                        self.handleCall(method, params)
+        
+        except (select.error, KeyboardInterrupt, socket.error):
+            # just ignore these
+            pass
+        
+        except Exception:
+            exctype, excval, exctb = sys.exc_info()
+            tbinfofile = io.StringIO()
+            traceback.print_tb(exctb, None, tbinfofile)
+            tbinfofile.seek(0)
+            tbinfo = tbinfofile.read()
+            del exctb
+            self.sendJson("ClientException", {
+                "ExceptionType": str(exctype),
+                "ExceptionValue": str(excval),
+                "Traceback": tbinfo,
+            })
+        
+        return None
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eric6/E5Network/E5JsonServer.py	Thu Jun 03 11:39:23 2021 +0200
@@ -0,0 +1,336 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2017 - 2021 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing the JSON based server base class.
+"""
+
+import contextlib
+import json
+
+from PyQt5.QtCore import (
+    pyqtSlot, QProcess, QProcessEnvironment, QCoreApplication, QEventLoop,
+    QTimer
+)
+from PyQt5.QtNetwork import QTcpServer, QHostAddress
+
+from E5Gui import E5MessageBox
+
+import Preferences
+import Utilities
+
+
+class E5JsonServer(QTcpServer):
+    """
+    Class implementing a JSON based server base class.
+    """
+    def __init__(self, name="", multiplex=False, parent=None):
+        """
+        Constructor
+        
+        @param name name of the server (used for output only)
+        @type str
+        @param multiplex flag indicating a multiplexing server
+        @type bool
+        @param parent parent object
+        @type QObject
+        """
+        super().__init__(parent)
+        
+        self.__name = name
+        self.__multiplex = multiplex
+        if self.__multiplex:
+            self.__clientProcesses = {}
+            self.__connections = {}
+        else:
+            self.__clientProcess = None
+            self.__connection = None
+        
+        # setup the network interface
+        networkInterface = Preferences.getDebugger("NetworkInterface")
+        if networkInterface == "all" or '.' in networkInterface:
+            # IPv4
+            self.__hostAddress = '127.0.0.1'
+        else:
+            # IPv6
+            self.__hostAddress = '::1'
+        self.listen(QHostAddress(self.__hostAddress))
+
+        self.newConnection.connect(self.handleNewConnection)
+        
+        port = self.serverPort()
+        ## Note: Need the port if client is started external in debugger.
+        print('JSON server ({1}) listening on: {0:d}'   # __IGNORE_WARNING__
+              .format(port, self.__name))
+    
+    @pyqtSlot()
+    def handleNewConnection(self):
+        """
+        Public slot for new incoming connections from a client.
+        """
+        connection = self.nextPendingConnection()
+        if not connection.isValid():
+            return
+        
+        if self.__multiplex:
+            if not connection.waitForReadyRead(3000):
+                return
+            idString = bytes(connection.readLine()).decode(
+                "utf-8", 'backslashreplace').strip()
+            if idString in self.__connections:
+                self.__connections[idString].close()
+            self.__connections[idString] = connection
+        else:
+            idString = ""
+            if self.__connection is not None:
+                self.__connection.close()
+            
+            self.__connection = connection
+        
+        connection.readyRead.connect(
+            lambda: self.__receiveJson(idString))
+        connection.disconnected.connect(
+            lambda: self.__handleDisconnect(idString))
+    
+    @pyqtSlot()
+    def __handleDisconnect(self, idString):
+        """
+        Private slot handling a disconnect of the client.
+        
+        @param idString id of the connection been disconnected
+        @type str
+        """
+        if idString:
+            if idString in self.__connections:
+                self.__connections[idString].close()
+                del self.__connections[idString]
+        else:
+            if self.__connection is not None:
+                self.__connection.close()
+            
+            self.__connection = None
+    
+    def connectionNames(self):
+        """
+        Public method to get the list of active connection names.
+        
+        If this is not a multiplexing server, an empty list is returned.
+        
+        @return list of active connection names
+        @rtype list of str
+        """
+        if self.__multiplex:
+            return list(self.__connections.keys())
+        else:
+            return []
+    
+    @pyqtSlot()
+    def __receiveJson(self, idString):
+        """
+        Private slot handling received data from the client.
+        
+        @param idString id of the connection been disconnected
+        @type str
+        """
+        if idString:
+            try:
+                connection = self.__connections[idString]
+            except KeyError:
+                connection = None
+        else:
+            connection = self.__connection
+        
+        while connection and connection.canReadLine():
+            data = connection.readLine()
+            jsonLine = bytes(data).decode("utf-8", 'backslashreplace')
+            
+            #- print("JSON Server ({0}): {1}".format(self.__name, jsonLine))
+            #- this is for debugging only
+            
+            try:
+                clientDict = json.loads(jsonLine.strip())
+            except (TypeError, ValueError) as err:
+                E5MessageBox.critical(
+                    None,
+                    self.tr("JSON Protocol Error"),
+                    self.tr("""<p>The response received from the client"""
+                            """ could not be decoded. Please report"""
+                            """ this issue with the received data to the"""
+                            """ eric bugs email address.</p>"""
+                            """<p>Error: {0}</p>"""
+                            """<p>Data:<br/>{1}</p>""").format(
+                        str(err), Utilities.html_encode(jsonLine.strip())),
+                    E5MessageBox.StandardButtons(
+                        E5MessageBox.Ok))
+                return
+            
+            self.handleCall(clientDict["method"], clientDict["params"])
+    
+    def sendJson(self, command, params, flush=False, idString=""):
+        """
+        Public method to send a single command to a client.
+        
+        @param command command name to be sent
+        @type str
+        @param params dictionary of named parameters for the command
+        @type dict
+        @param flush flag indicating to flush the data to the socket
+        @type bool
+        @param idString id of the connection to send data to
+        @type str
+        """
+        commandDict = {
+            "jsonrpc": "2.0",
+            "method": command,
+            "params": params,
+        }
+        cmd = json.dumps(commandDict) + '\n'
+        
+        if idString:
+            try:
+                connection = self.__connections[idString]
+            except KeyError:
+                connection = None
+        else:
+            connection = self.__connection
+        
+        if connection is not None:
+            data = cmd.encode('utf8', 'backslashreplace')
+            length = "{0:09d}".format(len(data))
+            connection.write(length.encode() + data)
+            if flush:
+                connection.flush()
+    
+    def startClient(self, interpreter, clientScript, clientArgs, idString="",
+                    environment=None):
+        """
+        Public method to start a client process.
+        
+        @param interpreter interpreter to be used for the client
+        @type str
+        @param clientScript path to the client script
+        @type str
+        @param clientArgs list of arguments for the client
+        @param idString id of the client to be started
+        @type str
+        @param environment dictionary of environment settings to pass
+        @type dict
+        @return flag indicating a successful client start and the exit code
+            in case of an issue
+        @rtype bool, int
+        """
+        if interpreter == "" or not Utilities.isinpath(interpreter):
+            return False
+        
+        exitCode = None
+        
+        proc = QProcess()
+        proc.setProcessChannelMode(
+            QProcess.ProcessChannelMode.ForwardedChannels)
+        if environment is not None:
+            env = QProcessEnvironment()
+            for key, value in list(environment.items()):
+                env.insert(key, value)
+            proc.setProcessEnvironment(env)
+        args = [clientScript, self.__hostAddress, str(self.serverPort())]
+        if idString:
+            args.append(idString)
+        args.extend(clientArgs)
+        proc.start(interpreter, args)
+        if not proc.waitForStarted(10000):
+            proc = None
+        
+        if idString:
+            self.__clientProcesses[idString] = proc
+            if proc:
+                timer = QTimer()
+                timer.setSingleShot(True)
+                timer.start(30000)           # 30s timeout
+                while (
+                    idString not in self.connectionNames() and
+                    timer.isActive()
+                ):
+                    # Give the event loop the chance to process the new
+                    # connection of the client (= slow start).
+                    QCoreApplication.processEvents(
+                        QEventLoop.ProcessEventsFlag.ExcludeUserInputEvents)
+                    
+                    # check if client exited prematurely
+                    if proc.state() == QProcess.ProcessState.NotRunning:
+                        exitCode = proc.exitCode()
+                        proc = None
+                        self.__clientProcesses[idString] = None
+                        break
+        else:
+            if proc:
+                timer = QTimer()
+                timer.setSingleShot(True)
+                timer.start(1000)           # 1s timeout
+                while timer.isActive():
+                    # check if client exited prematurely
+                    QCoreApplication.processEvents(
+                        QEventLoop.ProcessEventsFlag.ExcludeUserInputEvents)
+                    if proc.state() == QProcess.ProcessState.NotRunning:
+                        exitCode = proc.exitCode()
+                        proc = None
+                        break
+            self.__clientProcess = proc
+        
+        return proc is not None, exitCode
+    
+    def stopClient(self, idString=""):
+        """
+        Public method to stop a client process.
+        
+        @param idString id of the client to be stopped
+        @type str
+        """
+        self.sendJson("Exit", {}, flush=True, idString=idString)
+        
+        if idString:
+            try:
+                connection = self.__connections[idString]
+            except KeyError:
+                connection = None
+        else:
+            connection = self.__connection
+        if connection is not None:
+            connection.waitForDisconnected()
+        
+        if idString:
+            with contextlib.suppress(KeyError):
+                if self .__clientProcesses[idString] is not None:
+                    self .__clientProcesses[idString].close()
+                del self.__clientProcesses[idString]
+        else:
+            if self.__clientProcess is not None:
+                self.__clientProcess.close()
+                self.__clientProcess = None
+    
+    def stopAllClients(self):
+        """
+        Public method to stop all clients.
+        """
+        clientNames = self.connectionNames()[:]
+        for clientName in clientNames:
+            self.stopClient(clientName)
+    
+    #######################################################################
+    ## The following methods should be overridden by derived classes
+    #######################################################################
+    
+    def handleCall(self, method, params):
+        """
+        Public method to handle a method call from the client.
+        
+        Note: This is an empty implementation that must be overridden in
+        derived classes.
+        
+        @param method requested method name
+        @type str
+        @param params dictionary with method specific parameters
+        @type dict
+        """
+        pass
--- a/eric6/E5XML/TasksReader.py	Sat May 01 14:27:38 2021 +0200
+++ b/eric6/E5XML/TasksReader.py	Thu Jun 03 11:39:23 2021 +0200
@@ -15,7 +15,7 @@
 from .Config import tasksFileFormatVersion
 from .XMLStreamReaderBase import XMLStreamReaderBase
 
-from Tasks.Task import Task
+from Tasks.Task import TaskType, TaskPriority
 
 import Utilities
 
@@ -80,25 +80,27 @@
         Private method to read the task info.
         """
         task = {"summary": "",
-                "priority": 1,
+                "priority": TaskPriority.NORMAL,
                 "completed": False,
                 "created": 0,
                 "filename": "",
                 "linenumber": 0,
-                "type": Task.TypeTodo,
+                "type": TaskType.TODO,
                 "description": "",
                 "uid": "",
                 }
-        task["priority"] = int(self.attribute("priority", "1"))
+        task["priority"] = TaskPriority(
+            int(self.attribute("priority", str(TaskPriority.NORMAL.value)))
+        )
         task["completed"] = self.toBool(self.attribute("completed", "False"))
         if self.version in ["4.2", "5.0"]:
             isBugfix = self.toBool(self.attribute("bugfix", "False"))
             if isBugfix:
-                task["type"] = Task.TypeFixme
+                task["type"] = TaskType.FIXME
         else:
-            # TODO: task type enum change
-            #  TaskType(int(self.attribute("type", str(Task.TypeTodo.value))))
-            task["type"] = int(self.attribute("type", str(Task.TypeTodo)))
+            task["type"] = TaskType(
+                int(self.attribute("type", str(TaskType.TODO.value)))
+            )
         uid = self.attribute("uid", "")
         if uid:
             task["uid"] = uid
--- a/eric6/E5XML/TasksWriter.py	Sat May 01 14:27:38 2021 +0200
+++ b/eric6/E5XML/TasksWriter.py	Thu Jun 03 11:39:23 2021 +0200
@@ -74,10 +74,9 @@
         )
         for task in tasks:
             self.writeStartElement("Task")
-            self.writeAttribute("priority", str(task.priority))
+            self.writeAttribute("priority", str(task.priority.value))
             self.writeAttribute("completed", str(task.completed))
-            # TODO: task type enum change; str(task.taskType.value)
-            self.writeAttribute("type", str(task.taskType))
+            self.writeAttribute("type", str(task.taskType.value))
             self.writeAttribute("uid", task.uid)
             if task.parentUid:
                 self.writeAttribute("parent_uid", task.parentUid)
--- a/eric6/Globals/__init__.py	Sat May 01 14:27:38 2021 +0200
+++ b/eric6/Globals/__init__.py	Thu Jun 03 11:39:23 2021 +0200
@@ -246,14 +246,18 @@
     configDir = os.path.expanduser(d)
 
 
-def getPythonModulesDirectory():
+def getPythonLibraryDirectory():
     """
-    Function to determine the path to Python's modules directory.
+    Function to determine the path to Python's library directory.
     
-    @return path to the Python modules directory (string)
+    @return path to the Python library directory
+    @rtype str
     """
     import distutils.sysconfig
     return distutils.sysconfig.get_python_lib(True)
+# backward compatibility for eric < 21.6
+getPythonModulesDirectory = getPythonLibraryDirectory
+# TODO: eric7: delete this
 
 
 def getPyQt5ModulesDirectory():
--- a/eric6/Graphics/ApplicationDiagramBuilder.py	Sat May 01 14:27:38 2021 +0200
+++ b/eric6/Graphics/ApplicationDiagramBuilder.py	Thu Jun 03 11:39:23 2021 +0200
@@ -10,7 +10,7 @@
 import os
 import glob
 
-from PyQt5.QtWidgets import QApplication
+from PyQt5.QtWidgets import QApplication, QInputDialog
 
 from E5Gui import E5MessageBox
 from E5Gui.E5ProgressDialog import E5ProgressDialog
@@ -29,11 +29,15 @@
         """
         Constructor
         
-        @param dialog reference to the UML dialog (UMLDialog)
-        @param view reference to the view object (UMLGraphicsView)
-        @param project reference to the project object (Project)
+        @param dialog reference to the UML dialog
+        @type UMLDialog
+        @param view reference to the view object
+        @type UMLGraphicsView
+        @param project reference to the project object
+        @type Project
         @param noModules flag indicating, that no module names should be
-            shown (boolean)
+            shown
+        @type bool
         """
         super().__init__(dialog, view, project)
         self.setObjectName("ApplicationDiagram")
@@ -49,7 +53,8 @@
         Private method to build a dictionary of modules contained in the
         application.
         
-        @return dictionary of modules contained in the application.
+        @return dictionary of modules contained in the application
+        @rtype dict
         """
         import Utilities.ModuleParser
         extensions = (
@@ -88,27 +93,74 @@
             progress.setValue(tot)
             progress.deleteLater()
         return moduleDict
+    
+    def __findApplicationRoot(self):
+        """
+        Private method to find the application root path.
+        
+        @return application root path
+        @rtype str
+        """
+        candidates = []
+        path = self.project.getProjectPath()
+        init = os.path.join(path, "__init__.py")
+        if os.path.exists(init):
+            # project is a package
+            return path
+        else:
+            # check, if one of the top directories is a package
+            for entry in os.listdir(path):
+                if entry.startswith("."):
+                    # ignore hidden files and directories
+                    continue
+                
+                fullpath = os.path.join(path, entry)
+                if os.path.isdir(fullpath):
+                    init = os.path.join(fullpath, "__init__.py")
+                    if os.path.exists(init):
+                        candidates.append(fullpath)
+            
+            if len(candidates) == 1:
+                return candidates[0]
+            elif len(candidates) > 1:
+                root, ok = QInputDialog.getItem(
+                    None,
+                    self.tr("Application Diagram"),
+                    self.tr("Select the application directory:"),
+                    sorted(candidates),
+                    0, True)
+                if ok:
+                    return root
+            else:
+                E5MessageBox.warning(
+                    None,
+                    self.tr("Application Diagram"),
+                    self.tr("""No application package could be detected."""
+                            """ Aborting..."""))
+        return None
         
     def buildDiagram(self):
         """
         Public method to build the packages shapes of the diagram.
         """
-        project = (
-            os.path.splitdrive(self.project.getProjectPath())[1]
-            .replace(os.sep, '.')[1:]
-        )
+        rpath = self.__findApplicationRoot()
+        if rpath is None:
+            # no root path detected
+            return
+        
+        root = os.path.splitdrive(rpath)[1].replace(os.sep, '.')[1:]
+        
         packages = {}
-        shapes = {}
-        p = 10
-        y = 10
-        maxHeight = 0
-        sceneRect = self.umlView.sceneRect()
+        self.__shapes = {}
         
         modules = self.__buildModulesDict()
         
         # step 1: build a dictionary of packages
         for module in sorted(modules.keys()):
-            packageName, moduleName = module.rsplit(".", 1)
+            if "." in module:
+                packageName, moduleName = module.rsplit(".", 1)
+            else:
+                packageName, moduleName = "", module
             if packageName in packages:
                 packages[packageName][0].append(moduleName)
             else:
@@ -128,14 +180,14 @@
                         if n in modules:
                             impLst.append(n)
                         else:
-                            n = "{0}.{1}".format(project, moduleImport)
+                            n = "{0}.{1}".format(root, moduleImport)
                             if n in modules:
                                 impLst.append(n)
                             elif n in packages:
                                 n = "{0}.<<Dummy>>".format(n)
                                 impLst.append(n)
                     else:
-                        n = "{0}.{1}".format(project, moduleImport)
+                        n = "{0}.{1}".format(root, moduleImport)
                         if n in modules:
                             impLst.append(n)
             for moduleImport in list(modules[module].from_imports.keys()):
@@ -170,27 +222,30 @@
                         if n in modules:
                             impLst.append(n)
                         else:
-                            n = "{0}.{1}".format(project, moduleImport)
+                            n = "{0}.{1}".format(root, moduleImport)
                             if n in modules:
                                 impLst.append(n)
                             elif n in packages:
                                 n = "{0}.<<Dummy>>".format(n)
                                 impLst.append(n)
                     else:
-                        n = "{0}.{1}".format(project, moduleImport)
+                        n = "{0}.{1}".format(root, moduleImport)
                         if n in modules:
                             impLst.append(n)
             for moduleImport in impLst:
                 impPackage = moduleImport.rsplit(".", 1)[0]
-                if (
-                    impPackage not in packages[package][1] and
-                    impPackage != package
-                ):
-                    packages[package][1].append(impPackage)
-                    
+                try:
+                    if (
+                        impPackage not in packages[package][1] and
+                        impPackage != package
+                    ):
+                        packages[package][1].append(impPackage)
+                except KeyError:
+                    continue
+        
         for package in sorted(packages.keys()):
             if package:
-                relPackage = package.replace(project, '')
+                relPackage = package.replace(root, '')
                 if relPackage and relPackage[0] == '.':
                     relPackage = relPackage[1:]
                 else:
@@ -199,41 +254,36 @@
                 relPackage = self.tr("<<Others>>")
             shape = self.__addPackage(
                 relPackage, packages[package][0], 0.0, 0.0)
-            shapeRect = shape.sceneBoundingRect()
-            shapes[package] = (shape, packages[package][1])
-            pn = p + shapeRect.width() + 10
-            maxHeight = max(maxHeight, shapeRect.height())
-            if pn > sceneRect.width():
-                p = 10
-                y += maxHeight + 10
-                maxHeight = shapeRect.height()
-                shape.setPos(p, y)
-                p += shapeRect.width() + 10
-            else:
-                shape.setPos(p, y)
-                p = pn
+            self.__shapes[package] = (shape, packages[package][1])
         
-        rect = self.umlView._getDiagramRect(10)
-        sceneRect = self.umlView.sceneRect()
-        if rect.width() > sceneRect.width():
-            sceneRect.setWidth(rect.width())
-        if rect.height() > sceneRect.height():
-            sceneRect.setHeight(rect.height())
-        self.umlView.setSceneSize(sceneRect.width(), sceneRect.height())
+        # build a list of routes
+        nodes = []
+        routes = []
+        for module in self.__shapes:
+            nodes.append(module)
+            for rel in self.__shapes[module][1]:
+                route = (module, rel)
+                if route not in routes:
+                    routes.append(route)
         
-        self.__createAssociations(shapes)
+        self.__arrangeNodes(nodes, routes[:])
+        self.__createAssociations(routes)
         self.umlView.autoAdjustSceneSize(limit=True)
-        
+    
     def __addPackage(self, name, modules, x, y):
         """
         Private method to add a package to the diagram.
         
-        @param name package name to be shown (string)
+        @param name package name to be shown
+        @type str
         @param modules list of module names contained in the package
-            (list of strings)
-        @param x x-coordinate (float)
-        @param y y-coordinate (float)
-        @return reference to the package item (PackageItem)
+        @type list of str
+        @param x x-coordinate
+        @type float
+        @param y y-coordinate
+        @type float
+        @return reference to the package item
+        @rtype PackageItem
         """
         from .PackageItem import PackageItem, PackageModel
         modules.sort()
@@ -242,27 +292,108 @@
                          colors=self.umlView.getDrawingColors())
         pw.setId(self.umlView.getItemId())
         return pw
+    
+    def __arrangeNodes(self, nodes, routes, whiteSpaceFactor=1.2):
+        """
+        Private method to arrange the shapes on the canvas.
         
-    def __createAssociations(self, shapes):
+        The algorithm is borrowed from Boa Constructor.
+        
+        @param nodes list of nodes to arrange
+        @type list of str
+        @param routes list of routes
+        @type list of tuple of (str, str)
+        @param whiteSpaceFactor factor to increase whitespace between
+            items
+        @type float
         """
-        Private method to generate the associations between the package shapes.
+        from . import GraphicsUtilities
+        generations = GraphicsUtilities.sort(nodes, routes)
+        
+        # calculate width and height of all elements
+        sizes = []
+        for generation in generations:
+            sizes.append([])
+            for child in generation:
+                sizes[-1].append(
+                    self.__shapes[child][0].sceneBoundingRect())
+                
+        # calculate total width and total height
+        width = 0
+        height = 0
+        widths = []
+        heights = []
+        for generation in sizes:
+            currentWidth = 0
+            currentHeight = 0
+            
+            for rect in generation:
+                if rect.height() > currentHeight:
+                    currentHeight = rect.height()
+                currentWidth += rect.width()
+                
+            # update totals
+            if currentWidth > width:
+                width = currentWidth
+            height += currentHeight
+            
+            # store generation info
+            widths.append(currentWidth)
+            heights.append(currentHeight)
         
-        @param shapes list of shapes
+        # add in some whitespace
+        width *= whiteSpaceFactor
+        height = height * whiteSpaceFactor - 20
+        verticalWhiteSpace = 40.0
+        
+        sceneRect = self.umlView.sceneRect()
+        width += 50.0
+        height += 50.0
+        swidth = sceneRect.width() if width < sceneRect.width() else width
+        sheight = sceneRect.height() if height < sceneRect.height() else height
+        self.umlView.setSceneSize(swidth, sheight)
+        
+        # distribute each generation across the width and the
+        # generations across height
+        y = 10.0
+        for currentWidth, currentHeight, generation in (
+            zip(reversed(widths), reversed(heights), reversed(generations))
+        ):
+            x = 10.0
+            # whiteSpace is the space between any two elements
+            whiteSpace = (
+                (width - currentWidth - 20) /
+                (len(generation) - 1.0 or 2.0)
+            )
+            for name in generation:
+                shape = self.__shapes[name][0]
+                shape.setPos(x, y)
+                rect = shape.sceneBoundingRect()
+                x = x + rect.width() + whiteSpace
+            y = y + currentHeight + verticalWhiteSpace
+    
+    def __createAssociations(self, routes):
+        """
+        Private method to generate the associations between the module shapes.
+        
+        @param routes list of associations
+        @type list of tuple of (str, str)
         """
         from .AssociationItem import AssociationItem, AssociationType
-        for package in shapes:
-            for rel in shapes[package][1]:
-                assoc = AssociationItem(
-                    shapes[package][0], shapes[rel][0],
-                    AssociationType.IMPORTS,
-                    colors=self.umlView.getDrawingColors())
-                self.scene.addItem(assoc)
+        for route in routes:
+            assoc = AssociationItem(
+                self.__shapes[route[0]][0],
+                self.__shapes[route[1]][0],
+                AssociationType.IMPORTS,
+                colors=self.umlView.getDrawingColors())
+            self.scene.addItem(assoc)
     
     def getPersistenceData(self):
         """
         Public method to get a string for data to be persisted.
         
-        @return persisted data string (string)
+        @return persisted data string
+        @rtype str
         """
         return "project={0}, no_modules={1}".format(
             self.project.getProjectFile(), self.noModules)
@@ -271,9 +402,12 @@
         """
         Public method to parse persisted data.
         
-        @param version version of the data (string)
-        @param data persisted data to be parsed (string)
-        @return flag indicating success (boolean)
+        @param version version of the data
+        @type str
+        @param data persisted data to be parsed
+        @type str
+        @return flag indicating success
+        @rtype bool
         """
         parts = data.split(", ")
         if (
@@ -300,3 +434,43 @@
         self.initialize()
         
         return True
+    
+    def toDict(self):
+        """
+        Public method to collect data to be persisted.
+        
+        @return dictionary containing data to be persisted
+        @rtype dict
+        """
+        return {
+            "project_name": self.project.getProjectName(),
+            "no_modules": self.noModules,
+        }
+    
+    def fromDict(self, version, data):
+        """
+        Public method to populate the class with data persisted by 'toDict()'.
+        
+        @param version version of the data
+        @type str
+        @param data dictionary containing the persisted data
+        @type dict
+        @return tuple containing a flag indicating success and an info
+            message in case the diagram belongs to a different project
+        @rtype tuple of (bool, str)
+        """
+        try:
+            self.noModules = data["no_modules"]
+            
+            if data["project_name"] != self.project.getProjectName():
+                msg = self.tr(
+                    "<p>The diagram belongs to project <b>{0}</b>."
+                    " Please open it and try again.</p>"
+                ).format(data["project_name"])
+                return False, msg
+        except KeyError:
+            return False, ""
+        
+        self.initialize()
+        
+        return True, ""
--- a/eric6/Graphics/AssociationItem.py	Sat May 01 14:27:38 2021 +0200
+++ b/eric6/Graphics/AssociationItem.py	Thu Jun 03 11:39:23 2021 +0200
@@ -107,8 +107,10 @@
         Private method to map item's rectangle to this item's coordinate
         system.
         
-        @param item reference to the item to be mapped (QGraphicsRectItem)
-        @return item's rectangle in local coordinates (QRectF)
+        @param item reference to the item to be mapped
+        @type QGraphicsRectItem
+        @return item's rectangle in local coordinates
+        @rtype QRectF
         """
         rect = item.rect()
         tl = self.mapFromItem(item, rect.topLeft())
@@ -260,9 +262,12 @@
         Private method to find out, which region of rectangle rect contains
         the point (PosX, PosY) and returns the region number.
         
-        @param rect rectangle to calculate the region for (QRectF)
-        @param posX x position of point (float)
-        @param posY y position of point (float)
+        @param rect rectangle to calculate the region for
+        @type QRectF
+        @param posX x position of point
+        @type float
+        @param posY y position of point
+        @type float
         @return the calculated region number<br />
             West = Region 1<br />
             North = Region 2<br />
@@ -273,6 +278,7 @@
             SouthEast = On diagonal 2 between Region 3 and 4<br />
             SouthWest = On diagonal 1 between Region4 and 1<br />
             Center = On diagonal 1 and On diagonal 2 (the center)<br />
+        @rtype AssociationPointRegion
         """
         w = rect.width()
         h = rect.height()
@@ -330,8 +336,10 @@
         """
         Private method to update an endpoint.
         
-        @param region the region for the endpoint (integer)
-        @param isWidgetA flag indicating update for itemA is done (boolean)
+        @param region the region for the endpoint
+        @type AssociationPointRegion
+        @param isWidgetA flag indicating update for itemA is done
+        @type bool
         """
         if region == AssociationPointRegion.NO_REGION:
             return
@@ -371,13 +379,17 @@
         
     def __findRectIntersectionPoint(self, item, p1, p2):
         """
-        Private method to find the intersetion point of a line with a
+        Private method to find the intersection point of a line with a
         rectangle.
         
         @param item item to check against
-        @param p1 first point of the line (QPointF)
-        @param p2 second point of the line (QPointF)
-        @return the intersection point (QPointF)
+        @type UMLItem
+        @param p1 first point of the line
+        @type QPointF
+        @param p2 second point of the line
+        @type QPointF
+        @return the intersection point
+        @rtype QPointF
         """
         rect = self.__mapRectFromItem(item)
         lines = [
@@ -419,11 +431,16 @@
         In order for the linear function calculations to work in this method
         we must switch x and y values (x values become y values and viceversa)
         
-        @param p1 first point of first line (QPointF)
-        @param p2 second point of first line (QPointF)
-        @param p3 first point of second line (QPointF)
-        @param p4 second point of second line (QPointF)
-        @return the intersection point (QPointF)
+        @param p1 first point of first line
+        @type QPointF
+        @param p2 second point of first line
+        @type QPointF
+        @param p3 first point of second line
+        @type QPointF
+        @param p4 second point of second line
+        @type QPointF
+        @return the intersection point
+        @rtype QPointF
         """
         x1 = p1.y()
         y1 = p1.x()
@@ -545,7 +562,8 @@
         This string should be built like "attribute=value" with pairs separated
         by ", ". value must not contain ", " or newlines.
         
-        @return persistence data (string)
+        @return persistence data
+        @rtype str
         """
         entries = [
             "src={0}".format(self.itemA.getId()),
@@ -560,10 +578,12 @@
         """
         Class method to parse the given persistence data.
         
-        @param data persisted data to be parsed (string)
+        @param data persisted data to be parsed
+        @type str
         @return tuple with the IDs of the source and destination items,
             the association type and a flag indicating to associate from top
-            to bottom (integer, integer, integer, boolean)
+            to bottom
+        @rtype tuple of (int, int, int, bool)
         """
         src = -1
         dst = -1
@@ -582,3 +602,41 @@
                     topToBottom = Utilities.toBool(value)
         
         return src, dst, assocType, topToBottom
+    
+    def toDict(self):
+        """
+        Public method to collect data to be persisted.
+        
+        @return dictionary containing data to be persisted
+        @rtype dict
+        """
+        return {
+            "src": self.itemA.getId(),
+            "dst": self.itemB.getId(),
+            "type": self.assocType.value,
+            "topToBottom": self.topToBottom,
+        }
+    
+    @classmethod
+    def fromDict(cls, data, umlItems, colors=None):
+        """
+        Class method to create an association item from persisted data.
+        
+        @param data dictionary containing the persisted data as generated
+            by toDict()
+        @type dict
+        @param umlItems list of UML items
+        @type list of UMLItem
+        @param colors tuple containing the foreground and background colors
+        @type tuple of (QColor, QColor)
+        @return created association item
+        @rtype AssociationItem
+        """
+        try:
+            return cls(umlItems[data["src"]],
+                       umlItems[data["dst"]],
+                       assocType=AssociationType(data["type"]),
+                       topToBottom=data["topToBottom"],
+                       colors=colors)
+        except (KeyError, ValueError):
+            return None
--- a/eric6/Graphics/ClassItem.py	Sat May 01 14:27:38 2021 +0200
+++ b/eric6/Graphics/ClassItem.py	Thu Jun 03 11:39:23 2021 +0200
@@ -7,6 +7,7 @@
 Module implementing an UML like class item.
 """
 
+from PyQt5.QtCore import QCoreApplication
 from PyQt5.QtGui import QFont
 from PyQt5.QtWidgets import QGraphicsSimpleTextItem, QStyle
 
@@ -19,53 +20,88 @@
     """
     Class implementing the class model.
     """
-    def __init__(self, name, methods=None, attributes=None):
+    def __init__(self, name, methods=None, instanceAttributes=None,
+                 classAttributes=None):
         """
         Constructor
         
-        @param name the class name (string)
+        @param name the class name
+        @type str
         @param methods list of method names of the class
-            (list of strings)
-        @param attributes list of attribute names of the class
-            (list of strings)
+        @type list of str
+        @param instanceAttributes list of instance attribute names of the class
+        @type list of str
+        @param classAttributes list of class attribute names of the class
+        @type list of str
         """
         super().__init__(name)
         
         self.methods = [] if methods is None else methods[:]
-        self.attributes = [] if attributes is None else attributes[:]
+        self.instanceAttributes = (
+            []
+            if instanceAttributes is None else
+            instanceAttributes[:]
+        )
+        self.classAttributes = (
+            []
+            if classAttributes is None else
+            classAttributes[:]
+        )
     
     def addMethod(self, method):
         """
         Public method to add a method to the class model.
         
-        @param method method name to be added (string)
+        @param method method name to be added
+        @type str
         """
         self.methods.append(method)
     
-    def addAttribute(self, attribute):
+    def addInstanceAttribute(self, attribute):
         """
-        Public method to add an attribute to the class model.
+        Public method to add an instance attribute to the class model.
         
-        @param attribute attribute name to be added (string)
+        @param attribute instance attribute name to be added
+        @type str
+        """
+        self.instanceAttributes.append(attribute)
+    
+    def addClassAttribute(self, attribute):
         """
-        self.attributes.append(attribute)
+        Public method to add a class attribute to the class model.
+        
+        @param attribute class attribute name to be added
+        @type str
+        """
+        self.classAttributes.append(attribute)
     
     def getMethods(self):
         """
         Public method to retrieve the methods of the class.
         
-        @return list of class methods (list of strings)
+        @return list of class methods
+        @rtype list of str
         """
         return self.methods[:]
     
-    def getAttributes(self):
+    def getInstanceAttributes(self):
         """
         Public method to retrieve the attributes of the class.
         
-        @return list of class attributes (list of strings)
+        @return list of instance attributes
+        @rtype list of str
+        """
+        return self.instanceAttributes[:]
+    
+    def getClassAttributes(self):
         """
-        return self.attributes[:]
-    
+        Public method to retrieve the global attributes of the class.
+        
+        @return list of class attributes
+        @rtype list of str
+        """
+        return self.classAttributes[:]
+
 
 class ClassItem(UMLItem):
     """
@@ -103,7 +139,8 @@
         self.external = external
         self.noAttrs = noAttrs
         
-        scene.addItem(self)
+        if scene:
+            scene.addItem(self)
         
         if self.model:
             self.__createTexts()
@@ -118,8 +155,10 @@
         
         boldFont = QFont(self.font)
         boldFont.setBold(True)
+        boldFont.setUnderline(True)
         
-        attrs = self.model.getAttributes()
+        classAttributes = self.model.getClassAttributes()
+        attrs = self.model.getInstanceAttributes()
         meths = self.model.getMethods()
         
         x = self.margin + self.rect().x()
@@ -130,13 +169,32 @@
         self.header.setText(self.model.getName())
         self.header.setPos(x, y)
         y += self.header.boundingRect().height() + self.margin
+        
+        if self.external:
+            self.classAttributes = None
+        else:
+            txt = QCoreApplication.translate(
+                "ClassItem", "Class Attributes:\n  ")
+            txt += (
+                "\n  ".join(classAttributes)
+                if globals else
+                "  " + QCoreApplication.translate("ClassItem", "none")
+            )
+            self.classAttributes = QGraphicsSimpleTextItem(self)
+            self.classAttributes.setBrush(self._colors[0])
+            self.classAttributes.setFont(self.font)
+            self.classAttributes.setText(txt)
+            self.classAttributes.setPos(x, y)
+            y += self.classAttributes.boundingRect().height() + self.margin
+        
         if not self.noAttrs and not self.external:
-            # TODO: add class attributes next to the instance attributes
-            #       separate class and instance attributes by dashed line
-            if attrs:
-                txt = "\n".join(attrs)
-            else:
-                txt = " "
+            txt = QCoreApplication.translate(
+                "ClassItem", "Instance Attributes:\n  ")
+            txt += (
+                "\n  ".join(attrs)
+                if attrs else
+                "  " + QCoreApplication.translate("ClassItem", "none")
+            )
             self.attrs = QGraphicsSimpleTextItem(self)
             self.attrs.setBrush(self._colors[0])
             self.attrs.setFont(self.font)
@@ -145,7 +203,16 @@
             y += self.attrs.boundingRect().height() + self.margin
         else:
             self.attrs = None
-        txt = "\n".join(meths) if meths else " "
+        
+        if self.external:
+            txt = " "
+        else:
+            txt = QCoreApplication.translate("ClassItem", "Methods:\n  ")
+            txt += (
+                "\n  ".join(meths)
+                if meths else
+                "  " + QCoreApplication.translate("ClassItem", "none")
+            )
         self.meths = QGraphicsSimpleTextItem(self)
         self.meths.setBrush(self._colors[0])
         self.meths.setFont(self.font)
@@ -161,22 +228,32 @@
         
         width = self.header.boundingRect().width()
         height = self.header.boundingRect().height()
+        if self.classAttributes:
+            width = max(width, self.classAttributes.boundingRect().width())
+            height += (
+                self.classAttributes.boundingRect().height() + self.margin
+            )
         if self.attrs:
             width = max(width, self.attrs.boundingRect().width())
             height = height + self.attrs.boundingRect().height() + self.margin
         if self.meths:
             width = max(width, self.meths.boundingRect().width())
             height += self.meths.boundingRect().height()
+        
         self.setSize(width + 2 * self.margin, height + 2 * self.margin)
         
     def setModel(self, model):
         """
         Public method to set the class model.
         
-        @param model class model containing the class data (ClassModel)
+        @param model class model containing the class data
+        @type ClassModel
         """
         self.scene().removeItem(self.header)
         self.header = None
+        if self.classAttributes:
+            self.scene().removeItem(self.classAttributes)
+            self.classAttributes = None
         if self.attrs:
             self.scene().removeItem(self.attrs)
             self.attrs = None
@@ -191,9 +268,12 @@
         """
         Public method to paint the item in local coordinates.
         
-        @param painter reference to the painter object (QPainter)
-        @param option style options (QStyleOptionGraphicsItem)
-        @param widget optional reference to the widget painted on (QWidget)
+        @param painter reference to the painter object
+        @type QPainter
+        @param option style options
+        @type QStyleOptionGraphicsItem
+        @param widget optional reference to the widget painted on
+        @type QWidget
         """
         pen = self.pen()
         if (
@@ -216,6 +296,10 @@
         painter.drawRect(offsetX, offsetY, w, h)
         y = self.margin + self.header.boundingRect().height()
         painter.drawLine(offsetX, offsetY + y, offsetX + w - 1, offsetY + y)
+        if self.classAttributes:
+            y += self.margin + self.classAttributes.boundingRect().height()
+            painter.drawLine(offsetX, offsetY + y,
+                             offsetX + w - 1, offsetY + y)
         if self.attrs:
             y += self.margin + self.attrs.boundingRect().height()
             painter.drawLine(offsetX, offsetY + y,
@@ -227,7 +311,8 @@
         """
         Public method returning the external state.
         
-        @return external state (boolean)
+        @return external state
+        @rtype bool
         """
         return self.external
     
@@ -239,19 +324,26 @@
         "attribute=value" with pairs separated by ", ". value must not
         contain ", " or newlines.
         
-        @return persistence data (string)
+        @return persistence data
+        @rtype str
         """
         entries = [
             "is_external={0}".format(self.external),
             "no_attributes={0}".format(self.noAttrs),
             "name={0}".format(self.model.getName()),
         ]
-        attributes = self.model.getAttributes()
-        if attributes:
-            entries.append("attributes={0}".format("||".join(attributes)))
+        instanceAttributes = self.model.getInstanceAttributes()
+        if instanceAttributes:
+            entries.append("attributes={0}".format(
+                "||".join(instanceAttributes)))
         methods = self.model.getMethods()
         if methods:
-            entries.append("methods={0}".format("||".join(methods)))
+            entries.append("methods={0}".format(
+                "||".join(methods)))
+        classAttributes = self.model.getClassAttributes()
+        if classAttributes:
+            entries.append("class_attributes={0}".format(
+                "||".join(classAttributes)))
         
         return ", " + ", ".join(entries)
     
@@ -259,17 +351,21 @@
         """
         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)
+        @param version version of the data
+        @type str
+        @param data persisted data to be parsed
+        @type str
+        @return flag indicating success
+        @rtype bool
         """
         parts = data.split(", ")
         if len(parts) < 3:
             return False
         
         name = ""
-        attributes = []
+        instanceAttributes = []
         methods = []
+        classAttributes = []
         
         for part in parts:
             key, value = part.split("=", 1)
@@ -280,14 +376,67 @@
             elif key == "name":
                 name = value.strip()
             elif key == "attributes":
-                attributes = value.strip().split("||")
+                instanceAttributes = value.strip().split("||")
             elif key == "methods":
                 methods = value.strip().split("||")
+            elif key == "class_attributes":
+                classAttributes = value.strip().split("||")
             else:
                 return False
         
-        self.model = ClassModel(name, methods, attributes)
+        self.model = ClassModel(name, methods, instanceAttributes,
+                                classAttributes)
         self.__createTexts()
         self.__calculateSize()
         
         return True
+    
+    def toDict(self):
+        """
+        Public method to collect data to be persisted.
+        
+        @return dictionary containing data to be persisted
+        @rtype dict
+        """
+        return {
+            "id": self.getId(),
+            "x": self.x(),
+            "y": self.y(),
+            "type": self.getItemType(),
+            "is_external": self.external,
+            "no_attributes": self.noAttrs,
+            "model_name": self.model.getName(),
+            "attributes": self.model.getInstanceAttributes(),
+            "methods": self.model.getMethods(),
+            "class_attributes": self.model.getClassAttributes(),
+        }
+    
+    @classmethod
+    def fromDict(cls, data, colors=None):
+        """
+        Class method to create a class item from persisted data.
+        
+        @param data dictionary containing the persisted data as generated
+            by toDict()
+        @type dict
+        @param colors tuple containing the foreground and background colors
+        @type tuple of (QColor, QColor)
+        @return created class item
+        @rtype ClassItem
+        """
+        try:
+            model = ClassModel(data["model_name"],
+                               data["methods"],
+                               data["attributes"],
+                               data["class_attributes"])
+            itm = cls(model=model,
+                      external=data["is_external"],
+                      x=0,
+                      y=0,
+                      noAttrs=data["no_attributes"],
+                      colors=colors)
+            itm.setPos(data["x"], data["y"])
+            itm.setId(data["id"])
+            return itm
+        except KeyError:
+            return None
--- a/eric6/Graphics/GraphicsUtilities.py	Sat May 01 14:27:38 2021 +0200
+++ b/eric6/Graphics/GraphicsUtilities.py	Thu Jun 03 11:39:23 2021 +0200
@@ -25,10 +25,14 @@
     The algorithm was taken from Boa Constructor.
     
     @param nodes list of nodes to be sorted
+    @type str
     @param routes list of routes between the nodes
+    @type list of tuple of (str, str)
     @param noRecursion flag indicating, if recursion errors should be raised
+    @type bool
+    @return list of stages
+    @rtype list of lists of str
     @exception RecursionError a recursion error was detected
-    @return list of stages
     """
     children, parents = _buildChildrenLists(routes)
     
@@ -97,7 +101,9 @@
     Taken from Boa Constructor.
     
     @param routes list of routes between nodes
+    @type list of tuple of (str, str)
     @return dictionary of child and dictionary of parent relationships
+    @rtype tuple of (dict, dict)
     """
     childrenTable = {}
     parentTable = {}
--- a/eric6/Graphics/ImportsDiagramBuilder.py	Sat May 01 14:27:38 2021 +0200
+++ b/eric6/Graphics/ImportsDiagramBuilder.py	Thu Jun 03 11:39:23 2021 +0200
@@ -32,19 +32,30 @@
         """
         Constructor
         
-        @param dialog reference to the UML dialog (UMLDialog)
-        @param view reference to the view object (UMLGraphicsView)
-        @param project reference to the project object (Project)
+        @param dialog reference to the UML dialog
+        @type UMLDialog
+        @param view reference to the view object
+        @type UMLGraphicsView
+        @param project reference to the project object
+        @type Project
         @param package name of a python package to show the import
-            relationships (string)
+            relationships
+        @type str
         @param showExternalImports flag indicating to show exports from
-            outside the package (boolean)
+            outside the package
+        @type bool
         """
         super().__init__(dialog, view, project)
         self.setObjectName("ImportsDiagram")
         
         self.showExternalImports = showExternalImports
         self.packagePath = os.path.abspath(package)
+        
+        self.__relPackagePath = (
+            self.project.getRelativePath(self.packagePath)
+            if self.project.isProjectSource(self.packagePath) else
+            ""
+        )
     
     def initialize(self):
         """
@@ -74,7 +85,8 @@
         Private method to build a dictionary of modules contained in the
         package.
         
-        @return dictionary of modules contained in the package.
+        @return dictionary of modules contained in the package
+        @rtype dict
         """
         import Utilities.ModuleParser
         extensions = (
@@ -121,115 +133,97 @@
         initlist = glob.glob(os.path.join(self.packagePath, '__init__.*'))
         if len(initlist) == 0:
             ct = QGraphicsTextItem(None)
-            ct.setHtml(
-                self.tr(
-                    "The directory <b>'{0}'</b> is not a Python package.")
-                .format(self.package))
+            ct.setHtml(self.buildErrorMessage(
+                self.tr("The directory <b>'{0}'</b> is not a Python"
+                        " package.").format(self.package)
+            ))
             self.scene.addItem(ct)
             return
         
-        shapes = {}
-        p = 10
-        y = 10
-        maxHeight = 0
-        sceneRect = self.umlView.sceneRect()
+        self.__shapes = {}
         
         modules = self.__buildModulesDict()
-        sortedkeys = sorted(modules.keys())
         externalMods = []
         packageList = self.shortPackage.split('.')
         packageListLen = len(packageList)
-        for module in sortedkeys:
+        for module in sorted(modules.keys()):
             impLst = []
-            for i in modules[module].imports:
-                n = (i[len(self.package) + 1:]
-                     if i.startswith(self.package) else i)
-                if i in modules:
+            for importName in modules[module].imports:
+                n = (
+                    importName[len(self.package) + 1:]
+                    if importName.startswith(self.package) else
+                    importName
+                )
+                if importName in modules:
                     impLst.append(n)
                 elif self.showExternalImports:
                     impLst.append(n)
                     if n not in externalMods:
                         externalMods.append(n)
-            for i in list(modules[module].from_imports.keys()):
-                if i.startswith('.'):
-                    dots = len(i) - len(i.lstrip('.'))
+            for importName in list(modules[module].from_imports.keys()):
+                if importName.startswith('.'):
+                    dots = len(importName) - len(importName.lstrip('.'))
                     if dots == 1:
-                        n = i[1:]
-                        i = n
+                        n = importName[1:]
+                        importName = n
                     else:
                         if self.showExternalImports:
                             n = '.'.join(
                                 packageList[:packageListLen - dots + 1] +
-                                [i[dots:]])
+                                [importName[dots:]])
                         else:
-                            n = i
-                elif i.startswith(self.package):
-                    n = i[len(self.package) + 1:]
+                            n = importName
+                elif importName.startswith(self.package):
+                    n = importName[len(self.package) + 1:]
                 else:
-                    n = i
-                if i in modules:
+                    n = importName
+                if importName in modules:
                     impLst.append(n)
                 elif self.showExternalImports:
                     impLst.append(n)
                     if n not in externalMods:
                         externalMods.append(n)
+            
             classNames = []
-            for cls in list(modules[module].classes.keys()):
-                className = modules[module].classes[cls].name
+            for class_ in list(modules[module].classes.keys()):
+                className = modules[module].classes[class_].name
                 if className not in classNames:
                     classNames.append(className)
             shape = self.__addModule(module, classNames, 0.0, 0.0)
-            shapeRect = shape.sceneBoundingRect()
-            shapes[module] = (shape, impLst)
-            pn = p + shapeRect.width() + 10
-            maxHeight = max(maxHeight, shapeRect.height())
-            if pn > sceneRect.width():
-                p = 10
-                y += maxHeight + 10
-                maxHeight = shapeRect.height()
-                shape.setPos(p, y)
-                p += shapeRect.width() + 10
-            else:
-                shape.setPos(p, y)
-                p = pn
+            self.__shapes[module] = (shape, impLst)
         
         for module in externalMods:
             shape = self.__addModule(module, [], 0.0, 0.0)
-            shapeRect = shape.sceneBoundingRect()
-            shapes[module] = (shape, [])
-            pn = p + shapeRect.width() + 10
-            maxHeight = max(maxHeight, shapeRect.height())
-            if pn > sceneRect.width():
-                p = 10
-                y += maxHeight + 10
-                maxHeight = shapeRect.height()
-                shape.setPos(p, y)
-                p += shapeRect.width() + 10
-            else:
-                shape.setPos(p, y)
-                p = pn
+            self.__shapes[module] = (shape, [])
         
-        rect = self.umlView._getDiagramRect(10)
-        sceneRect = self.umlView.sceneRect()
-        if rect.width() > sceneRect.width():
-            sceneRect.setWidth(rect.width())
-        if rect.height() > sceneRect.height():
-            sceneRect.setHeight(rect.height())
-        self.umlView.setSceneSize(sceneRect.width(), sceneRect.height())
+        # build a list of routes
+        nodes = []
+        routes = []
+        for module in self.__shapes:
+            nodes.append(module)
+            for rel in self.__shapes[module][1]:
+                route = (module, rel)
+                if route not in routes:
+                    routes.append(route)
         
-        self.__createAssociations(shapes)
+        self.__arrangeNodes(nodes, routes[:])
+        self.__createAssociations(routes)
         self.umlView.autoAdjustSceneSize(limit=True)
     
     def __addModule(self, name, classes, x, y):
         """
         Private method to add a module to the diagram.
         
-        @param name module name to be shown (string)
+        @param name module name to be shown
+        @type str
         @param classes list of class names contained in the module
-            (list of strings)
-        @param x x-coordinate (float)
-        @param y y-coordinate (float)
-        @return reference to the imports item (ModuleItem)
+        @type list of str
+        @param x x-coordinate
+        @type float
+        @param y y-coordinate
+        @type float
+        @return reference to the imports item
+        @rtype ModuleItem
         """
         from .ModuleItem import ModuleItem, ModuleModel
         classes.sort()
@@ -239,26 +233,107 @@
         impW.setId(self.umlView.getItemId())
         return impW
     
-    def __createAssociations(self, shapes):
+    def __arrangeNodes(self, nodes, routes, whiteSpaceFactor=1.2):
+        """
+        Private method to arrange the shapes on the canvas.
+        
+        The algorithm is borrowed from Boa Constructor.
+        
+        @param nodes list of nodes to arrange
+        @type list of str
+        @param routes list of routes
+        @type list of tuple of (str, str)
+        @param whiteSpaceFactor factor to increase whitespace between
+            items
+        @type float
+        """
+        from . import GraphicsUtilities
+        generations = GraphicsUtilities.sort(nodes, routes)
+        
+        # calculate width and height of all elements
+        sizes = []
+        for generation in generations:
+            sizes.append([])
+            for child in generation:
+                sizes[-1].append(
+                    self.__shapes[child][0].sceneBoundingRect())
+                
+        # calculate total width and total height
+        width = 0
+        height = 0
+        widths = []
+        heights = []
+        for generation in sizes:
+            currentWidth = 0
+            currentHeight = 0
+            
+            for rect in generation:
+                if rect.height() > currentHeight:
+                    currentHeight = rect.height()
+                currentWidth += rect.width()
+                
+            # update totals
+            if currentWidth > width:
+                width = currentWidth
+            height += currentHeight
+            
+            # store generation info
+            widths.append(currentWidth)
+            heights.append(currentHeight)
+        
+        # add in some whitespace
+        width *= whiteSpaceFactor
+        height = height * whiteSpaceFactor - 20
+        verticalWhiteSpace = 40.0
+        
+        sceneRect = self.umlView.sceneRect()
+        width += 50.0
+        height += 50.0
+        swidth = sceneRect.width() if width < sceneRect.width() else width
+        sheight = sceneRect.height() if height < sceneRect.height() else height
+        self.umlView.setSceneSize(swidth, sheight)
+        
+        # distribute each generation across the width and the
+        # generations across height
+        y = 10.0
+        for currentWidth, currentHeight, generation in (
+            zip(reversed(widths), reversed(heights), reversed(generations))
+        ):
+            x = 10.0
+            # whiteSpace is the space between any two elements
+            whiteSpace = (
+                (width - currentWidth - 20) /
+                (len(generation) - 1.0 or 2.0)
+            )
+            for name in generation:
+                shape = self.__shapes[name][0]
+                shape.setPos(x, y)
+                rect = shape.sceneBoundingRect()
+                x = x + rect.width() + whiteSpace
+            y = y + currentHeight + verticalWhiteSpace
+    
+    def __createAssociations(self, routes):
         """
         Private method to generate the associations between the module shapes.
         
-        @param shapes list of shapes
+        @param routes list of associations
+        @type list of tuple of (str, str)
         """
         from .AssociationItem import AssociationItem, AssociationType
-        for module in list(shapes.keys()):
-            for rel in shapes[module][1]:
-                assoc = AssociationItem(
-                    shapes[module][0], shapes[rel][0],
-                    AssociationType.IMPORTS,
-                    colors=self.umlView.getDrawingColors())
-                self.scene.addItem(assoc)
+        for route in routes:
+            assoc = AssociationItem(
+                self.__shapes[route[0]][0],
+                self.__shapes[route[1]][0],
+                AssociationType.IMPORTS,
+                colors=self.umlView.getDrawingColors())
+            self.scene.addItem(assoc)
     
     def getPersistenceData(self):
         """
         Public method to get a string for data to be persisted.
         
-        @return persisted data string (string)
+        @return persisted data string
+        @rtype str
         """
         return "package={0}, show_external={1}".format(
             self.packagePath, self.showExternalImports)
@@ -267,9 +342,12 @@
         """
         Public method to parse persisted data.
         
-        @param version version of the data (string)
-        @param data persisted data to be parsed (string)
-        @return flag indicating success (boolean)
+        @param version version of the data
+        @type str
+        @param data persisted data to be parsed
+        @type str
+        @return flag indicating success
+        @rtype bool
         """
         parts = data.split(", ")
         if (
@@ -286,3 +364,60 @@
         self.initialize()
         
         return True
+    
+    def toDict(self):
+        """
+        Public method to collect data to be persisted.
+        
+        @return dictionary containing data to be persisted
+        @rtype dict
+        """
+        data = {
+            "project_name": self.project.getProjectName(),
+            "show_external": self.showExternalImports,
+        }
+        
+        data["package"] = (
+            Utilities.fromNativeSeparators(self.__relPackagePath)
+            if self.__relPackagePath else
+            Utilities.fromNativeSeparators(self.packagePath)
+        )
+        
+        return data
+    
+    def fromDict(self, version, data):
+        """
+        Public method to populate the class with data persisted by 'toDict()'.
+        
+        @param version version of the data
+        @type str
+        @param data dictionary containing the persisted data
+        @type dict
+        @return tuple containing a flag indicating success and an info
+            message in case the diagram belongs to a different project
+        @rtype tuple of (bool, str)
+        """
+        try:
+            self.showExternalImports = data["show_external"]
+            
+            packagePath = Utilities.toNativeSeparators(data["package"])
+            if os.path.isabs(packagePath):
+                self.packagePath = packagePath
+                self.__relPackagePath = ""
+            else:
+                # relative package paths indicate a project package
+                if data["project_name"] != self.project.getProjectName():
+                    msg = self.tr(
+                        "<p>The diagram belongs to project <b>{0}</b>."
+                        " Please open it and try again.</p>"
+                    ).format(data["project_name"])
+                    return False, msg
+                
+                self.__relPackagePath = packagePath
+                self.package = self.project.getAbsolutePath(packagePath)
+        except KeyError:
+            return False, ""
+        
+        self.initialize()
+        
+        return True, ""
--- a/eric6/Graphics/ModuleItem.py	Sat May 01 14:27:38 2021 +0200
+++ b/eric6/Graphics/ModuleItem.py	Thu Jun 03 11:39:23 2021 +0200
@@ -21,8 +21,10 @@
         """
         Constructor
         
-        @param name the module name (string)
-        @param classlist list of class names (list of strings)
+        @param name the module name
+        @type str
+        @param classlist list of class names
+        @type list of str
         """
         super().__init__(name)
         
@@ -32,7 +34,8 @@
         """
         Public method to add a class to the module model.
         
-        @param classname class name to be added (string)
+        @param classname class name to be added
+        @type str
         """
         self.classlist.append(classname)
     
@@ -40,7 +43,8 @@
         """
         Public method to retrieve the classes of the module.
         
-        @return list of class names (list of strings)
+        @return list of class names
+        @rtype list of str
         """
         return self.classlist[:]
 
@@ -73,7 +77,8 @@
         """
         UMLItem.__init__(self, model, x, y, rounded, colors, parent)
         
-        scene.addItem(self)
+        if scene:
+            scene.addItem(self)
         
         if self.model:
             self.__createTexts()
@@ -124,7 +129,8 @@
         """
         Public method to set the module model.
         
-        @param model module model containing the module data (ModuleModel)
+        @param model module model containing the module data
+        @type ModuleModel
         """
         self.scene().removeItem(self.header)
         self.header = None
@@ -139,9 +145,12 @@
         """
         Public method to paint the item in local coordinates.
         
-        @param painter reference to the painter object (QPainter)
-        @param option style options (QStyleOptionGraphicsItem)
-        @param widget optional reference to the widget painted on (QWidget)
+        @param painter reference to the painter object
+        @type QPainter
+        @param option style options
+        @type QStyleOptionGraphicsItem
+        @param widget optional reference to the widget painted on
+        @type QWidget
         """
         pen = self.pen()
         if (
@@ -175,7 +184,8 @@
         "attribute=value" with pairs separated by ", ". value must not
         contain ", " or newlines.
         
-        @return persistence data (string)
+        @return persistence data
+        @rtype str
         """
         entries = [
             "name={0}".format(self.model.getName()),
@@ -190,9 +200,12 @@
         """
         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)
+        @param version version of the data
+        @type str
+        @param data persisted data to be parsed
+        @type str
+        @return flag indicating success
+        @rtype bool
         """
         parts = data.split(", ")
         if len(parts) < 1:
@@ -215,3 +228,45 @@
         self.__calculateSize()
         
         return True
+    
+    def toDict(self):
+        """
+        Public method to collect data to be persisted.
+        
+        @return dictionary containing data to be persisted
+        @rtype dict
+        """
+        return {
+            "id": self.getId(),
+            "x": self.x(),
+            "y": self.y(),
+            "type": self.getItemType(),
+            "model_name": self.model.getName(),
+            "classes": self.model.getClasses(),
+        }
+    
+    @classmethod
+    def fromDict(cls, data, colors=None):
+        """
+        Class method to create a class item from persisted data.
+        
+        @param data dictionary containing the persisted data as generated
+            by toDict()
+        @type dict
+        @param colors tuple containing the foreground and background colors
+        @type tuple of (QColor, QColor)
+        @return created class item
+        @rtype ClassItem
+        """
+        try:
+            model = ModuleModel(data["model_name"],
+                                data["classes"])
+            itm = cls(model,
+                      x=0,
+                      y=0,
+                      colors=colors)
+            itm.setPos(data["x"], data["y"])
+            itm.setId(data["id"])
+            return itm
+        except KeyError:
+            return None
--- a/eric6/Graphics/PackageDiagramBuilder.py	Sat May 01 14:27:38 2021 +0200
+++ b/eric6/Graphics/PackageDiagramBuilder.py	Thu Jun 03 11:39:23 2021 +0200
@@ -4,7 +4,7 @@
 #
 
 """
-Module implementing a dialog showing a UML like class diagram of a package.
+Module implementing a dialog showing an UML like class diagram of a package.
 """
 
 import glob
@@ -29,18 +29,28 @@
         """
         Constructor
         
-        @param dialog reference to the UML dialog (UMLDialog)
-        @param view reference to the view object (UMLGraphicsView)
-        @param project reference to the project object (Project)
-        @param package name of a python package to be shown (string)
+        @param dialog reference to the UML dialog
+        @type UMLDialog
+        @param view reference to the view object
+        @type UMLGraphicsView
+        @param project reference to the project object
+        @type Project
+        @param package name of a python package to be shown
+        @type str
         @param noAttrs flag indicating, that no attributes should be shown
-            (boolean)
+        @type bool
         """
         super().__init__(dialog, view, project)
         self.setObjectName("PackageDiagram")
         
         self.package = os.path.abspath(package)
         self.noAttrs = noAttrs
+        
+        self.__relPackage = (
+            self.project.getRelativePath(self.package)
+            if self.project.isProjectSource(self.package) else
+            ""
+        )
     
     def initialize(self):
         """
@@ -59,8 +69,10 @@
         """
         Private method to get the named shape.
         
-        @param name name of the shape (string)
-        @return shape (QCanvasItem)
+        @param name name of the shape
+        @type str
+        @return shape
+        @rtype QCanvasItem
         """
         return self.allClasses.get(name)
     
@@ -69,7 +81,8 @@
         Private method to build a dictionary of modules contained in the
         package.
         
-        @return dictionary of modules contained in the package.
+        @return dictionary of modules contained in the package
+        @rtype dict
         """
         import Utilities.ModuleParser
         
@@ -121,6 +134,7 @@
         package.
         
         @return dictionary of sub-packages contained in this package
+        @rtype dict
         """
         import Utilities.ModuleParser
         
@@ -208,13 +222,15 @@
             return
         
         modules = self.__buildModulesDict()
-        if not modules:
+        subpackages = self.__buildSubpackagesDict()
+        
+        if not modules and not subpackages:
             ct = QGraphicsTextItem(None)
             self.scene.addItem(ct)
-            ct.setHtml(
-                self.tr(
-                    "The package <b>'{0}'</b> does not contain any modules.")
-                .format(self.package))
+            ct.setHtml(self.buildErrorMessage(
+                self.tr("The package <b>'{0}'</b> does not contain any modules"
+                        " or subpackages.").format(self.package)
+            ))
             return
             
         # step 1: build all classes found in the modules
@@ -225,13 +241,13 @@
             for cls in list(module.classes.keys()):
                 classesFound = True
                 self.__addLocalClass(cls, module.classes[cls], 0, 0)
-        if not classesFound:
+        if not classesFound and not subpackages:
             ct = QGraphicsTextItem(None)
             self.scene.addItem(ct)
-            ct.setHtml(
-                self.tr(
-                    "The package <b>'{0}'</b> does not contain any classes.")
-                .format(self.package))
+            ct.setHtml(self.buildErrorMessage(
+                self.tr("The package <b>'{0}'</b> does not contain any"
+                        " classes or subpackages.").format(self.package)
+            ))
             return
         
         # step 2: build the class hierarchies
@@ -243,7 +259,7 @@
             todo = [module.createHierarchy()]
             while todo:
                 hierarchy = todo[0]
-                for className in list(hierarchy.keys()):
+                for className in hierarchy:
                     cw = self.__getCurrentShape(className)
                     if not cw and className.find('.') >= 0:
                         cw = self.__getCurrentShape(className.split('.')[-1])
@@ -282,7 +298,6 @@
                 del todo[0]
         
         # step 3: build the subpackages
-        subpackages = self.__buildSubpackagesDict()
         for subpackage in sorted(subpackages.keys()):
             self.__addPackage(subpackage, subpackages[subpackage], 0, 0)
             nodes.append(subpackage)
@@ -298,9 +313,12 @@
         The algorithm is borrowed from Boa Constructor.
         
         @param nodes list of nodes to arrange
+        @type list of str
         @param routes list of routes
+        @type list of tuple of (str, str)
         @param whiteSpaceFactor factor to increase whitespace between
-            items (float)
+            items
+        @type float
         """
         from . import GraphicsUtilities
         generations = GraphicsUtilities.sort(nodes, routes)
@@ -335,7 +353,7 @@
             # store generation info
             widths.append(currentWidth)
             heights.append(currentHeight)
-            
+        
         # add in some whitespace
         width *= whiteSpaceFactor
         height = height * whiteSpaceFactor - 20
@@ -344,8 +362,8 @@
         sceneRect = self.umlView.sceneRect()
         width += 50.0
         height += 50.0
-        swidth = width < sceneRect.width() and sceneRect.width() or width
-        sheight = height < sceneRect.height() and sceneRect.height() or height
+        swidth = sceneRect.width() if width < sceneRect.width() else width
+        sheight = sceneRect.height() if height < sceneRect.height() else height
         self.umlView.setSceneSize(swidth, sheight)
         
         # distribute each generation across the width and the
@@ -371,19 +389,27 @@
         """
         Private method to add a class defined in the module.
         
-        @param className name of the class to be as a dictionary key (string)
-        @param _class class to be shown (ModuleParser.Class)
-        @param x x-coordinate (float)
-        @param y y-coordinate (float)
-        @param isRbModule flag indicating a Ruby module (boolean)
+        @param className name of the class to be as a dictionary key
+        @type str
+        @param _class class to be shown
+        @type ModuleParser.Class
+        @param x x-coordinate
+        @type float
+        @param y y-coordinate
+        @type float
+        @param isRbModule flag indicating a Ruby module
+        @type bool
         """
         from .ClassItem import ClassItem, ClassModel
-        meths = sorted(_class.methods.keys())
-        attrs = sorted(_class.attributes.keys())
         name = _class.name
         if isRbModule:
             name = "{0} (Module)".format(name)
-        cl = ClassModel(name, meths[:], attrs[:])
+        cl = ClassModel(
+            name,
+            sorted(_class.methods.keys())[:],
+            sorted(_class.attributes.keys())[:],
+            sorted(_class.globals.keys())[:]
+        )
         cw = ClassItem(cl, False, x, y, noAttrs=self.noAttrs, scene=self.scene,
                        colors=self.umlView.getDrawingColors())
         cw.setId(self.umlView.getItemId())
@@ -396,9 +422,12 @@
         If the canvas is too small to take the shape, it
         is enlarged.
         
-        @param _class class to be shown (string)
-        @param x x-coordinate (float)
-        @param y y-coordinate (float)
+        @param _class class to be shown
+        @type ModuleParser.Class
+        @param x x-coordinate
+        @type float
+        @param y y-coordinate
+        @type float
         """
         from .ClassItem import ClassItem, ClassModel
         cl = ClassModel(_class)
@@ -411,11 +440,14 @@
         """
         Private method to add a package to the diagram.
         
-        @param name package name to be shown (string)
+        @param name package name to be shown
+        @type str
         @param modules list of module names contained in the package
-            (list of strings)
-        @param x x-coordinate (float)
-        @param y y-coordinate (float)
+        @type list of str
+        @param x x-coordinate
+        @type float
+        @param y y-coordinate
+        @type float
         """
         from .PackageItem import PackageItem, PackageModel
         pm = PackageModel(name, modules)
@@ -429,6 +461,7 @@
         Private method to generate the associations between the class shapes.
         
         @param routes list of relationsships
+        @type list of tuple of (str, str)
         """
         from .AssociationItem import AssociationItem, AssociationType
         for route in routes:
@@ -445,7 +478,8 @@
         """
         Public method to get a string for data to be persisted.
         
-        @return persisted data string (string)
+        @return persisted data string
+        @rtype str
         """
         return "package={0}, no_attributes={1}".format(
             self.package, self.noAttrs)
@@ -454,9 +488,12 @@
         """
         Public method to parse persisted data.
         
-        @param version version of the data (string)
-        @param data persisted data to be parsed (string)
-        @return flag indicating success (boolean)
+        @param version version of the data
+        @type str
+        @param data persisted data to be parsed
+        @type str
+        @return flag indicating success
+        @rtype bool
         """
         parts = data.split(", ")
         if (
@@ -472,3 +509,60 @@
         self.initialize()
         
         return True
+    
+    def toDict(self):
+        """
+        Public method to collect data to be persisted.
+        
+        @return dictionary containing data to be persisted
+        @rtype dict
+        """
+        data = {
+            "project_name": self.project.getProjectName(),
+            "no_attributes": self.noAttrs,
+        }
+        
+        data["package"] = (
+            Utilities.fromNativeSeparators(self.__relPackage)
+            if self.__relPackage else
+            Utilities.fromNativeSeparators(self.package)
+        )
+        
+        return data
+    
+    def fromDict(self, version, data):
+        """
+        Public method to populate the class with data persisted by 'toDict()'.
+        
+        @param version version of the data
+        @type str
+        @param data dictionary containing the persisted data
+        @type dict
+        @return tuple containing a flag indicating success and an info
+            message in case the diagram belongs to a different project
+        @rtype tuple of (bool, str)
+        """
+        try:
+            self.noAttrs = data["no_attributes"]
+            
+            package = Utilities.toNativeSeparators(data["package"])
+            if os.path.isabs(package):
+                self.package = package
+                self.__relPackage = ""
+            else:
+                # relative package paths indicate a project package
+                if data["project_name"] != self.project.getProjectName():
+                    msg = self.tr(
+                        "<p>The diagram belongs to project <b>{0}</b>."
+                        " Please open it and try again.</p>"
+                    ).format(data["project_name"])
+                    return False, msg
+                
+                self.__relPackage = package
+                self.package = self.project.getAbsolutePath(package)
+        except KeyError:
+            return False, ""
+        
+        self.initialize()
+        
+        return True, ""
--- a/eric6/Graphics/PackageItem.py	Sat May 01 14:27:38 2021 +0200
+++ b/eric6/Graphics/PackageItem.py	Thu Jun 03 11:39:23 2021 +0200
@@ -23,8 +23,10 @@
         """
         Constructor
         
-        @param name package name (string)
-        @param moduleslist list of module names (list of strings)
+        @param name package name
+        @type str
+        @param moduleslist list of module names
+        @type list of str
         """
         super().__init__(name)
         
@@ -34,7 +36,8 @@
         """
         Public method to add a module to the package model.
         
-        @param modulename module name to be added (string)
+        @param modulename module name to be added
+        @type str
         """
         self.moduleslist.append(modulename)
     
@@ -42,7 +45,8 @@
         """
         Public method to retrieve the modules of the package.
         
-        @return list of module names (list of strings)
+        @return list of module names
+        @rtype list of str
         """
         return self.moduleslist[:]
 
@@ -79,7 +83,8 @@
         UMLItem.__init__(self, model, x, y, rounded, colors, parent)
         self.noModules = noModules
         
-        scene.addItem(self)
+        if scene:
+            scene.addItem(self)
         
         if self.model:
             self.__createTexts()
@@ -147,7 +152,8 @@
         """
         Public method to set the package model.
         
-        @param model package model containing the package data (PackageModel)
+        @param model package model containing the package data
+        @type PackageModel
         """
         self.scene().removeItem(self.header)
         self.header = None
@@ -162,9 +168,12 @@
         """
         Public method to paint the item in local coordinates.
         
-        @param painter reference to the painter object (QPainter)
-        @param option style options (QStyleOptionGraphicsItem)
-        @param widget optional reference to the widget painted on (QWidget)
+        @param painter reference to the painter object
+        @type QPainter
+        @param option style options
+        @type QStyleOptionGraphicsItem
+        @param widget optional reference to the widget painted on
+        @type QWidget
         """
         pen = self.pen()
         if (
@@ -201,7 +210,8 @@
         "attribute=value" with pairs separated by ", ". value must not
         contain ", " or newlines.
         
-        @return persistence data (string)
+        @return persistence data
+        @rtype str
         """
         entries = [
             "no_modules={0}".format(self.noModules),
@@ -217,9 +227,12 @@
         """
         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)
+        @param version version of the data
+        @type str
+        @param data persisted data to be parsed
+        @type str
+        @return flag indicating success
+        @rtype bool
         """
         parts = data.split(", ")
         if len(parts) < 2:
@@ -244,3 +257,47 @@
         self.__calculateSize()
         
         return True
+    
+    def toDict(self):
+        """
+        Public method to collect data to be persisted.
+        
+        @return dictionary containing data to be persisted
+        @rtype dict
+        """
+        return {
+            "id": self.getId(),
+            "x": self.x(),
+            "y": self.y(),
+            "type": self.getItemType(),
+            "model_name": self.model.getName(),
+            "no_nodules": self.noModules,
+            "modules": self.model.getModules(),
+        }
+    
+    @classmethod
+    def fromDict(cls, data, colors=None):
+        """
+        Class method to create a class item from persisted data.
+        
+        @param data dictionary containing the persisted data as generated
+            by toDict()
+        @type dict
+        @param colors tuple containing the foreground and background colors
+        @type tuple of (QColor, QColor)
+        @return created class item
+        @rtype ClassItem
+        """
+        try:
+            model = PackageModel(data["model_name"],
+                                 data["modules"])
+            itm = cls(model,
+                      x=0,
+                      y=0,
+                      noModules=data["no_nodules"],
+                      colors=colors)
+            itm.setPos(data["x"], data["y"])
+            itm.setId(data["id"])
+            return itm
+        except KeyError:
+            return None
--- a/eric6/Graphics/PixmapDiagram.py	Sat May 01 14:27:38 2021 +0200
+++ b/eric6/Graphics/PixmapDiagram.py	Thu Jun 03 11:39:23 2021 +0200
@@ -40,9 +40,12 @@
         """
         Constructor
         
-        @param pixmap filename of a graphics file to show (string)
-        @param parent parent widget of the view (QWidget)
-        @param name name of the view widget (string)
+        @param pixmap filename of a graphics file to show
+        @type str
+        @param parent parent widget of the view
+        @type QWidget
+        @param name name of the view widget
+        @type str
         """
         super().__init__(parent)
         if name:
@@ -122,7 +125,8 @@
         """
         Private slot to show the context menu of the listview.
         
-        @param coord the position of the mouse pointer (QPoint)
+        @param coord the position of the mouse pointer
+        @type QPoint
         """
         self.__menu.popup(self.mapToGlobal(coord))
         
@@ -146,8 +150,10 @@
         """
         Private method to show a file.
         
-        @param filename name of the file to be shown (string)
-        @return flag indicating success (boolean)
+        @param filename name of the file to be shown
+        @type str
+        @return flag indicating success
+        @rtype bool
         """
         image = QImage(filename)
         if image.isNull():
@@ -168,6 +174,7 @@
         Public method to retrieve a name for the diagram.
         
         @return name for the diagram
+        @rtype str
         """
         return self.pixmapfile
         
@@ -175,7 +182,8 @@
         """
         Public method to retrieve the status of the canvas.
         
-        @return flag indicating a successful pixmap loading (boolean)
+        @return flag indicating a successful pixmap loading
+        @rtype bool
         """
         return self.status
     
@@ -183,7 +191,8 @@
         """
         Protected method to handle wheel events.
         
-        @param evt reference to the wheel event (QWheelEvent)
+        @param evt reference to the wheel event
+        @type QWheelEvent
         """
         if evt.modifiers() & Qt.KeyboardModifier.ControlModifier:
             delta = evt.angleDelta().y()
@@ -200,8 +209,10 @@
         """
         Public method handling events.
         
-        @param evt reference to the event (QEvent)
-        @return flag indicating, if the event was handled (boolean)
+        @param evt reference to the event
+        @type QEvent
+        @return flag indicating, if the event was handled
+        @rtype bool
         """
         if evt.type() == QEvent.Type.Gesture:
             self.gestureEvent(evt)
@@ -213,7 +224,8 @@
         """
         Protected method handling gesture events.
         
-        @param evt reference to the gesture event (QGestureEvent
+        @param evt reference to the gesture event
+        @type QGestureEvent
         """
         pinch = evt.gesture(Qt.GestureType.PinchGesture)
         if pinch:
@@ -231,8 +243,10 @@
         """
         Private method to adjust a scrollbar by a certain factor.
         
-        @param scrollBar reference to the scrollbar object (QScrollBar)
-        @param factor factor to adjust by (float)
+        @param scrollBar reference to the scrollbar object
+        @type QScrollBar
+        @param factor factor to adjust by
+        @type float
         """
         scrollBar.setValue(int(factor * scrollBar.value() +
                            ((factor - 1) * scrollBar.pageStep() / 2)))
@@ -241,8 +255,10 @@
         """
         Private method determining the zoom level index given a zoom factor.
         
-        @param zoom zoom factor (integer)
-        @return index of zoom factor (integer)
+        @param zoom zoom factor
+        @type int
+        @return index of zoom factor
+        @rtype int
         """
         try:
             index = PixmapDiagram.ZoomLevels.index(zoom)
@@ -256,7 +272,8 @@
         """
         Private method to set the zoom value in percent.
         
-        @param value zoom value in percent (integer)
+        @param value zoom value in percent
+        @type int
         """
         oldValue = self.__zoom()
         if value != oldValue:
@@ -297,7 +314,8 @@
         """
         Private method to get the current zoom factor in percent.
         
-        @return current zoom factor in percent (integer)
+        @return current zoom factor in percent
+        @rtype int
         """
         return int(self.pixmapLabel.width() /
                    self.pixmapLabel.pixmap().width() * 100.0)
@@ -355,7 +373,8 @@
         """
         Private slot to the actual printing.
         
-        @param printer reference to the printer object (QPrinter)
+        @param printer reference to the printer object
+        @type QPrinter
         """
         painter = QPainter()
         painter.begin(printer)
@@ -365,12 +384,18 @@
         painter.setFont(font)
         fm = painter.fontMetrics()
         fontHeight = fm.lineSpacing()
-        marginX = printer.pageRect().x() - printer.paperRect().x()
+        marginX = (
+            printer.pageLayout().paintRectPixels(printer.resolution()).x() -
+            printer.pageLayout().fullRectPixels(printer.resolution()).x()
+        )
         marginX = (
             Preferences.getPrinter("LeftMargin") *
             int(printer.resolution() / 2.54) - marginX
         )
-        marginY = printer.pageRect().y() - printer.paperRect().y()
+        marginY = (
+            printer.pageLayout().paintRectPixels(printer.resolution()).y() -
+            printer.pageLayout().fullRectPixels(printer.resolution()).y()
+        )
         marginY = (
             Preferences.getPrinter("TopMargin") *
             int(printer.resolution() / 2.54) - marginY
--- a/eric6/Graphics/SvgDiagram.py	Sat May 01 14:27:38 2021 +0200
+++ b/eric6/Graphics/SvgDiagram.py	Thu Jun 03 11:39:23 2021 +0200
@@ -38,9 +38,12 @@
         """
         Constructor
         
-        @param svgFile filename of a SVG graphics file to show (string)
-        @param parent parent widget of the view (QWidget)
-        @param name name of the view widget (string)
+        @param svgFile filename of a SVG graphics file to show
+        @type str
+        @param parent parent widget of the view
+        @type QWidget
+        @param name name of the view widget
+        @type str
         """
         super().__init__(parent)
         if name:
@@ -121,7 +124,8 @@
         """
         Private slot to show the context menu of the listview.
         
-        @param coord the position of the mouse pointer (QPoint)
+        @param coord the position of the mouse pointer
+        @type QPoint
         """
         self.__menu.popup(self.mapToGlobal(coord))
         
@@ -146,6 +150,7 @@
         Public method to retrieve a name for the diagram.
         
         @return name for the diagram
+        @rtype str
         """
         return self.svgFile
     
@@ -153,7 +158,8 @@
         """
         Protected method to handle wheel events.
         
-        @param evt reference to the wheel event (QWheelEvent)
+        @param evt reference to the wheel event
+        @type QWheelEvent
         """
         if evt.modifiers() & Qt.KeyboardModifier.ControlModifier:
             delta = evt.angleDelta().y()
@@ -170,8 +176,10 @@
         """
         Public method handling events.
         
-        @param evt reference to the event (QEvent)
-        @return flag indicating, if the event was handled (boolean)
+        @param evt reference to the event
+        @type QEvent
+        @return flag indicating, if the event was handled
+        @rtype bool
         """
         if evt.type() == QEvent.Type.Gesture:
             self.gestureEvent(evt)
@@ -183,7 +191,8 @@
         """
         Protected method handling gesture events.
         
-        @param evt reference to the gesture event (QGestureEvent
+        @param evt reference to the gesture event
+        @type QGestureEvent
         """
         pinch = evt.gesture(Qt.GestureType.PinchGesture)
         if pinch:
@@ -201,8 +210,10 @@
         """
         Private method to adjust a scrollbar by a certain factor.
         
-        @param scrollBar reference to the scrollbar object (QScrollBar)
-        @param factor factor to adjust by (float)
+        @param scrollBar reference to the scrollbar object
+        @type QScrollBar
+        @param factor factor to adjust by
+        @type float
         """
         scrollBar.setValue(
             int(factor * scrollBar.value() +
@@ -212,8 +223,10 @@
         """
         Private method determining the zoom level index given a zoom factor.
         
-        @param zoom zoom factor (integer)
-        @return index of zoom factor (integer)
+        @param zoom zoom factor
+        @type int
+        @return index of zoom factor
+        @rtype int
         """
         try:
             index = SvgDiagram.ZoomLevels.index(zoom)
@@ -227,7 +240,8 @@
         """
         Private method to set the zoom value in percent.
         
-        @param value zoom value in percent (integer)
+        @param value zoom value in percent
+        @type int
         """
         oldValue = self.__zoom()
         if value != oldValue:
@@ -265,7 +279,8 @@
         """
         Private method to get the current zoom factor in percent.
         
-        @return current zoom factor in percent (integer)
+        @return current zoom factor in percent
+        @rtype int
         """
         return int(self.svgWidget.width() /
                    self.svgWidget.sizeHint().width() * 100.0)
@@ -327,7 +342,8 @@
         """
         Private slot to the actual printing.
         
-        @param printer reference to the printer object (QPrinter)
+        @param printer reference to the printer object
+        @type QPrinter
         """
         painter = QPainter()
         painter.begin(printer)
@@ -337,12 +353,18 @@
         painter.setFont(font)
         fm = painter.fontMetrics()
         fontHeight = fm.lineSpacing()
-        marginX = printer.pageRect().x() - printer.paperRect().x()
+        marginX = (
+            printer.pageLayout().paintRectPixels(printer.resolution()).x() -
+            printer.pageLayout().fullRectPixels(printer.resolution()).x()
+        )
         marginX = (
             Preferences.getPrinter("LeftMargin") *
             int(printer.resolution() / 2.54) - marginX
         )
-        marginY = printer.pageRect().y() - printer.paperRect().y()
+        marginY = (
+            printer.pageLayout().paintRectPixels(printer.resolution()).y() -
+            printer.pageLayout().fullRectPixels(printer.resolution()).y()
+        )
         marginY = (
             Preferences.getPrinter("TopMargin") *
             int(printer.resolution() / 2.54) - marginY
--- a/eric6/Graphics/UMLClassDiagramBuilder.py	Sat May 01 14:27:38 2021 +0200
+++ b/eric6/Graphics/UMLClassDiagramBuilder.py	Thu Jun 03 11:39:23 2021 +0200
@@ -8,6 +8,7 @@
 """
 
 from itertools import zip_longest
+import os
 
 from PyQt5.QtWidgets import QGraphicsTextItem
 
@@ -25,18 +26,28 @@
         """
         Constructor
         
-        @param dialog reference to the UML dialog (UMLDialog)
-        @param view reference to the view object (UMLGraphicsView)
-        @param project reference to the project object (Project)
-        @param file file name of a python module to be shown (string)
+        @param dialog reference to the UML dialog
+        @type UMLDialog
+        @param view reference to the view object
+        @type UMLGraphicsView
+        @param project reference to the project object
+        @type Project
+        @param file file name of a python module to be shown
+        @type str
         @param noAttrs flag indicating, that no attributes should be shown
-            (boolean)
+        @type bool
         """
         super().__init__(dialog, view, project)
         self.setObjectName("UMLClassDiagramBuilder")
         
         self.file = file
         self.noAttrs = noAttrs
+        
+        self.__relFile = (
+            self.project.getRelativePath(self.file)
+            if self.project.isProjectSource(self.file) else
+            ""
+        )
     
     def initialize(self):
         """
@@ -55,8 +66,10 @@
         """
         Private method to get the named shape.
         
-        @param name name of the shape (string)
-        @return shape (QGraphicsItem)
+        @param name name of the shape
+        @type str
+        @return shape
+        @rtype QGraphicsItem
         """
         return self.allClasses.get(name)
         
@@ -80,9 +93,10 @@
                 self.file, extensions=extensions, caching=False)
         except ImportError:
             ct = QGraphicsTextItem(None)
-            ct.setHtml(
<