Plugin Repository Dialog eric7

Thu, 16 Nov 2023 15:56:12 +0100

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Thu, 16 Nov 2023 15:56:12 +0100
branch
eric7
changeset 10314
1f7d52f024b1
parent 10313
8f69edb4ad73
child 10315
4102a69604eb

Plugin Repository Dialog
- Introduced categories to improve the presentation of the list of available plugins.

docs/changelog.md file | annotate | diff | comparison | revisions
src/eric7/APIs/Python3/eric7.api file | annotate | diff | comparison | revisions
src/eric7/APIs/Python3/eric7.bas file | annotate | diff | comparison | revisions
src/eric7/Documentation/Help/source.qch file | annotate | diff | comparison | revisions
src/eric7/Documentation/Help/source.qhp file | annotate | diff | comparison | revisions
src/eric7/Documentation/Source/eric7.EricXML.PluginRepositoryReader.html file | annotate | diff | comparison | revisions
src/eric7/Documentation/Source/eric7.PluginManager.PluginManager.html file | annotate | diff | comparison | revisions
src/eric7/Documentation/Source/eric7.PluginManager.PluginRepositoryDialog.html file | annotate | diff | comparison | revisions
src/eric7/EricXML/PluginRepositoryReader.py file | annotate | diff | comparison | revisions
src/eric7/PluginManager/PluginManager.py file | annotate | diff | comparison | revisions
src/eric7/PluginManager/PluginRepositoryDialog.py file | annotate | diff | comparison | revisions
src/eric7/PluginManager/PluginRepositoryDialog.ui file | annotate | diff | comparison | revisions
--- a/docs/changelog.md	Thu Nov 16 13:58:04 2023 +0100
+++ b/docs/changelog.md	Thu Nov 16 15:56:12 2023 +0100
@@ -19,6 +19,9 @@
 - Icons
     - Added a configuration option to override the style dependent icon size
       of the tool bars.
+- Plugin Repository Dialog
+    - Introduced categories to improve the presentation of the list of available
+      plugins.
 - Syntax Checker
     - Added code to show some per file and overall statistics of the check.
 
--- a/src/eric7/APIs/Python3/eric7.api	Thu Nov 16 13:58:04 2023 +0100
+++ b/src/eric7/APIs/Python3/eric7.api	Thu Nov 16 15:56:12 2023 +0100
@@ -3908,7 +3908,7 @@
 eric7.PluginManager.PluginManager.PluginManager.activatePlugin?4(name, onDemand=False)
 eric7.PluginManager.PluginManager.PluginManager.activatePlugins?4()
 eric7.PluginManager.PluginManager.PluginManager.allPlugginsActivated?7
-eric7.PluginManager.PluginManager.PluginManager.checkPluginEntry?4(name, short, description, url, author, version, filename, status, )
+eric7.PluginManager.PluginManager.PluginManager.checkPluginEntry?4(name, short, description, url, author, version, filename, status, category, )
 eric7.PluginManager.PluginManager.PluginManager.checkPluginUpdatesAvailable?4()
 eric7.PluginManager.PluginManager.PluginManager.clearPluginsPrivateData?4(type_)
 eric7.PluginManager.PluginManager.PluginManager.deactivatePlugin?4(name, onDemand=False)
@@ -3953,13 +3953,8 @@
 eric7.PluginManager.PluginRepositoryDialog.PluginRepositoryWidget.AuthorRole?7
 eric7.PluginManager.PluginRepositoryDialog.PluginRepositoryWidget.DescrRole?7
 eric7.PluginManager.PluginRepositoryDialog.PluginRepositoryWidget.FilenameRole?7
-eric7.PluginManager.PluginRepositoryDialog.PluginRepositoryWidget.PluginStatusError?7
-eric7.PluginManager.PluginRepositoryDialog.PluginRepositoryWidget.PluginStatusLocalUpdate?7
-eric7.PluginManager.PluginRepositoryDialog.PluginRepositoryWidget.PluginStatusNew?7
-eric7.PluginManager.PluginRepositoryDialog.PluginRepositoryWidget.PluginStatusRemoteUpdate?7
-eric7.PluginManager.PluginRepositoryDialog.PluginRepositoryWidget.PluginStatusUpToDate?7
 eric7.PluginManager.PluginRepositoryDialog.PluginRepositoryWidget.UrlRole?7
-eric7.PluginManager.PluginRepositoryDialog.PluginRepositoryWidget.addEntry?4(name, short, description, url, author, version, filename, status)
+eric7.PluginManager.PluginRepositoryDialog.PluginRepositoryWidget.addEntry?4(name, short, description, url, author, version, filename, status, category, )
 eric7.PluginManager.PluginRepositoryDialog.PluginRepositoryWidget.closeAndInstall?7
 eric7.PluginManager.PluginRepositoryDialog.PluginRepositoryWidget.getDownloadedPlugins?4()
 eric7.PluginManager.PluginRepositoryDialog.PluginRepositoryWidget.on_buttonBox_clicked?4(button)
@@ -3970,7 +3965,12 @@
 eric7.PluginManager.PluginRepositoryDialog.PluginRepositoryWidget.reloadList?4()
 eric7.PluginManager.PluginRepositoryDialog.PluginRepositoryWidget?1(pluginManager, integrated=False, parent=None)
 eric7.PluginManager.PluginRepositoryDialog.PluginRepositoryWindow?1(parent=None)
-eric7.PluginManager.PluginRepositoryDialog.registerPlugin?4(name, short, description, url, author, version, filename, status)
+eric7.PluginManager.PluginRepositoryDialog.PluginStatus.Error?7
+eric7.PluginManager.PluginRepositoryDialog.PluginStatus.LocalUpdate?7
+eric7.PluginManager.PluginRepositoryDialog.PluginStatus.New?7
+eric7.PluginManager.PluginRepositoryDialog.PluginStatus.RemoteUpdate?7
+eric7.PluginManager.PluginRepositoryDialog.PluginStatus.UpToDate?7
+eric7.PluginManager.PluginRepositoryDialog.registerPlugin?4(name, short, description, url, author, version, filename, status, category, )
 eric7.PluginManager.PluginUninstallDialog.PluginUninstallDialog?1(pluginManager, parent=None)
 eric7.PluginManager.PluginUninstallDialog.PluginUninstallWidget.accepted?7
 eric7.PluginManager.PluginUninstallDialog.PluginUninstallWidget.on_buttonBox_accepted?4()
--- a/src/eric7/APIs/Python3/eric7.bas	Thu Nov 16 13:58:04 2023 +0100
+++ b/src/eric7/APIs/Python3/eric7.bas	Thu Nov 16 15:56:12 2023 +0100
@@ -790,6 +790,7 @@
 PluginRepositoryReader XMLStreamReaderBase
 PluginRepositoryWidget QWidget Ui_PluginRepositoryDialog
 PluginRepositoryWindow EricMainWindow
+PluginStatus enum.Enum
 PluginUninstallDialog QDialog
 PluginUninstallWidget QWidget Ui_PluginUninstallDialog
 PluginUninstallWindow EricMainWindow
Binary file src/eric7/Documentation/Help/source.qch has changed
--- a/src/eric7/Documentation/Help/source.qhp	Thu Nov 16 13:58:04 2023 +0100
+++ b/src/eric7/Documentation/Help/source.qhp	Thu Nov 16 15:56:12 2023 +0100
@@ -12659,11 +12659,11 @@
       <keyword name="PluginRepositoryWidget.__downloadPlugins" id="PluginRepositoryWidget.__downloadPlugins" ref="eric7.PluginManager.PluginRepositoryDialog.html#PluginRepositoryWidget.__downloadPlugins" />
       <keyword name="PluginRepositoryWidget.__downloadPluginsDone" id="PluginRepositoryWidget.__downloadPluginsDone" ref="eric7.PluginManager.PluginRepositoryDialog.html#PluginRepositoryWidget.__downloadPluginsDone" />
       <keyword name="PluginRepositoryWidget.__downloadProgress" id="PluginRepositoryWidget.__downloadProgress" ref="eric7.PluginManager.PluginRepositoryDialog.html#PluginRepositoryWidget.__downloadProgress" />
-      <keyword name="PluginRepositoryWidget.__downloadRepositoryFileDone" id="PluginRepositoryWidget.__downloadRepositoryFileDone" ref="eric7.PluginManager.PluginRepositoryDialog.html#PluginRepositoryWidget.__downloadRepositoryFileDone" />
       <keyword name="PluginRepositoryWidget.__formatDescription" id="PluginRepositoryWidget.__formatDescription" ref="eric7.PluginManager.PluginRepositoryDialog.html#PluginRepositoryWidget.__formatDescription" />
       <keyword name="PluginRepositoryWidget.__hasHiddenPlugins" id="PluginRepositoryWidget.__hasHiddenPlugins" ref="eric7.PluginManager.PluginRepositoryDialog.html#PluginRepositoryWidget.__hasHiddenPlugins" />
       <keyword name="PluginRepositoryWidget.__hidePlugin" id="PluginRepositoryWidget.__hidePlugin" ref="eric7.PluginManager.PluginRepositoryDialog.html#PluginRepositoryWidget.__hidePlugin" />
       <keyword name="PluginRepositoryWidget.__hideSelectedPlugins" id="PluginRepositoryWidget.__hideSelectedPlugins" ref="eric7.PluginManager.PluginRepositoryDialog.html#PluginRepositoryWidget.__hideSelectedPlugins" />
+      <keyword name="PluginRepositoryWidget.__initHeaderItemsCache" id="PluginRepositoryWidget.__initHeaderItemsCache" ref="eric7.PluginManager.PluginRepositoryDialog.html#PluginRepositoryWidget.__initHeaderItemsCache" />
       <keyword name="PluginRepositoryWidget.__populateList" id="PluginRepositoryWidget.__populateList" ref="eric7.PluginManager.PluginRepositoryDialog.html#PluginRepositoryWidget.__populateList" />
       <keyword name="PluginRepositoryWidget.__reachabilityChanged" id="PluginRepositoryWidget.__reachabilityChanged" ref="eric7.PluginManager.PluginRepositoryDialog.html#PluginRepositoryWidget.__reachabilityChanged" />
       <keyword name="PluginRepositoryWidget.__resortRepositoryList" id="PluginRepositoryWidget.__resortRepositoryList" ref="eric7.PluginManager.PluginRepositoryDialog.html#PluginRepositoryWidget.__resortRepositoryList" />
@@ -12684,6 +12684,7 @@
       <keyword name="PluginRepositoryWindow" id="PluginRepositoryWindow" ref="eric7.PluginManager.PluginRepositoryDialog.html#PluginRepositoryWindow" />
       <keyword name="PluginRepositoryWindow (Constructor)" id="PluginRepositoryWindow (Constructor)" ref="eric7.PluginManager.PluginRepositoryDialog.html#PluginRepositoryWindow.__init__" />
       <keyword name="PluginRepositoryWindow.__startPluginInstall" id="PluginRepositoryWindow.__startPluginInstall" ref="eric7.PluginManager.PluginRepositoryDialog.html#PluginRepositoryWindow.__startPluginInstall" />
+      <keyword name="PluginStatus" id="PluginStatus" ref="eric7.PluginManager.PluginRepositoryDialog.html#PluginStatus" />
       <keyword name="PluginSyntaxChecker (Module)" id="PluginSyntaxChecker (Module)" ref="eric7.Plugins.PluginSyntaxChecker.html" />
       <keyword name="PluginTranslator (Module)" id="PluginTranslator (Module)" ref="eric7.Plugins.PluginTranslator.html" />
       <keyword name="PluginUninstallDialog" id="PluginUninstallDialog" ref="eric7.PluginManager.PluginUninstallDialog.html#PluginUninstallDialog" />
--- a/src/eric7/Documentation/Source/eric7.EricXML.PluginRepositoryReader.html	Thu Nov 16 13:58:04 2023 +0100
+++ b/src/eric7/Documentation/Source/eric7.EricXML.PluginRepositoryReader.html	Thu Nov 16 15:56:12 2023 +0100
@@ -82,14 +82,14 @@
 </p>
 <dl>
 
-<dt><i>device</i></dt>
+<dt><i>device</i> (QIODevice)</dt>
 <dd>
-reference to the I/O device to read from (QIODevice)
+reference to the I/O device to read from
 </dd>
-<dt><i>entryCallback</i></dt>
+<dt><i>entryCallback</i> (function)</dt>
 <dd>
 reference to a function to be called once the
-            data for a plug-in has been read (function)
+            data for a plug-in has been read
 </dd>
 </dl>
 <a NAME="PluginRepositoryReader.__readPlugin" ID="PluginRepositoryReader.__readPlugin"></a>
--- a/src/eric7/Documentation/Source/eric7.PluginManager.PluginManager.html	Thu Nov 16 13:58:04 2023 +0100
+++ b/src/eric7/Documentation/Source/eric7.PluginManager.PluginManager.html	Thu Nov 16 15:56:12 2023 +0100
@@ -118,7 +118,7 @@
 </tr>
 <tr>
 <td><a href="#PluginManager.__insertPluginsPaths">__insertPluginsPaths</a></td>
-<td>Private method to insert the valid plugin paths intos the search path.</td>
+<td>Private method to insert the valid plugin paths into the search path.</td>
 </tr>
 <tr>
 <td><a href="#PluginManager.__loadPlugins">__loadPlugins</a></td>
@@ -210,7 +210,7 @@
 </tr>
 <tr>
 <td><a href="#PluginManager.getPluginObject">getPluginObject</a></td>
-<td>Public method to activate an ondemand plugin given by type and typename.</td>
+<td>Public method to activate an on-demand plugin given by type and type name.</td>
 </tr>
 <tr>
 <td><a href="#PluginManager.getPluginPreviewPixmap">getPluginPreviewPixmap</a></td>
@@ -337,7 +337,7 @@
 </p>
 <dl>
 
-<dt><i>module</i></dt>
+<dt><i>module</i> (Module)</dt>
 <dd>
 reference to the module to be activated
 </dd>
@@ -346,7 +346,13 @@
 <dt>Return:</dt>
 <dd>
 flag indicating, if the module satisfies all requirements
-            for being activated (boolean)
+            for being activated
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+bool
 </dd>
 </dl>
 <dl>
@@ -371,7 +377,7 @@
 </p>
 <dl>
 
-<dt><i>module</i></dt>
+<dt><i>module</i> (Module)</dt>
 <dd>
 reference to the module to be deactivated
 </dd>
@@ -380,7 +386,13 @@
 <dt>Return:</dt>
 <dd>
 flag indicating, if the module satisfies all requirements
-            for being deactivated (boolean)
+            for being deactivated
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+bool
 </dd>
 </dl>
 <a NAME="PluginManager.__checkPluginsDownloadDirectory" ID="PluginManager.__checkPluginsDownloadDirectory"></a>
@@ -414,7 +426,7 @@
 </p>
 <dl>
 
-<dt><i>module</i></dt>
+<dt><i>module</i> (Module)</dt>
 <dd>
 module to extract short info from
 </dd>
@@ -422,7 +434,7 @@
 <dl>
 <dt>Return:</dt>
 <dd>
-dictionay containing plug-in data
+dictionary containing plug-in data
 </dd>
 </dl>
 <dl>
@@ -437,7 +449,7 @@
 <b>__insertPluginsPaths</b>(<i></i>)
 
 <p>
-        Private method to insert the valid plugin paths intos the search path.
+        Private method to insert the valid plugin paths into the search path.
 </p>
 <a NAME="PluginManager.__loadPlugins" ID="PluginManager.__loadPlugins"></a>
 <h4>PluginManager.__loadPlugins</h4>
@@ -460,7 +472,13 @@
 <dt>Return:</dt>
 <dd>
 tuple of a flag indicating existence of any of the plugin
-            directories (boolean) and a message (string)
+            directories and a message
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+tuple of (bool, str)
 </dd>
 </dl>
 <a NAME="PluginManager.__pluginModulesExist" ID="PluginManager.__pluginModulesExist"></a>
@@ -473,7 +491,13 @@
 <dl>
 <dt>Return:</dt>
 <dd>
-flag indicating the availability of plugins (boolean)
+flag indicating the availability of plugins
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+bool
 </dd>
 </dl>
 <a NAME="PluginManager.__sslErrors" ID="PluginManager.__sslErrors"></a>
@@ -485,13 +509,13 @@
 </p>
 <dl>
 
-<dt><i>reply</i></dt>
+<dt><i>reply</i> (QNetworkReply)</dt>
 <dd>
-reference to the reply object (QNetworkReply)
+reference to the reply object
 </dd>
-<dt><i>errors</i></dt>
+<dt><i>errors</i> (list of QSslError)</dt>
 <dd>
-list of SSL errors (list of QSslError)
+list of SSL errors
 </dd>
 </dl>
 <a NAME="PluginManager.activatePlugin" ID="PluginManager.activatePlugin"></a>
@@ -543,44 +567,48 @@
 </p>
 <a NAME="PluginManager.checkPluginEntry" ID="PluginManager.checkPluginEntry"></a>
 <h4>PluginManager.checkPluginEntry</h4>
-<b>checkPluginEntry</b>(<i>name, short, description, url, author, version, filename, status, </i>)
+<b>checkPluginEntry</b>(<i>name, short, description, url, author, version, filename, status, category, </i>)
 
 <p>
         Public method to check a plug-in's data for an update.
 </p>
 <dl>
 
-<dt><i>name</i></dt>
+<dt><i>name</i> (str)</dt>
 <dd>
-data for the name field (string)
+data for the name field
 </dd>
-<dt><i>short</i></dt>
+<dt><i>short</i> (str)</dt>
 <dd>
-data for the short field (string)
+data for the short field
 </dd>
-<dt><i>description</i></dt>
+<dt><i>description</i> (list of str)</dt>
 <dd>
-data for the description field (list of strings)
+data for the description field
 </dd>
-<dt><i>url</i></dt>
+<dt><i>url</i> (str)</dt>
 <dd>
-data for the url field (string)
+data for the url field
 </dd>
-<dt><i>author</i></dt>
+<dt><i>author</i> (str)</dt>
 <dd>
-data for the author field (string)
+data for the author field
 </dd>
-<dt><i>version</i></dt>
+<dt><i>version</i> (str)</dt>
 <dd>
-data for the version field (string)
+data for the version field
 </dd>
-<dt><i>filename</i></dt>
+<dt><i>filename</i> (str)</dt>
 <dd>
-data for the filename field (string)
+data for the filename field
 </dd>
-<dt><i>status</i></dt>
+<dt><i>status</i> (str)</dt>
 <dd>
-status of the plugin (string [stable, unstable, unknown])
+status of the plugin (one of stable, unstable, unknown)
+</dd>
+<dt><i>category</i> (str)</dt>
+<dd>
+category designation of the plugin
 </dd>
 </dl>
 <a NAME="PluginManager.checkPluginUpdatesAvailable" ID="PluginManager.checkPluginUpdatesAvailable"></a>
@@ -604,9 +632,9 @@
 </p>
 <dl>
 
-<dt><i>type_</i></dt>
+<dt><i>type_</i> (str)</dt>
 <dd>
-type of the plugin to clear private data for (string)
+type of the plugin to clear private data for
 </dd>
 </dl>
 <a NAME="PluginManager.deactivatePlugin" ID="PluginManager.deactivatePlugin"></a>
@@ -618,14 +646,14 @@
 </p>
 <dl>
 
-<dt><i>name</i></dt>
+<dt><i>name</i> (str)</dt>
 <dd>
 name of the module to be deactivated
 </dd>
-<dt><i>onDemand</i></dt>
+<dt><i>onDemand</i> (bool)</dt>
 <dd>
 flag indicating deactivation of an
-            on demand plugin (boolean)
+            on demand plugin
 </dd>
 </dl>
 <a NAME="PluginManager.deactivateVcsPlugins" ID="PluginManager.deactivateVcsPlugins"></a>
@@ -673,15 +701,21 @@
 </p>
 <dl>
 
-<dt><i>language</i></dt>
+<dt><i>language</i> (str)</dt>
 <dd>
-language of the requested API files (string)
+language of the requested API files
 </dd>
 </dl>
 <dl>
 <dt>Return:</dt>
 <dd>
-list of API filenames (list of string)
+list of API filenames
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+list of str
 </dd>
 </dl>
 <a NAME="PluginManager.getPluginConfigData" ID="PluginManager.getPluginConfigData"></a>
@@ -724,6 +758,12 @@
 plug-in configuration data
 </dd>
 </dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+dict
+</dd>
+</dl>
 <a NAME="PluginManager.getPluginDetails" ID="PluginManager.getPluginDetails"></a>
 <h4>PluginManager.getPluginDetails</h4>
 <b>getPluginDetails</b>(<i>name</i>)
@@ -733,9 +773,9 @@
 </p>
 <dl>
 
-<dt><i>name</i></dt>
+<dt><i>name</i> (str)</dt>
 <dd>
-name of the module to get detailed infos about (string)
+name of the module to get detailed infos about
 </dd>
 </dl>
 <dl>
@@ -744,6 +784,12 @@
 details of the plugin as a dictionary
 </dd>
 </dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+dict
+</dd>
+</dl>
 <a NAME="PluginManager.getPluginDir" ID="PluginManager.getPluginDir"></a>
 <h4>PluginManager.getPluginDir</h4>
 <b>getPluginDir</b>(<i>key</i>)
@@ -753,15 +799,21 @@
 </p>
 <dl>
 
-<dt><i>key</i></dt>
+<dt><i>key</i> (str)</dt>
 <dd>
-key of the plug-in directory (string)
+key of the plug-in directory
 </dd>
 </dl>
 <dl>
 <dt>Return:</dt>
 <dd>
-path of the requested plugin directory (string)
+path of the requested plugin directory
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+str
 </dd>
 </dl>
 <a NAME="PluginManager.getPluginDisplayStrings" ID="PluginManager.getPluginDisplayStrings"></a>
@@ -774,16 +826,21 @@
 </p>
 <dl>
 
-<dt><i>type_</i></dt>
+<dt><i>type_</i> (str)</dt>
 <dd>
-type of the plugins (string)
+type of the plugins
 </dd>
 </dl>
 <dl>
 <dt>Return:</dt>
 <dd>
 dictionary with name as key and display string as value
-            (dictionary of string)
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+dict
 </dd>
 </dl>
 <a NAME="PluginManager.getPluginExeDisplayData" ID="PluginManager.getPluginExeDisplayData"></a>
@@ -827,6 +884,12 @@
             </ul>
 </dd>
 </dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+list of dict
+</dd>
+</dl>
 <a NAME="PluginManager.getPluginInfos" ID="PluginManager.getPluginInfos"></a>
 <h4>PluginManager.getPluginInfos</h4>
 <b>getPluginInfos</b>(<i></i>)
@@ -858,15 +921,21 @@
 </p>
 <dl>
 
-<dt><i>pluginPath</i></dt>
+<dt><i>pluginPath</i> (str)</dt>
 <dd>
-name of the path to search (string)
+name of the path to search
 </dd>
 </dl>
 <dl>
 <dt>Return:</dt>
 <dd>
-list of plugin module names (list of string)
+list of plugin module names
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+list of str
 </dd>
 </dl>
 <a NAME="PluginManager.getPluginObject" ID="PluginManager.getPluginObject"></a>
@@ -874,8 +943,8 @@
 <b>getPluginObject</b>(<i>type_, typename, maybeActive=False</i>)
 
 <p>
-        Public method to activate an ondemand plugin given by type and
-        typename.
+        Public method to activate an on-demand plugin given by type and
+        type name.
 </p>
 <dl>
 
@@ -914,19 +983,25 @@
 </p>
 <dl>
 
-<dt><i>type_</i></dt>
+<dt><i>type_</i> (str)</dt>
 <dd>
-type of the plugin (string)
+type of the plugin
 </dd>
-<dt><i>name</i></dt>
+<dt><i>name</i> (str)</dt>
 <dd>
-name of the plugin type (string)
+name of the plugin type
 </dd>
 </dl>
 <dl>
 <dt>Return:</dt>
 <dd>
-preview pixmap (QPixmap)
+preview pixmap
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+QPixmap
 </dd>
 </dl>
 <a NAME="PluginManager.getPluginQtHelpFiles" ID="PluginManager.getPluginQtHelpFiles"></a>
@@ -966,8 +1041,14 @@
 <dt>Return:</dt>
 <dd>
 dictionary with indicator as key and a list of tuples as
-            values. Each tuple contains the vcs name (string) and vcs display
-            string (string).
+            values. Each tuple contains the vcs name (str) and vcs display
+            string (str).
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+dict
 </dd>
 </dl>
 <a NAME="PluginManager.initOnDemandPlugin" ID="PluginManager.initOnDemandPlugin"></a>
@@ -982,9 +1063,9 @@
 </p>
 <dl>
 
-<dt><i>name</i></dt>
+<dt><i>name</i> (str)</dt>
 <dd>
-name of the plug-in (string)
+name of the plug-in
 </dd>
 </dl>
 <dl>
@@ -1014,10 +1095,9 @@
 </p>
 <dl>
 
-<dt><i>toolbarManager</i></dt>
+<dt><i>toolbarManager</i> (EricToolBarManager)</dt>
 <dd>
 reference to the toolbar manager object
-            (EricToolBarManager)
 </dd>
 </dl>
 <a NAME="PluginManager.isPluginActive" ID="PluginManager.isPluginActive"></a>
@@ -1029,15 +1109,21 @@
 </p>
 <dl>
 
-<dt><i>pluginName</i></dt>
+<dt><i>pluginName</i> (str)</dt>
 <dd>
-name of the plugin to check for (string)
+name of the plugin to check for
 </dd>
 </dl>
 <dl>
 <dt>Return:</dt>
 <dd>
-flag indicating, if the plugin is active (boolean)
+flag indicating, if the plugin is active
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+bool
 </dd>
 </dl>
 <a NAME="PluginManager.isPluginLoaded" ID="PluginManager.isPluginLoaded"></a>
@@ -1049,15 +1135,21 @@
 </p>
 <dl>
 
-<dt><i>pluginName</i></dt>
+<dt><i>pluginName</i> (str)</dt>
 <dd>
-name of the plugin to check for (string)
+name of the plugin to check for
 </dd>
 </dl>
 <dl>
 <dt>Return:</dt>
 <dd>
-flag indicating, if the plugin is loaded (boolean)
+flag indicating, if the plugin is loaded
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+bool
 </dd>
 </dl>
 <a NAME="PluginManager.isValidPluginName" ID="PluginManager.isValidPluginName"></a>
@@ -1072,15 +1164,21 @@
 </p>
 <dl>
 
-<dt><i>pluginName</i></dt>
+<dt><i>pluginName</i> (str)</dt>
 <dd>
-name of the file to be checked (string)
+name of the file to be checked
 </dd>
 </dl>
 <dl>
 <dt>Return:</dt>
 <dd>
-flag indicating a valid plugin name (boolean)
+flag indicating a valid plugin name
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+bool
 </dd>
 </dl>
 <a NAME="PluginManager.loadDocumentationSetPlugins" ID="PluginManager.loadDocumentationSetPlugins"></a>
@@ -1170,24 +1268,29 @@
 </p>
 <dl>
 
-<dt><i>pluginName</i></dt>
+<dt><i>pluginName</i> (str)</dt>
 <dd>
-name of the plugin module (string)
+name of the plugin module
 </dd>
-<dt><i>package</i></dt>
+<dt><i>package</i> (str)</dt>
 <dd>
-name of the plugin package (string)
+name of the plugin package
 </dd>
-<dt><i>internalPackages</i></dt>
+<dt><i>internalPackages</i> (list of str)</dt>
 <dd>
-list of intenal packages (list of string)
+list of intenal packages
 </dd>
 </dl>
 <dl>
 <dt>Return:</dt>
 <dd>
 flag indicating the plugin module was found in sys.modules
-            (boolean)
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+bool
 </dd>
 </dl>
 <a NAME="PluginManager.unloadPlugin" ID="PluginManager.unloadPlugin"></a>
@@ -1199,15 +1302,21 @@
 </p>
 <dl>
 
-<dt><i>name</i></dt>
+<dt><i>name</i> (str)</dt>
 <dd>
-name of the module to be unloaded (string)
+name of the module to be unloaded
 </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>
 <div align="right"><a href="#top">Up</a></div>
--- a/src/eric7/Documentation/Source/eric7.PluginManager.PluginRepositoryDialog.html	Thu Nov 16 13:58:04 2023 +0100
+++ b/src/eric7/Documentation/Source/eric7.PluginManager.PluginRepositoryDialog.html	Thu Nov 16 15:56:12 2023 +0100
@@ -32,6 +32,10 @@
 <td><a href="#PluginRepositoryWindow">PluginRepositoryWindow</a></td>
 <td>Main window class for the standalone dialog.</td>
 </tr>
+<tr>
+<td><a href="#PluginStatus">PluginStatus</a></td>
+<td>Class defining the various plugin status.</td>
+</tr>
 </table>
 <h3>Functions</h3>
 
@@ -124,7 +128,13 @@
 <dl>
 <dt>Return:</dt>
 <dd>
-list of plugin filenames (list of strings)
+list of plugin filenames
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+list of str
 </dd>
 </dl>
 <div align="right"><a href="#top">Up</a></div>
@@ -150,7 +160,7 @@
 <h3>Class Attributes</h3>
 
 <table>
-<tr><td>AuthorRole</td></tr><tr><td>DescrRole</td></tr><tr><td>FilenameRole</td></tr><tr><td>PluginStatusError</td></tr><tr><td>PluginStatusLocalUpdate</td></tr><tr><td>PluginStatusNew</td></tr><tr><td>PluginStatusRemoteUpdate</td></tr><tr><td>PluginStatusUpToDate</td></tr><tr><td>UrlRole</td></tr>
+<tr><td>AuthorRole</td></tr><tr><td>DescrRole</td></tr><tr><td>FilenameRole</td></tr><tr><td>UrlRole</td></tr>
 </table>
 <h3>Class Methods</h3>
 
@@ -218,10 +228,6 @@
 <td>Private slot to show the download progress.</td>
 </tr>
 <tr>
-<td><a href="#PluginRepositoryWidget.__downloadRepositoryFileDone">__downloadRepositoryFileDone</a></td>
-<td>Private method called after the repository file was downloaded.</td>
-</tr>
-<tr>
 <td><a href="#PluginRepositoryWidget.__formatDescription">__formatDescription</a></td>
 <td>Private method to format the description.</td>
 </tr>
@@ -238,6 +244,10 @@
 <td>Private slot to hide all selected plug-ins.</td>
 </tr>
 <tr>
+<td><a href="#PluginRepositoryWidget.__initHeaderItemsCache">__initHeaderItemsCache</a></td>
+<td>Private method to initialize the cache variables for the header items.</td>
+</tr>
+<tr>
 <td><a href="#PluginRepositoryWidget.__populateList">__populateList</a></td>
 <td>Private method to populate the list of available plugins.</td>
 </tr>
@@ -251,7 +261,7 @@
 </tr>
 <tr>
 <td><a href="#PluginRepositoryWidget.__selectedItems">__selectedItems</a></td>
-<td>Private method to get all selected items without the toplevel ones.</td>
+<td>Private method to get all selected items without the status and category items.</td>
 </tr>
 <tr>
 <td><a href="#PluginRepositoryWidget.__showAllPlugins">__showAllPlugins</a></td>
@@ -347,7 +357,7 @@
 <dd>
 URL to be modified
 </dd>
-<dt><i>newScheme</i></dt>
+<dt><i>newScheme</i> (str)</dt>
 <dd>
 scheme to be set for the given URL
 </dd>
@@ -408,15 +418,15 @@
 </p>
 <dl>
 
-<dt><i>url</i></dt>
+<dt><i>url</i> (str)</dt>
 <dd>
-URL for the download (string)
+URL for the download
 </dd>
-<dt><i>filename</i></dt>
+<dt><i>filename</i> (str)</dt>
 <dd>
-local name of the file (string)
+local name of the file
 </dd>
-<dt><i>doneMethod</i></dt>
+<dt><i>doneMethod</i> (function)</dt>
 <dd>
 method to be called when done
 </dd>
@@ -439,7 +449,7 @@
 <dd>
 local name of the file
 </dd>
-<dt><i>doneMethod</i> (func)</dt>
+<dt><i>doneMethod</i> (function)</dt>
 <dd>
 method to be called when done
 </dd>
@@ -467,13 +477,13 @@
 </p>
 <dl>
 
-<dt><i>status</i></dt>
+<dt><i>status</i> (bool)</dt>
 <dd>
-flag indicating a successful download (boolean)
+flag indicating a successful download
 </dd>
-<dt><i>filename</i></dt>
+<dt><i>filename</i> (str)</dt>
 <dd>
-full path of the downloaded file (string)
+full path of the downloaded file
 </dd>
 </dl>
 <a NAME="PluginRepositoryWidget.__downloadPlugins" ID="PluginRepositoryWidget.__downloadPlugins"></a>
@@ -499,31 +509,13 @@
 </p>
 <dl>
 
-<dt><i>done</i></dt>
+<dt><i>done</i> (int)</dt>
 <dd>
-number of bytes downloaded so far (integer)
-</dd>
-<dt><i>total</i></dt>
-<dd>
-total bytes to be downloaded (integer)
+number of bytes downloaded so far
 </dd>
-</dl>
-<a NAME="PluginRepositoryWidget.__downloadRepositoryFileDone" ID="PluginRepositoryWidget.__downloadRepositoryFileDone"></a>
-<h4>PluginRepositoryWidget.__downloadRepositoryFileDone</h4>
-<b>__downloadRepositoryFileDone</b>(<i>status, filename</i>)
-
-<p>
-        Private method called after the repository file was downloaded.
-</p>
-<dl>
-
-<dt><i>status</i></dt>
+<dt><i>total</i> (int)</dt>
 <dd>
-flaging indicating a successful download (boolean)
-</dd>
-<dt><i>filename</i></dt>
-<dd>
-full path of the downloaded file (string)
+total bytes to be downloaded
 </dd>
 </dl>
 <a NAME="PluginRepositoryWidget.__formatDescription" ID="PluginRepositoryWidget.__formatDescription"></a>
@@ -535,15 +527,21 @@
 </p>
 <dl>
 
-<dt><i>lines</i></dt>
+<dt><i>lines</i> (list of str)</dt>
 <dd>
-lines of the description (list of strings)
+lines of the description
 </dd>
 </dl>
 <dl>
 <dt>Return:</dt>
 <dd>
-formatted description (string)
+formatted description
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+str
 </dd>
 </dl>
 <a NAME="PluginRepositoryWidget.__hasHiddenPlugins" ID="PluginRepositoryWidget.__hasHiddenPlugins"></a>
@@ -556,7 +554,13 @@
 <dl>
 <dt>Return:</dt>
 <dd>
-flag indicating the presence of hidden plug-ins (boolean)
+flag indicating the presence of hidden plug-ins
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+bool
 </dd>
 </dl>
 <a NAME="PluginRepositoryWidget.__hidePlugin" ID="PluginRepositoryWidget.__hidePlugin"></a>
@@ -573,6 +577,13 @@
 <p>
         Private slot to hide all selected plug-ins.
 </p>
+<a NAME="PluginRepositoryWidget.__initHeaderItemsCache" ID="PluginRepositoryWidget.__initHeaderItemsCache"></a>
+<h4>PluginRepositoryWidget.__initHeaderItemsCache</h4>
+<b>__initHeaderItemsCache</b>(<i></i>)
+
+<p>
+        Private method to initialize the cache variables for the header items.
+</p>
 <a NAME="PluginRepositoryWidget.__populateList" ID="PluginRepositoryWidget.__populateList"></a>
 <h4>PluginRepositoryWidget.__populateList</h4>
 <b>__populateList</b>(<i></i>)
@@ -606,12 +617,18 @@
 <b>__selectedItems</b>(<i></i>)
 
 <p>
-        Private method to get all selected items without the toplevel ones.
+        Private method to get all selected items without the status and category items.
 </p>
 <dl>
 <dt>Return:</dt>
 <dd>
-list of selected items (list)
+list of selected items without header items
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+list of QTreeWidgetItem
 </dd>
 </dl>
 <a NAME="PluginRepositoryWidget.__showAllPlugins" ID="PluginRepositoryWidget.__showAllPlugins"></a>
@@ -630,13 +647,13 @@
 </p>
 <dl>
 
-<dt><i>reply</i></dt>
+<dt><i>reply</i> (QNetworkReply)</dt>
 <dd>
-reference to the reply object (QNetworkReply)
+reference to the reply object
 </dd>
-<dt><i>errors</i></dt>
+<dt><i>errors</i> (list of QSslError)</dt>
 <dd>
-list of SSL errors (list of QSslError)
+list of SSL errors
 </dd>
 </dl>
 <a NAME="PluginRepositoryWidget.__updateHiddenPluginsList" ID="PluginRepositoryWidget.__updateHiddenPluginsList"></a>
@@ -648,10 +665,9 @@
 </p>
 <dl>
 
-<dt><i>hideList</i></dt>
+<dt><i>hideList</i> (list of str)</dt>
 <dd>
 list of plug-ins to add to the list of hidden ones
-            (list of string)
 </dd>
 </dl>
 <a NAME="PluginRepositoryWidget.__updateList" ID="PluginRepositoryWidget.__updateList"></a>
@@ -670,63 +686,72 @@
 </p>
 <dl>
 
-<dt><i>filename</i></dt>
+<dt><i>filename</i> (str)</dt>
 <dd>
-data for the filename field (string)
+data for the filename field
 </dd>
-<dt><i>version</i></dt>
+<dt><i>version</i> (str)</dt>
 <dd>
-data for the version field (string)
+data for the version field
 </dd>
 </dl>
 <dl>
 <dt>Return:</dt>
 <dd>
-plug-in update status (integer, one of PluginStatusNew,
-            PluginStatusUpToDate, PluginStatusLocalUpdate,
-            PluginStatusRemoteUpdate)
+plug-in update status
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+int (one of PluginStatusNew, PluginStatusUpToDate,
+            PluginStatusLocalUpdate, PluginStatusRemoteUpdate)
 </dd>
 </dl>
 <a NAME="PluginRepositoryWidget.addEntry" ID="PluginRepositoryWidget.addEntry"></a>
 <h4>PluginRepositoryWidget.addEntry</h4>
-<b>addEntry</b>(<i>name, short, description, url, author, version, filename, status</i>)
+<b>addEntry</b>(<i>name, short, description, url, author, version, filename, status, category, </i>)
 
 <p>
         Public method to add an entry to the list.
 </p>
 <dl>
 
-<dt><i>name</i></dt>
+<dt><i>name</i> (str)</dt>
 <dd>
-data for the name field (string)
+data for the name field
 </dd>
-<dt><i>short</i></dt>
+<dt><i>short</i> (str)</dt>
 <dd>
-data for the short field (string)
+data for the short field
 </dd>
-<dt><i>description</i></dt>
+<dt><i>description</i> (list of str)</dt>
 <dd>
-data for the description field (list of strings)
+data for the description field
 </dd>
-<dt><i>url</i></dt>
+<dt><i>url</i> (str)</dt>
 <dd>
-data for the url field (string)
+data for the url field
 </dd>
-<dt><i>author</i></dt>
+<dt><i>author</i> (str)</dt>
 <dd>
-data for the author field (string)
+data for the author field
 </dd>
-<dt><i>version</i></dt>
+<dt><i>version</i> (str)</dt>
 <dd>
-data for the version field (string)
+data for the version field
 </dd>
-<dt><i>filename</i></dt>
+<dt><i>filename</i> (str)</dt>
 <dd>
-data for the filename field (string)
+data for the filename field
 </dd>
-<dt><i>status</i></dt>
+<dt><i>status</i> (str)</dt>
 <dd>
-status of the plugin (string [stable, unstable, unknown])
+status of the plugin (one of stable, unstable, unknown)
+</dd>
+<dt><i>category</i> (str)</dt>
+<dd>
+category designation of the plugin
 </dd>
 </dl>
 <a NAME="PluginRepositoryWidget.getDownloadedPlugins" ID="PluginRepositoryWidget.getDownloadedPlugins"></a>
@@ -739,7 +764,13 @@
 <dl>
 <dt>Return:</dt>
 <dd>
-list of plugin filenames (list of strings)
+list of plugin filenames
+</dd>
+</dl>
+<dl>
+<dt>Return Type:</dt>
+<dd>
+list of str
 </dd>
 </dl>
 <a NAME="PluginRepositoryWidget.on_buttonBox_clicked" ID="PluginRepositoryWidget.on_buttonBox_clicked"></a>
@@ -751,9 +782,9 @@
 </p>
 <dl>
 
-<dt><i>button</i></dt>
+<dt><i>button</i> (QAbstractButton)</dt>
 <dd>
-reference to the button pressed (QAbstractButton)
+reference to the button pressed
 </dd>
 </dl>
 <a NAME="PluginRepositoryWidget.on_repositoryList_currentItemChanged" ID="PluginRepositoryWidget.on_repositoryList_currentItemChanged"></a>
@@ -765,13 +796,13 @@
 </p>
 <dl>
 
-<dt><i>current</i></dt>
+<dt><i>current</i> (QTreeWidgetItem)</dt>
 <dd>
-reference to the new current item (QTreeWidgetItem)
+reference to the new current item
 </dd>
-<dt><i>previous</i></dt>
+<dt><i>previous</i> (QTreeWidgetItem)</dt>
 <dd>
-reference to the old current item (QTreeWidgetItem)
+reference to the old current item
 </dd>
 </dl>
 <a NAME="PluginRepositoryWidget.on_repositoryList_customContextMenuRequested" ID="PluginRepositoryWidget.on_repositoryList_customContextMenuRequested"></a>
@@ -783,9 +814,9 @@
 </p>
 <dl>
 
-<dt><i>pos</i></dt>
+<dt><i>pos</i> (QPoint)</dt>
 <dd>
-position to show the menu (QPoint)
+position to show the menu
 </dd>
 </dl>
 <a NAME="PluginRepositoryWidget.on_repositoryList_itemSelectionChanged" ID="PluginRepositoryWidget.on_repositoryList_itemSelectionChanged"></a>
@@ -805,9 +836,9 @@
 </p>
 <dl>
 
-<dt><i>checked</i></dt>
+<dt><i>checked</i> (bool)</dt>
 <dd>
-state of the push button (boolean)
+state of the push button
 </dd>
 </dl>
 <a NAME="PluginRepositoryWidget.reloadList" ID="PluginRepositoryWidget.reloadList"></a>
@@ -866,9 +897,9 @@
 </p>
 <dl>
 
-<dt><i>parent</i></dt>
+<dt><i>parent</i> (QWidget)</dt>
 <dd>
-reference to the parent widget (QWidget)
+reference to the parent widget
 </dd>
 </dl>
 <a NAME="PluginRepositoryWindow.__startPluginInstall" ID="PluginRepositoryWindow.__startPluginInstall"></a>
@@ -881,6 +912,38 @@
 <div align="right"><a href="#top">Up</a></div>
 <hr />
 <hr />
+<a NAME="PluginStatus" ID="PluginStatus"></a>
+<h2>PluginStatus</h2>
+
+<p>
+    Class defining the various plugin status.
+</p>
+<h3>Derived from</h3>
+enum.Enum
+<h3>Class Attributes</h3>
+
+<table>
+<tr><td>Error</td></tr><tr><td>LocalUpdate</td></tr><tr><td>New</td></tr><tr><td>RemoteUpdate</td></tr><tr><td>UpToDate</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="PluginRepositoryDownloadCleanup" ID="PluginRepositoryDownloadCleanup"></a>
 <h2>PluginRepositoryDownloadCleanup</h2>
 <b>PluginRepositoryDownloadCleanup</b>(<i>quiet=False</i>)
@@ -900,44 +963,48 @@
 <hr />
 <a NAME="registerPlugin" ID="registerPlugin"></a>
 <h2>registerPlugin</h2>
-<b>registerPlugin</b>(<i>name, short, description, url, author, version, filename, status</i>)
+<b>registerPlugin</b>(<i>name, short, description, url, author, version, filename, status, category, </i>)
 
 <p>
         Method to register a plug-in's data.
 </p>
 <dl>
 
-<dt><i>name</i></dt>
+<dt><i>name</i> (str)</dt>
 <dd>
-data for the name field (string)
+data for the name field
 </dd>
-<dt><i>short</i></dt>
+<dt><i>short</i> (str)</dt>
 <dd>
-data for the short field (string)
+data for the short field
 </dd>
-<dt><i>description</i></dt>
+<dt><i>description</i> (list of str)</dt>
 <dd>
-data for the description field (list of strings)
+data for the description field
 </dd>
-<dt><i>url</i></dt>
+<dt><i>url</i> (str)</dt>
 <dd>
-data for the url field (string)
+data for the url field
 </dd>
-<dt><i>author</i></dt>
+<dt><i>author</i> (str)</dt>
 <dd>
-data for the author field (string)
+data for the author field
 </dd>
-<dt><i>version</i></dt>
+<dt><i>version</i> (str)</dt>
 <dd>
-data for the version field (string)
+data for the version field
 </dd>
-<dt><i>filename</i></dt>
+<dt><i>filename</i> (str)</dt>
 <dd>
-data for the filename field (string)
+data for the filename field
 </dd>
-<dt><i>status</i></dt>
+<dt><i>status</i> (str)</dt>
 <dd>
-status of the plugin (string [stable, unstable, unknown])
+status of the plugin (one of stable, unstable, unknown)
+</dd>
+<dt><i>category</i> (str)</dt>
+<dd>
+category designation of the plugin
 </dd>
 </dl>
 <div align="right"><a href="#top">Up</a></div>
--- a/src/eric7/EricXML/PluginRepositoryReader.py	Thu Nov 16 13:58:04 2023 +0100
+++ b/src/eric7/EricXML/PluginRepositoryReader.py	Thu Nov 16 15:56:12 2023 +0100
@@ -24,9 +24,11 @@
         """
         Constructor
 
-        @param device reference to the I/O device to read from (QIODevice)
+        @param device reference to the I/O device to read from
+        @type QIODevice
         @param entryCallback reference to a function to be called once the
-            data for a plug-in has been read (function)
+            data for a plug-in has been read
+        @type function
         """
         XMLStreamReaderBase.__init__(self, device)
 
@@ -70,6 +72,7 @@
             "version": "",
             "filename": "",
             "status": self.attribute("status", "unknown"),
+            "category": self.attribute("category", "not categorized")
         }
 
         while not self.atEnd():
@@ -84,6 +87,7 @@
                     pluginInfo["version"],
                     pluginInfo["filename"],
                     pluginInfo["status"],
+                    pluginInfo["category"],
                 )
                 break
 
--- a/src/eric7/PluginManager/PluginManager.py	Thu Nov 16 13:58:04 2023 +0100
+++ b/src/eric7/PluginManager/PluginManager.py	Thu Nov 16 15:56:12 2023 +0100
@@ -186,8 +186,10 @@
         """
         Public method to get the path of a plugin directory.
 
-        @param key key of the plug-in directory (string)
-        @return path of the requested plugin directory (string)
+        @param key key of the plug-in directory
+        @type str
+        @return path of the requested plugin directory
+        @rtype str
         """
         if key not in ["global", "user"]:
             return None
@@ -204,7 +206,8 @@
         If the plugin folders don't exist, they are created (if possible).
 
         @return tuple of a flag indicating existence of any of the plugin
-            directories (boolean) and a message (string)
+            directories and a message
+        @rtype tuple of (bool, str)
         """
         if self.__develPluginFile:
             path = FileSystemUtilities.splitPath(self.__develPluginFile)[0]
@@ -259,7 +262,8 @@
         """
         Private method to check, if there are plugins available.
 
-        @return flag indicating the availability of plugins (boolean)
+        @return flag indicating the availability of plugins
+        @rtype bool
         """
         if self.__develPluginFile and not os.path.exists(self.__develPluginFile):
             return False
@@ -286,8 +290,10 @@
         """
         Public method to get a list of plugin modules.
 
-        @param pluginPath name of the path to search (string)
-        @return list of plugin module names (list of string)
+        @param pluginPath name of the path to search
+        @type str
+        @return list of plugin module names
+        @rtype list of str
         """
         pluginFiles = [
             f[:-3] for f in os.listdir(pluginPath) if self.isValidPluginName(f)
@@ -300,14 +306,16 @@
 
         Plugin modules must start with "Plugin" and have the extension ".py".
 
-        @param pluginName name of the file to be checked (string)
-        @return flag indicating a valid plugin name (boolean)
+        @param pluginName name of the file to be checked
+        @type str
+        @return flag indicating a valid plugin name
+        @rtype bool
         """
         return pluginName.startswith("Plugin") and pluginName.endswith(".py")
 
     def __insertPluginsPaths(self):
         """
-        Private method to insert the valid plugin paths intos the search path.
+        Private method to insert the valid plugin paths into the search path.
         """
         for key in self.__priorityOrder:
             if key in self.pluginDirs:
@@ -468,8 +476,10 @@
         """
         Public method to unload a plugin module.
 
-        @param name name of the module to be unloaded (string)
-        @return flag indicating success (boolean)
+        @param name name of the module to be unloaded
+        @type str
+        @return flag indicating success
+        @rtype bool
         """
         if name in self.__onDemandActiveModules:
             # cannot unload an ondemand plugin, that is in use
@@ -503,11 +513,14 @@
         Public method to remove a plugin and all related modules from
         sys.modules.
 
-        @param pluginName name of the plugin module (string)
-        @param package name of the plugin package (string)
-        @param internalPackages list of intenal packages (list of string)
+        @param pluginName name of the plugin module
+        @type str
+        @param package name of the plugin package
+        @type str
+        @param internalPackages list of intenal packages
+        @type list of str
         @return flag indicating the plugin module was found in sys.modules
-            (boolean)
+        @rtype bool
         """
         packages = [package] + internalPackages
         found = False
@@ -535,7 +548,8 @@
 
         Note: The plug-in is not activated.
 
-        @param name name of the plug-in (string)
+        @param name name of the plug-in
+        @type str
         @exception PluginActivationError raised to indicate an issue during the
             plug-in activation
         """
@@ -565,7 +579,7 @@
         Public method to initialize plug-in toolbars.
 
         @param toolbarManager reference to the toolbar manager object
-            (EricToolBarManager)
+        @type EricToolBarManager
         """
         self.initOnDemandPlugins()
         for pluginObject in self.__onDemandInactivePlugins.values():
@@ -670,8 +684,10 @@
         Private method to check, if a plugin can be activated.
 
         @param module reference to the module to be activated
+        @type Module
         @return flag indicating, if the module satisfies all requirements
-            for being activated (boolean)
+            for being activated
+        @rtype bool
         @exception PluginModuleFormatError raised to indicate an invalid
             plug-in module format
         @exception PluginClassFormatError raised to indicate an invalid
@@ -711,8 +727,10 @@
         Public method to deactivate a plugin.
 
         @param name name of the module to be deactivated
+        @type str
         @param onDemand flag indicating deactivation of an
-            on demand plugin (boolean)
+            on demand plugin
+        @type bool
         """
         try:
             module = (
@@ -751,15 +769,17 @@
         Private method to check, if a plugin can be deactivated.
 
         @param module reference to the module to be deactivated
+        @type Module
         @return flag indicating, if the module satisfies all requirements
-            for being deactivated (boolean)
+            for being deactivated
+        @rtype bool
         """
         return getPluginHeaderEntry(module, "deactivateable", True)
 
     def getPluginObject(self, type_, typename, maybeActive=False):
         """
-        Public method to activate an ondemand plugin given by type and
-        typename.
+        Public method to activate an on-demand plugin given by type and
+        type name.
 
         @param type_ type of the plugin to be activated
         @type str
@@ -868,7 +888,8 @@
         Private method to extract the short info from a module.
 
         @param module module to extract short info from
-        @return dictionay containing plug-in data
+        @type Module
+        @return dictionary containing plug-in data
         @rtype dict ("plugin_name": str, "version": str, "short_desc": str,
             "error": bool)
         """
@@ -883,8 +904,10 @@
         """
         Public method to get detailed information about a plugin.
 
-        @param name name of the module to get detailed infos about (string)
+        @param name name of the module to get detailed infos about
+        @type str
         @return details of the plugin as a dictionary
+        @rtype dict
         """
         details = {}
 
@@ -944,9 +967,10 @@
         Public method to get the display strings of all plugins of a specific
         type.
 
-        @param type_ type of the plugins (string)
+        @param type_ type of the plugins
+        @type str
         @return dictionary with name as key and display string as value
-            (dictionary of string)
+        @rtype dict
         """
         pluginDict = {}
 
@@ -969,9 +993,12 @@
         """
         Public method to get a preview pixmap of a plugin of a specific type.
 
-        @param type_ type of the plugin (string)
-        @param name name of the plugin type (string)
-        @return preview pixmap (QPixmap)
+        @param type_ type of the plugin
+        @type str
+        @param name name of the plugin type
+        @type str
+        @return preview pixmap
+        @rtype QPixmap
         """
         for module in list(self.__onDemandActiveModules.values()) + list(
             self.__onDemandInactiveModules.values()
@@ -991,8 +1018,10 @@
         """
         Public method to get the list of API files installed by a plugin.
 
-        @param language language of the requested API files (string)
-        @return list of API filenames (list of string)
+        @param language language of the requested API files
+        @type str
+        @return list of API filenames
+        @rtype list of str
         """
         apis = []
 
@@ -1055,6 +1084,7 @@
                 <li>text - entry text to be shown (string)</li>
                 <li>version - version text to be shown (string)</li>
             </ul>
+        @rtype list of dict
         """
         infos = []
 
@@ -1106,6 +1136,7 @@
         </dl>
 
         @return plug-in configuration data
+        @rtype dict
         """
         configData = {}
         for module in (
@@ -1121,8 +1152,10 @@
         """
         Public method to check, if a certain plugin is loaded.
 
-        @param pluginName name of the plugin to check for (string)
-        @return flag indicating, if the plugin is loaded (boolean)
+        @param pluginName name of the plugin to check for
+        @type str
+        @return flag indicating, if the plugin is loaded
+        @rtype bool
         """
         return (
             pluginName in self.__activeModules
@@ -1135,8 +1168,10 @@
         """
         Public method to check, if a certain plugin is active.
 
-        @param pluginName name of the plugin to check for (string)
-        @return flag indicating, if the plugin is active (boolean)
+        @param pluginName name of the plugin to check for
+        @type str
+        @return flag indicating, if the plugin is active
+        @rtype bool
         """
         return (
             pluginName in self.__activeModules
@@ -1160,8 +1195,9 @@
         a tuple with the vcs name (string) and vcs display string (string).
 
         @return dictionary with indicator as key and a list of tuples as
-            values. Each tuple contains the vcs name (string) and vcs display
-            string (string).
+            values. Each tuple contains the vcs name (str) and vcs display
+            string (str).
+        @rtype dict
         """
         vcsDict = {}
 
@@ -1351,18 +1387,29 @@
         version,
         filename,
         status,  # noqa: U100
+        category,  # noqa: U100
     ):
         """
         Public method to check a plug-in's data for an update.
 
-        @param name data for the name field (string)
-        @param short data for the short field (string)
-        @param description data for the description field (list of strings)
-        @param url data for the url field (string)
-        @param author data for the author field (string)
-        @param version data for the version field (string)
-        @param filename data for the filename field (string)
-        @param status status of the plugin (string [stable, unstable, unknown])
+        @param name data for the name field
+        @type str
+        @param short data for the short field
+        @type str
+        @param description data for the description field
+        @type list of str
+        @param url data for the url field
+        @type str
+        @param author data for the author field
+        @type str
+        @param version data for the version field
+        @type str
+        @param filename data for the filename field
+        @type str
+        @param status status of the plugin (one of stable, unstable, unknown)
+        @type str
+        @param category category designation of the plugin
+        @type str
         """
         # ignore hidden plug-ins
         pluginName = os.path.splitext(url.rsplit("/", 1)[1])[0]
@@ -1414,8 +1461,10 @@
         """
         Private slot to handle SSL errors.
 
-        @param reply reference to the reply object (QNetworkReply)
-        @param errors list of SSL errors (list of QSslError)
+        @param reply reference to the reply object
+        @type QNetworkReply
+        @param errors list of SSL errors
+        @type list of QSslError
         """
         ignored = self.__sslErrorHandler.sslErrorsReply(reply, errors)[0]
         if ignored == EricSslErrorState.NOT_IGNORED:
@@ -1433,7 +1482,8 @@
         Plugins supporting this functionality must support the module function
         clearPrivateData() and have the module level attribute pluginType.
 
-        @param type_ type of the plugin to clear private data for (string)
+        @param type_ type of the plugin to clear private data for
+        @type str
         """
         for module in (
             list(self.__onDemandActiveModules.values())
--- a/src/eric7/PluginManager/PluginRepositoryDialog.py	Thu Nov 16 13:58:04 2023 +0100
+++ b/src/eric7/PluginManager/PluginRepositoryDialog.py	Thu Nov 16 15:56:12 2023 +0100
@@ -7,11 +7,14 @@
 Module implementing a dialog showing the available plugins.
 """
 
+import enum
 import glob
 import os
 import re
 import zipfile
 
+from collections import ChainMap, defaultdict
+
 from PyQt6.QtCore import (
     QCoreApplication,
     QFile,
@@ -66,6 +69,18 @@
 from .Ui_PluginRepositoryDialog import Ui_PluginRepositoryDialog
 
 
+class PluginStatus(enum.Enum):
+    """
+    Class defining the various plugin status.
+    """
+
+    UpToDate = 0
+    New = 1
+    LocalUpdate = 2
+    RemoteUpdate = 3
+    Error = 4
+
+
 class PluginRepositoryWidget(QWidget, Ui_PluginRepositoryDialog):
     """
     Class implementing a dialog showing the available plugins.
@@ -81,12 +96,6 @@
     FilenameRole = Qt.ItemDataRole.UserRole + 2
     AuthorRole = Qt.ItemDataRole.UserRole + 3
 
-    PluginStatusUpToDate = 0
-    PluginStatusNew = 1
-    PluginStatusLocalUpdate = 2
-    PluginStatusRemoteUpdate = 3
-    PluginStatusError = 4
-
     def __init__(self, pluginManager, integrated=False, parent=None):
         """
         Constructor
@@ -111,6 +120,14 @@
 
         self.__integratedWidget = integrated
 
+        self.__statusTranslations = {
+            "stable": self.tr("Stable"),
+            "unstable": self.tr("Unstable"),
+            "obsolete": self.tr("Obsolete"),
+            "unknown": self.tr("Unknown"),
+        }
+        self.__initHeaderItemsCache()
+
         if self.__integratedWidget:
             self.layout().setContentsMargins(0, 3, 0, 0)
 
@@ -272,7 +289,8 @@
         """
         Private slot to handle the click of a button of the button box.
 
-        @param button reference to the button pressed (QAbstractButton)
+        @param button reference to the button pressed
+        @type QAbstractButton
         """
         if button == self.__updateButton:
             self.__updateList()
@@ -306,8 +324,10 @@
         """
         Private method to format the description.
 
-        @param lines lines of the description (list of strings)
-        @return formatted description (string)
+        @param lines lines of the description
+        @type list of str
+        @return formatted description
+        @rtype str
         """
         # remove empty line at start and end
         newlines = lines[:]
@@ -333,6 +353,7 @@
         @param url URL to be modified
         @type str
         @param newScheme scheme to be set for the given URL
+        @type str
         @return modified URL
         @rtype str
         """
@@ -350,7 +371,8 @@
         """
         Private slot to show the context menu.
 
-        @param pos position to show the menu (QPoint)
+        @param pos position to show the menu
+        @type QPoint
         """
         self.__hideAct.setEnabled(
             self.repositoryList.currentItem() is not None
@@ -365,8 +387,10 @@
         """
         Private slot to handle the change of the current item.
 
-        @param current reference to the new current item (QTreeWidgetItem)
-        @param previous reference to the old current item (QTreeWidgetItem)
+        @param current reference to the new current item
+        @type QTreeWidgetItem
+        @param previous reference to the old current item
+        @type QTreeWidgetItem
         """
         if self.__repositoryMissing or current is None:
             self.descriptionEdit.clear()
@@ -389,16 +413,20 @@
 
     def __selectedItems(self):
         """
-        Private method to get all selected items without the toplevel ones.
+        Private method to get all selected items without the status and category items.
 
-        @return list of selected items (list)
+        @return list of selected items without header items
+        @rtype list of QTreeWidgetItem
         """
-        ql = self.repositoryList.selectedItems()
-        for index in range(self.repositoryList.topLevelItemCount()):
-            ti = self.repositoryList.topLevelItem(index)
-            if ti in ql:
-                ql.remove(ti)
-        return ql
+        selectedItems = []
+        allCategoryItems = ChainMap(*self.__categoryItems.values())
+        for itm in self.repositoryList.selectedItems():
+            if (
+                itm not in self.__statusItems.values()
+                and itm not in allCategoryItems.values()
+            ):
+                selectedItems.append(itm)
+        return selectedItems
 
     @pyqtSlot()
     def on_repositoryList_itemSelectionChanged(self):
@@ -426,21 +454,14 @@
             url = url.replace("https://", "http://")
         self.__pluginManager.downLoadRepositoryFile(url=url)
 
-    def __downloadRepositoryFileDone(self, status, filename):  # noqa: U100
-        """
-        Private method called after the repository file was downloaded.
-
-        @param status flaging indicating a successful download (boolean)
-        @param filename full path of the downloaded file (string)
-        """
-        self.__populateList()
-
     def __downloadPluginDone(self, status, filename):
         """
         Private method called, when the download of a plugin is finished.
 
-        @param status flag indicating a successful download (boolean)
-        @param filename full path of the downloaded file (string)
+        @param status flag indicating a successful download
+        @type bool
+        @param filename full path of the downloaded file
+        @type str
         """
         if status:
             self.__pluginsDownloaded.append(filename)
@@ -480,21 +501,15 @@
             if Preferences.getPluginManager("ForceHttpPluginDownload")
             else self.repositoryUrlEdit.text().split("//", 1)[0]
         )
-        for itm in self.repositoryList.selectedItems():
-            if itm not in [
-                self.__stableItem,
-                self.__unstableItem,
-                self.__unknownItem,
-                self.__obsoleteItem,
-            ]:
-                url = self.__changeScheme(
-                    itm.data(0, PluginRepositoryWidget.UrlRole), newScheme
-                )
-                filename = os.path.join(
-                    Preferences.getPluginManager("DownloadPath"),
-                    itm.data(0, PluginRepositoryWidget.FilenameRole),
-                )
-                self.__pluginsToDownload.append((url, filename))
+        for itm in self.__selectedItems():
+            url = self.__changeScheme(
+                itm.data(0, PluginRepositoryWidget.UrlRole), newScheme
+            )
+            filename = os.path.join(
+                Preferences.getPluginManager("DownloadPath"),
+                itm.data(0, PluginRepositoryWidget.FilenameRole),
+            )
+            self.__pluginsToDownload.append((url, filename))
         if self.__pluginsToDownload:
             self.__downloadPlugin()
 
@@ -532,20 +547,30 @@
         """
         Private method to resort the tree.
         """
-        self.repositoryList.sortItems(
-            self.repositoryList.sortColumn(),
-            self.repositoryList.header().sortIndicatorOrder(),
-        )
+        if self.__integratedWidget:
+            self.repositoryList.sortItems(
+                self.repositoryList.sortColumn(),
+                Qt.SortOrder.AscendingOrder,
+            )
+        else:
+            self.repositoryList.sortItems(
+                self.repositoryList.sortColumn(),
+                self.repositoryList.header().sortIndicatorOrder(),
+            )
+
+    def __initHeaderItemsCache(self):
+        """
+        Private method to initialize the cache variables for the header items.
+        """
+        self.__statusItems = defaultdict(lambda: None)
+        self.__categoryItems = defaultdict(dict)
 
     def __populateList(self):
         """
         Private method to populate the list of available plugins.
         """
+        self.__initHeaderItemsCache()
         self.repositoryList.clear()
-        self.__stableItem = None
-        self.__unstableItem = None
-        self.__unknownItem = None
-        self.__obsoleteItem = None
 
         self.__newItems = 0
         self.__updateLocalItems = 0
@@ -604,9 +629,12 @@
         """
         Private slot to download the given file.
 
-        @param url URL for the download (string)
-        @param filename local name of the file (string)
+        @param url URL for the download
+        @type str
+        @param filename local name of the file
+        @type str
         @param doneMethod method to be called when done
+        @type function
         """
         if self.__online:
             self.__updateButton.setEnabled(False)
@@ -652,7 +680,7 @@
         @param fileName local name of the file
         @type str
         @param doneMethod method to be called when done
-        @type func
+        @type function
         """
         self.__updateButton.setEnabled(True)
         if not self.__integratedWidget:
@@ -720,69 +748,87 @@
         """
         Private slot to show the download progress.
 
-        @param done number of bytes downloaded so far (integer)
-        @param total total bytes to be downloaded (integer)
+        @param done number of bytes downloaded so far
+        @type int
+        @param total total bytes to be downloaded
+        @type int
         """
         if total:
             self.downloadProgress.setMaximum(total)
             self.downloadProgress.setValue(done)
 
     def addEntry(
-        self, name, short, description, url, author, version, filename, status
+        self,
+        name,
+        short,
+        description,
+        url,
+        author,
+        version,
+        filename,
+        status,
+        category,
     ):
         """
         Public method to add an entry to the list.
 
-        @param name data for the name field (string)
-        @param short data for the short field (string)
-        @param description data for the description field (list of strings)
-        @param url data for the url field (string)
-        @param author data for the author field (string)
-        @param version data for the version field (string)
-        @param filename data for the filename field (string)
-        @param status status of the plugin (string [stable, unstable, unknown])
+        @param name data for the name field
+        @type str
+        @param short data for the short field
+        @type str
+        @param description data for the description field
+        @type list of str
+        @param url data for the url field
+        @type str
+        @param author data for the author field
+        @type str
+        @param version data for the version field
+        @type str
+        @param filename data for the filename field
+        @type str
+        @param status status of the plugin (one of stable, unstable, unknown)
+        @type str
+        @param category category designation of the plugin
+        @type str
         """
         pluginName = filename.rsplit("-", 1)[0]
         if pluginName in self.__hiddenPlugins:
             return
 
-        if status == "stable":
-            if self.__stableItem is None:
-                self.__stableItem = QTreeWidgetItem(
-                    self.repositoryList, [self.tr("Stable")]
-                )
-                self.__stableItem.setExpanded(True)
-            parent = self.__stableItem
-        elif status == "unstable":
-            if self.__unstableItem is None:
-                self.__unstableItem = QTreeWidgetItem(
-                    self.repositoryList, [self.tr("Unstable")]
-                )
-                self.__unstableItem.setExpanded(True)
-            parent = self.__unstableItem
-        elif status == "obsolete":
-            if self.__obsoleteItem is None:
-                self.__obsoleteItem = QTreeWidgetItem(
-                    self.repositoryList, [self.tr("Obsolete")]
-                )
-                self.__obsoleteItem.setExpanded(True)
-            parent = self.__obsoleteItem
-        else:
-            if self.__unknownItem is None:
-                self.__unknownItem = QTreeWidgetItem(
-                    self.repositoryList, [self.tr("Unknown")]
-                )
-                self.__unknownItem.setExpanded(True)
-            parent = self.__unknownItem
+        # 1. determine and create the status item
+        statusItem = self.__statusItems[status]
+        if statusItem is None:
+            statusItem = QTreeWidgetItem(
+                self.repositoryList,
+                [
+                    self.__statusTranslations.get(
+                        status, self.__statusTranslations["unknown"]
+                    )
+                ],
+            )
+            statusItem.setExpanded(True)
+            statusItem.setFirstColumnSpanned(True)
+            self.__statusItems[status] = statusItem
 
+        # 2. determine and create the category item
+        try:
+            categoryItem = self.__categoryItems[status][category]
+        except KeyError:
+            # create the category item
+            categoryItem = QTreeWidgetItem(statusItem, [category])
+            categoryItem.setExpanded(True)
+            categoryItem.setFirstColumnSpanned(True)
+            self.__categoryItems[status][category] = categoryItem
+
+        # 3. create the plugin item
         if self.__integratedWidget:
             entryFormat = "<b>{0}</b> - Version: <i>{1}</i><br/>{2}"
-            itm = QTreeWidgetItem(parent)
+            itm = QTreeWidgetItem(categoryItem)
             itm.setFirstColumnSpanned(True)
             label = QLabel(entryFormat.format(name, version, short))
             self.repositoryList.setItemWidget(itm, 0, label)
         else:
-            itm = QTreeWidgetItem(parent, [name, version, short])
+            itm = QTreeWidgetItem(categoryItem, [name, version, short])
 
         itm.setData(0, PluginRepositoryWidget.UrlRole, url)
         itm.setData(0, PluginRepositoryWidget.FilenameRole, filename)
@@ -791,22 +837,22 @@
 
         iconColumn = 0 if self.__integratedWidget else 1
         updateStatus = self.__updateStatus(filename, version)
-        if updateStatus == PluginRepositoryWidget.PluginStatusUpToDate:
+        if updateStatus == PluginStatus.UpToDate:
             itm.setIcon(iconColumn, EricPixmapCache.getIcon("empty"))
             itm.setToolTip(iconColumn, self.tr("up-to-date"))
-        elif updateStatus == PluginRepositoryWidget.PluginStatusNew:
+        elif updateStatus == PluginStatus.New:
             itm.setIcon(iconColumn, EricPixmapCache.getIcon("download"))
             itm.setToolTip(iconColumn, self.tr("new download available"))
             self.__newItems += 1
-        elif updateStatus == PluginRepositoryWidget.PluginStatusLocalUpdate:
+        elif updateStatus == PluginStatus.LocalUpdate:
             itm.setIcon(iconColumn, EricPixmapCache.getIcon("updateLocal"))
             itm.setToolTip(iconColumn, self.tr("update installable"))
             self.__updateLocalItems += 1
-        elif updateStatus == PluginRepositoryWidget.PluginStatusRemoteUpdate:
+        elif updateStatus == PluginStatus.RemoteUpdate:
             itm.setIcon(iconColumn, EricPixmapCache.getIcon("updateRemote"))
             itm.setToolTip(iconColumn, self.tr("updated download available"))
             self.__updateRemoteItems += 1
-        elif updateStatus == PluginRepositoryWidget.PluginStatusError:
+        elif updateStatus == PluginStatus.Error:
             itm.setIcon(iconColumn, EricPixmapCache.getIcon("warning"))
             itm.setToolTip(iconColumn, self.tr("error determining status"))
 
@@ -814,11 +860,13 @@
         """
         Private method to check the given archive update status.
 
-        @param filename data for the filename field (string)
-        @param version data for the version field (string)
-        @return plug-in update status (integer, one of PluginStatusNew,
-            PluginStatusUpToDate, PluginStatusLocalUpdate,
-            PluginStatusRemoteUpdate)
+        @param filename data for the filename field
+        @type str
+        @param version data for the version field
+        @type str
+        @return plug-in update status
+        @rtype int (one of PluginStatusNew, PluginStatusUpToDate,
+            PluginStatusLocalUpdate, PluginStatusRemoteUpdate)
         """
         archive = os.path.join(Preferences.getPluginManager("DownloadPath"), filename)
 
@@ -830,23 +878,23 @@
             pluginName = filename.rsplit("-", 1)[0]
             pluginDetails = self.__pluginManager.getPluginDetails(pluginName)
             if pluginDetails is None or pluginDetails["moduleName"] != pluginName:
-                return PluginRepositoryWidget.PluginStatusNew
+                return PluginStatus.New
             if pluginDetails["error"]:
-                return PluginRepositoryWidget.PluginStatusError
+                return PluginStatus.Error
             pluginVersionTuple = Globals.versionToTuple(pluginDetails["version"])[:3]
             versionTuple = Globals.versionToTuple(version)[:3]
             if pluginVersionTuple < versionTuple:
-                return PluginRepositoryWidget.PluginStatusRemoteUpdate
+                return PluginStatus.RemoteUpdate
             else:
-                return PluginRepositoryWidget.PluginStatusUpToDate
+                return PluginStatus.UpToDate
 
         # check, if the archive exists
         if not os.path.exists(archive):
-            return PluginRepositoryWidget.PluginStatusRemoteUpdate
+            return PluginStatus.RemoteUpdate
 
         # check, if the archive is a valid zip file
         if not zipfile.is_zipfile(archive):
-            return PluginRepositoryWidget.PluginStatusRemoteUpdate
+            return PluginStatus.RemoteUpdate
 
         zipFile = zipfile.ZipFile(archive, "r")
         try:
@@ -860,23 +908,25 @@
             pluginName = filename.rsplit("-", 1)[0]
             pluginDetails = self.__pluginManager.getPluginDetails(pluginName)
             if pluginDetails is None:
-                return PluginRepositoryWidget.PluginStatusLocalUpdate
+                return PluginStatus.LocalUpdate
             if (
                 Globals.versionToTuple(pluginDetails["version"])[:3]
                 < Globals.versionToTuple(version)[:3]
             ):
-                return PluginRepositoryWidget.PluginStatusLocalUpdate
+                return PluginStatus.LocalUpdate
             else:
-                return PluginRepositoryWidget.PluginStatusUpToDate
+                return PluginStatus.UpToDate
         else:
-            return PluginRepositoryWidget.PluginStatusRemoteUpdate
+            return PluginStatus.RemoteUpdate
 
     def __sslErrors(self, reply, errors):
         """
         Private slot to handle SSL errors.
 
-        @param reply reference to the reply object (QNetworkReply)
-        @param errors list of SSL errors (list of QSslError)
+        @param reply reference to the reply object
+        @type QNetworkReply
+        @param errors list of SSL errors
+        @type list of QSslError
         """
         ignored = self.__sslErrorHandler.sslErrorsReply(reply, errors)[0]
         if ignored == EricSslErrorState.NOT_IGNORED:
@@ -886,7 +936,8 @@
         """
         Public method to get the list of recently downloaded plugin files.
 
-        @return list of plugin filenames (list of strings)
+        @return list of plugin filenames
+        @rtype list of str
         """
         return self.__pluginsDownloaded
 
@@ -896,7 +947,8 @@
         Private slot to set the read only status of the repository URL line
         edit.
 
-        @param checked state of the push button (boolean)
+        @param checked state of the push button
+        @type bool
         """
         self.repositoryUrlEdit.setReadOnly(not checked)
 
@@ -944,7 +996,8 @@
         """
         Private method to check, if there are any hidden plug-ins.
 
-        @return flag indicating the presence of hidden plug-ins (boolean)
+        @return flag indicating the presence of hidden plug-ins
+        @rtype bool
         """
         return bool(self.__hiddenPlugins)
 
@@ -953,7 +1006,7 @@
         Private method to store the list of hidden plug-ins to the settings.
 
         @param hideList list of plug-ins to add to the list of hidden ones
-            (list of string)
+        @type list of str
         """
         if hideList:
             self.__hiddenPlugins.extend(
@@ -1010,7 +1063,8 @@
         """
         Public method to get the list of recently downloaded plugin files.
 
-        @return list of plugin filenames (list of strings)
+        @return list of plugin filenames
+        @rtype list of str
         """
         return self.cw.getDownloadedPlugins()
 
@@ -1024,7 +1078,8 @@
         """
         Constructor
 
-        @param parent reference to the parent widget (QWidget)
+        @param parent reference to the parent widget
+        @type QWidget
         """
         super().__init__(parent)
         self.cw = PluginRepositoryWidget(None, parent=self)
@@ -1076,19 +1131,37 @@
     pluginsRegister = []  # list of plug-ins contained in the repository
 
     def registerPlugin(
-        name, short, description, url, author, version, filename, status  # noqa: U100
+        name,  # noqa: U100
+        short,  # noqa: U100
+        description,  # noqa: U100
+        url,
+        author,  # noqa: U100
+        version,  # noqa: U100
+        filename,  # noqa: U100
+        status,  # noqa: U100
+        category,  # noqa: U100
     ):
         """
         Method to register a plug-in's data.
 
-        @param name data for the name field (string)
-        @param short data for the short field (string)
-        @param description data for the description field (list of strings)
-        @param url data for the url field (string)
-        @param author data for the author field (string)
-        @param version data for the version field (string)
-        @param filename data for the filename field (string)
-        @param status status of the plugin (string [stable, unstable, unknown])
+        @param name data for the name field
+        @type str
+        @param short data for the short field
+        @type str
+        @param description data for the description field
+        @type list of str
+        @param url data for the url field
+        @type str
+        @param author data for the author field
+        @type str
+        @param version data for the version field
+        @type str
+        @param filename data for the filename field
+        @type str
+        @param status status of the plugin (one of stable, unstable, unknown)
+        @type str
+        @param category category designation of the plugin
+        @type str
         """
         pluginName = os.path.splitext(url.rsplit("/", 1)[1])[0]
         if pluginName not in pluginsRegister:
--- a/src/eric7/PluginManager/PluginRepositoryDialog.ui	Thu Nov 16 13:58:04 2023 +0100
+++ b/src/eric7/PluginManager/PluginRepositoryDialog.ui	Thu Nov 16 15:56:12 2023 +0100
@@ -36,12 +36,6 @@
        <property name="selectionMode">
         <enum>QAbstractItemView::ExtendedSelection</enum>
        </property>
-       <property name="rootIsDecorated">
-        <bool>false</bool>
-       </property>
-       <property name="itemsExpandable">
-        <bool>false</bool>
-       </property>
        <property name="sortingEnabled">
         <bool>true</bool>
        </property>

eric ide

mercurial