Adapted the web browser to Qt 6.8. eric7

Wed, 18 Dec 2024 16:52:16 +0100

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Wed, 18 Dec 2024 16:52:16 +0100
branch
eric7
changeset 11102
ceabb30155b8
parent 11101
33079db9e5ba
child 11103
382e5c9a43f0

Adapted the web browser to Qt 6.8.

src/eric7/WebBrowser/FeaturePermissions/FeaturePermissionBar.py file | annotate | diff | comparison | revisions
src/eric7/WebBrowser/FeaturePermissions/FeaturePermissionManager.py file | annotate | diff | comparison | revisions
src/eric7/WebBrowser/FeaturePermissions/FeaturePermissionsDialog.py file | annotate | diff | comparison | revisions
src/eric7/WebBrowser/WebBrowserPage.py file | annotate | diff | comparison | revisions
src/eric7/WebBrowser/WebBrowserWindow.py file | annotate | diff | comparison | revisions
src/eric7/icons/breeze-dark/clipboard.svg file | annotate | diff | comparison | revisions
src/eric7/icons/breeze-dark/font.svg file | annotate | diff | comparison | revisions
src/eric7/icons/breeze-light/clipboard.svg file | annotate | diff | comparison | revisions
src/eric7/icons/breeze-light/font.svg file | annotate | diff | comparison | revisions
--- a/src/eric7/WebBrowser/FeaturePermissions/FeaturePermissionBar.py	Wed Dec 18 16:51:10 2024 +0100
+++ b/src/eric7/WebBrowser/FeaturePermissions/FeaturePermissionBar.py	Wed Dec 18 16:52:16 2024 +0100
@@ -20,6 +20,8 @@
 class FeaturePermissionBar(EricAnimatedWidget):
     """
     Class implementing the feature permission bar widget.
+
+    Note: This is not needed for Qt 6.8+.
     """
 
     DefaultHeight = 30
@@ -57,7 +59,9 @@
             QWebEnginePage.Feature.MediaAudioVideoCapture: self.tr(
                 "{0} wants to use your microphone and camera."
             ),
-            QWebEnginePage.Feature.MouseLock: self.tr("{0} wants to lock your mouse."),
+            QWebEnginePage.Feature.MouseLock: self.tr(
+                "{0} wants to lock your mouse."
+            ),
             QWebEnginePage.Feature.DesktopVideoCapture: self.tr(
                 "{0} wants to capture video of your screen."
             ),
@@ -76,7 +80,8 @@
             QWebEnginePage.Feature.MediaAudioVideoCapture: "audio-video",
             QWebEnginePage.Feature.MouseLock: "mouse",
             QWebEnginePage.Feature.DesktopVideoCapture: "desktopVideoCapture",
-            QWebEnginePage.Feature.DesktopAudioVideoCapture: "desktopAudioVideoCapture",
+            QWebEnginePage.Feature.DesktopAudioVideoCapture:
+                "desktopAudioVideoCapture",
             QWebEnginePage.Feature.Notifications: "notification",
         }
 
@@ -93,7 +98,9 @@
         self.__rememberButton.setCheckable(True)
         self.__allowButton = QPushButton(self.tr("Allow"), self)
         self.__denyButton = QPushButton(self.tr("Deny"), self)
-        self.__discardButton = QPushButton(EricPixmapCache.getIcon("close"), "", self)
+        self.__discardButton = QPushButton(
+            EricPixmapCache.getIcon("close"), "", self
+        )
         self.__allowButton.clicked.connect(self.__permissionGranted)
         self.__denyButton.clicked.connect(self.__permissionDenied)
         self.__discardButton.clicked.connect(self.__permissionUnknown)
@@ -135,6 +142,7 @@
         self.__page.loadStarted.disconnect(self.hide)
         super().hide()
 
+    @pyqtSlot()
     def __permissionDenied(self):
         """
         Private slot handling the user pressing the deny button.
@@ -157,6 +165,7 @@
 
         self.hide()
 
+    @pyqtSlot()
     def __permissionGranted(self):
         """
         Private slot handling the user pressing the allow button.
@@ -179,9 +188,10 @@
 
         self.hide()
 
+    @pyqtSlot()
     def __permissionUnknown(self):
         """
-        Private slot handling the user closing the dialog without.
+        Private slot handling the user closing the dialog without a selection.
         """
         if self.__page is None or self.__manager is None:
             return
--- a/src/eric7/WebBrowser/FeaturePermissions/FeaturePermissionManager.py	Wed Dec 18 16:51:10 2024 +0100
+++ b/src/eric7/WebBrowser/FeaturePermissions/FeaturePermissionManager.py	Wed Dec 18 16:52:16 2024 +0100
@@ -18,6 +18,8 @@
 class FeaturePermissionManager(QObject):
     """
     Class implementing the feature permission manager object.
+
+    Note: This is not needed for Qt 6.8+.
     """
 
     SettingsKeyFormat = "WebBrowser/FeaturePermissions/{0}"
--- a/src/eric7/WebBrowser/FeaturePermissions/FeaturePermissionsDialog.py	Wed Dec 18 16:51:10 2024 +0100
+++ b/src/eric7/WebBrowser/FeaturePermissions/FeaturePermissionsDialog.py	Wed Dec 18 16:52:16 2024 +0100
@@ -7,11 +7,19 @@
 Module implementing the feature permission dialog.
 """
 
+import contextlib
+
 from PyQt6.QtCore import Qt, pyqtSlot
-from PyQt6.QtWebEngineCore import QWebEnginePage
 from PyQt6.QtWidgets import QAbstractItemView, QDialog, QTreeWidget, QTreeWidgetItem
+try:
+    # Qt 6.8+
+    from PyQt6.QtWebEngineCore import QWebEnginePermission
+except ImportError:
+    # Qt <6.8
+    from PyQt6.QtWebEngineCore import QWebEnginePage
 
 from eric7.EricGui import EricPixmapCache
+from eric7.SystemUtilities import QtUtilities
 
 from .Ui_FeaturePermissionsDialog import Ui_FeaturePermissionsDialog
 
@@ -26,8 +34,8 @@
         Constructor
 
         @param featurePermissions dictionary with remembered feature
-            permissions
-        @type dict of dict of list
+            permissions (Qt <6.8) or a list of permission objects (Qt 6.8+)
+        @type dict of dict of list or list of QWebEnginePermission
         @param parent reference to the parent widget
         @type QWidget
         """
@@ -166,6 +174,36 @@
             self.tr("Desktop Audio && Video"),
         )
 
+        if QtUtilities.qVersionTuple() >= (6, 8, 0):
+            # Qt 6.8+
+            self.clipboardList = QTreeWidget()
+            self.clipboardList.setAlternatingRowColors(True)
+            self.clipboardList.setSelectionMode(QAbstractItemView.SelectionMode.ExtendedSelection)
+            self.clipboardList.setRootIsDecorated(False)
+            self.clipboardList.setItemsExpandable(False)
+            self.clipboardList.setAllColumnsShowFocus(True)
+            self.clipboardList.setObjectName("camList")
+            self.clipboardList.setSortingEnabled(True)
+            self.clipboardList.headerItem().setText(0, self.tr("Host"))
+            self.clipboardList.headerItem().setText(1, self.tr("Permission"))
+            self.tabWidget.addTab(
+                self.clipboardList, EricPixmapCache.getIcon("clipboard"), self.tr("Clipboard")
+            )
+
+            self.localFontsList = QTreeWidget()
+            self.localFontsList.setAlternatingRowColors(True)
+            self.localFontsList.setSelectionMode(QAbstractItemView.SelectionMode.ExtendedSelection)
+            self.localFontsList.setRootIsDecorated(False)
+            self.localFontsList.setItemsExpandable(False)
+            self.localFontsList.setAllColumnsShowFocus(True)
+            self.localFontsList.setObjectName("camList")
+            self.localFontsList.setSortingEnabled(True)
+            self.localFontsList.headerItem().setText(0, self.tr("Host"))
+            self.localFontsList.headerItem().setText(1, self.tr("Permission"))
+            self.tabWidget.addTab(
+                self.localFontsList, EricPixmapCache.getIcon("font"), self.tr("Local Fonts")
+            )
+
         self.setTabOrder(self.tabWidget, self.notifList)
         self.setTabOrder(self.notifList, self.geoList)
         self.setTabOrder(self.geoList, self.micList)
@@ -174,33 +212,74 @@
         self.setTabOrder(self.micCamList, self.mouseLockList)
         self.setTabOrder(self.mouseLockList, self.deskVidList)
         self.setTabOrder(self.deskVidList, self.deskAudVidList)
-        self.setTabOrder(self.deskAudVidList, self.removeButton)
+        if QtUtilities.qVersionTuple() >= (6, 8, 0):
+            # Qt 6.8+
+            self.setTabOrder(self.deskAudVidList, self.clipboardList)
+            self.setTabOrder(self.clipboardList, self.localFontsList)
+            self.setTabOrder(self.localFontsList, self.removeButton)
+        else:
+            self.setTabOrder(self.deskAudVidList, self.removeButton)
         self.setTabOrder(self.removeButton, self.removeAllButton)
 
-        self.__permissionStrings = {
-            QWebEnginePage.PermissionPolicy.PermissionGrantedByUser: self.tr("Allow"),
-            QWebEnginePage.PermissionPolicy.PermissionDeniedByUser: self.tr("Deny"),
-        }
+        if QtUtilities.qVersionTuple() >= (6, 8, 0):
+            # Qt 6.8+
+            self.__permissionStrings = {
+                QWebEnginePermission.State.Granted: self.tr("Allow"),
+                QWebEnginePermission.State.Denied: self.tr("Deny"),
+                QWebEnginePermission.State.Ask: self.tr("Always Ask"),
+                QWebEnginePermission.State.Invalid: self.tr("Invalid"),
+            }
 
-        self.__permissionsLists = {
-            QWebEnginePage.Feature.Geolocation: self.geoList,
-            QWebEnginePage.Feature.MediaAudioCapture: self.micList,
-            QWebEnginePage.Feature.MediaVideoCapture: self.camList,
-            QWebEnginePage.Feature.MediaAudioVideoCapture: self.micCamList,
-            QWebEnginePage.Feature.MouseLock: self.mouseLockList,
-            QWebEnginePage.Feature.DesktopVideoCapture: self.deskVidList,
-            QWebEnginePage.Feature.DesktopAudioVideoCapture: self.deskAudVidList,
-            QWebEnginePage.Feature.Notifications: self.notifList,
-        }
+            self.__permissionsLists = {
+                QWebEnginePermission.PermissionType.Geolocation: self.geoList,
+                QWebEnginePermission.PermissionType.MediaAudioCapture: self.micList,
+                QWebEnginePermission.PermissionType.MediaVideoCapture: self.camList,
+                QWebEnginePermission.PermissionType.MediaAudioVideoCapture: self.micCamList,
+                QWebEnginePermission.PermissionType.MouseLock: self.mouseLockList,
+                QWebEnginePermission.PermissionType.DesktopVideoCapture: self.deskVidList,
+                QWebEnginePermission.PermissionType.DesktopAudioVideoCapture: self.deskAudVidList,
+                QWebEnginePermission.PermissionType.Notifications: self.notifList,
+                QWebEnginePermission.PermissionType.ClipboardReadWrite: self.clipboardList,
+                QWebEnginePermission.PermissionType.LocalFontsAccess: self.localFontsList,
+            }
 
-        for feature, permissionsList in self.__permissionsLists.items():
-            for permission in featurePermissions[feature]:
-                for host in featurePermissions[feature][permission]:
+            for permission in featurePermissions:
+                with contextlib.suppress(KeyError):
+                    permissionsList = self.__permissionsLists[permission.permissionType()]
                     itm = QTreeWidgetItem(
-                        permissionsList, [host, self.__permissionStrings[permission]]
+                        permissionsList, [
+                            permission.origin().toString(),
+                            self.__permissionStrings[permission.state()],
+                        ]
                     )
                     itm.setData(0, Qt.ItemDataRole.UserRole, permission)
+        else:
+            # Qt <6.8
+            self.__permissionStrings = {
+                QWebEnginePage.PermissionPolicy.PermissionGrantedByUser: self.tr("Allow"),
+                QWebEnginePage.PermissionPolicy.PermissionDeniedByUser: self.tr("Deny"),
+            }
 
+            self.__permissionsLists = {
+                QWebEnginePage.Feature.Geolocation: self.geoList,
+                QWebEnginePage.Feature.MediaAudioCapture: self.micList,
+                QWebEnginePage.Feature.MediaVideoCapture: self.camList,
+                QWebEnginePage.Feature.MediaAudioVideoCapture: self.micCamList,
+                QWebEnginePage.Feature.MouseLock: self.mouseLockList,
+                QWebEnginePage.Feature.DesktopVideoCapture: self.deskVidList,
+                QWebEnginePage.Feature.DesktopAudioVideoCapture: self.deskAudVidList,
+                QWebEnginePage.Feature.Notifications: self.notifList,
+            }
+
+            for feature, permissionsList in self.__permissionsLists.items():
+                for permission in featurePermissions[feature]:
+                    for host in featurePermissions[feature][permission]:
+                        itm = QTreeWidgetItem(
+                            permissionsList, [host, self.__permissionStrings[permission]]
+                        )
+                        itm.setData(0, Qt.ItemDataRole.UserRole, permission)
+
+        self.__removedPermissions = []
         self.__previousCurrent = -1
         self.tabWidget.currentChanged.connect(self.__currentTabChanged)
         self.tabWidget.setCurrentIndex(0)
@@ -247,6 +326,7 @@
         for itm in currentList.selectedItems():
             row = currentList.indexOfTopLevelItem(itm)
             itm = currentList.takeTopLevelItem(row)
+            self.__removedPermissions.append(itm.data(0, Qt.ItemDataRole.UserRole))
             del itm
         self.__updateButtons()
 
@@ -258,6 +338,7 @@
         currentList = self.tabWidget.currentWidget()
         while currentList.topLevelItemCount() > 0:
             itm = currentList.takeTopLevelItem(0)  # __IGNORE_WARNING__
+            self.__removedPermissions.append(itm.data(0, Qt.ItemDataRole.UserRole))
             del itm
         self.__updateButtons()
 
@@ -268,6 +349,7 @@
         @return new feature permission settings
         @rtype dict of dict of list
         """
+        # Qt <6.8
         featurePermissions = {}
         for feature, permissionsList in self.__permissionsLists.items():
             featurePermissions[feature] = {
@@ -281,3 +363,11 @@
                 featurePermissions[feature][permission].append(host)
 
         return featurePermissions
+
+    def persistChanges(self):
+        """
+        Public method to persist the removed permissions.
+        """
+        # Qt 6.8+
+        for permission in self.__removedPermissions:
+            permission.reset()
--- a/src/eric7/WebBrowser/WebBrowserPage.py	Wed Dec 18 16:51:10 2024 +0100
+++ b/src/eric7/WebBrowser/WebBrowserPage.py	Wed Dec 18 16:52:16 2024 +0100
@@ -8,7 +8,10 @@
 Module implementing the helpbrowser using QWebView.
 """
 
+import contextlib
+
 from PyQt6.QtCore import (
+    QCoreApplication,
     QEventLoop,
     QPoint,
     QTimer,
@@ -24,6 +27,7 @@
 from eric7 import EricUtilities, Preferences
 from eric7.EricWidgets import EricMessageBox
 from eric7.WebBrowser.WebBrowserWindow import WebBrowserWindow
+from eric7.SystemUtilities import QtUtilities
 
 from .JavaScript.ExternalJsObject import ExternalJsObject
 from .Tools import Scripts
@@ -38,6 +42,9 @@
 except ImportError:
     SSL_AVAILABLE = False
 
+with contextlib.suppress(ImportError):
+    from PyQt6.QtWebEngineCore import QWebEnginePermission
+
 
 class WebBrowserPage(QWebEnginePage):
     """
@@ -66,6 +73,52 @@
 
     sslConfigurationChanged = pyqtSignal()
 
+    if QtUtilities.qVersionTuple() >= (6, 8, 0):
+        PermissionTypeQuestions = {
+            QWebEnginePermission.PermissionType.Geolocation: QCoreApplication.translate(
+                "WebBrowserPage",
+                "<p>Allow <b>{0}</b> to access your location information?</p>",
+            ),
+            QWebEnginePermission.PermissionType.MediaAudioCapture: QCoreApplication.translate(
+                "WebBrowserPage",
+                "<p>Allow <b>{0}</b> to access your microphone?</p>",
+            ),
+            QWebEnginePermission.PermissionType.MediaVideoCapture: QCoreApplication.translate(
+                "WebBrowserPage",
+                "<p>Allow <b>{0}</b> to access your webcam?</p>",
+            ),
+            QWebEnginePermission.PermissionType.MediaAudioVideoCapture: QCoreApplication.translate(
+                "WebBrowserPage",
+                "<p>Allow <b>{0}</b> to access your microphone and webcam?</p>",
+            ),
+            QWebEnginePermission.PermissionType.MouseLock: QCoreApplication.translate(
+                "WebBrowserPage",
+                "<p>Allow <b>{0}</b> to lock your mouse cursor?</p>",
+            ),
+            QWebEnginePermission.PermissionType.DesktopVideoCapture: QCoreApplication.translate(
+                "WebBrowserPage",
+                "<p>Allow <b>{0}</b> to capture video of your desktop?</p>",
+            ),
+            QWebEnginePermission.PermissionType.DesktopAudioVideoCapture: QCoreApplication.translate(
+                "WebBrowserPage",
+                "<p>Allow <b>{0}</b> to capture audio and video of your desktop?</p>",
+            ),
+            QWebEnginePermission.PermissionType.Notifications: QCoreApplication.translate(
+                "WebBrowserPage",
+                "<p>Allow <b>{0}</b> to show notifications on your desktop?</p>",
+            ),
+            QWebEnginePermission.PermissionType.ClipboardReadWrite: QCoreApplication.translate(
+                "WebBrowserPage",
+                "<p>Allow <b>{0}</b> to read from and write to the clipboard?</p>",
+            ),
+            QWebEnginePermission.PermissionType.LocalFontsAccess: QCoreApplication.translate(
+                "WebBrowserPage",
+                "<p>Allow <b>{0}</b> to access fonts stored on this machine?</p>",
+            ),
+        }
+    else:
+        PermissionTypeQuestions = {}
+
     def __init__(self, view, parent=None):
         """
         Constructor
@@ -82,7 +135,12 @@
 
         self.__view = view
 
-        self.featurePermissionRequested.connect(self.__featurePermissionRequested)
+        try:
+            # Qt 6.8+
+            self.permissionRequested.connect(self.__permissionRequested)
+        except AttributeError:
+            # Qt <6.8
+            self.featurePermissionRequested.connect(self.__featurePermissionRequested)
         self.authenticationRequired.connect(
             lambda url, auth: WebBrowserWindow.networkManager().authentication(
                 url, auth, self
@@ -303,14 +361,35 @@
         @param feature requested feature
         @type QWebEnginePage.Feature
         """
+        # Qt <6.8
         manager = WebBrowserWindow.featurePermissionManager()
         manager.requestFeaturePermission(self, url, feature)
 
+    def __permissionRequested(self, permission):
+        """
+        Private slot handling a permission request.
+
+        @param permission reference to the permission request object
+        @type QWebEnginePermission
+        """
+        # Qt 6.8+
+        question = self.PermissionTypeQuestions.get(permission.permissionType())
+        if question and EricMessageBox.yesNo(
+            self.view(),
+            self.tr("Permission Request"),
+            question.format(permission.origin().host()),
+            yesDefault=True,
+        ):
+            permission.grant()
+        else:
+            permission.deny()
+        
+
     def execJavaScript(
         self, script, worldId=QWebEngineScript.ScriptWorldId.MainWorld, timeout=500
     ):
         """
-        Public method to execute a JavaScript function synchroneously.
+        Public method to execute a JavaScript function synchronously.
 
         @param script JavaScript script source to be executed
         @type str
--- a/src/eric7/WebBrowser/WebBrowserWindow.py	Wed Dec 18 16:51:10 2024 +0100
+++ b/src/eric7/WebBrowser/WebBrowserWindow.py	Wed Dec 18 16:52:16 2024 +0100
@@ -4294,7 +4294,16 @@
         """
         Private slot to show the feature permission dialog.
         """
-        self.featurePermissionManager().showFeaturePermissionsDialog(self)
+        if QtUtilities.qVersionTuple() >= (6, 8, 0):
+            # Qt 6.8+
+            from .FeaturePermissions.FeaturePermissionsDialog import FeaturePermissionsDialog
+
+            dlg = FeaturePermissionsDialog(self.webProfile().listAllPermissions(), parent=self)
+            if dlg.exec() == QDialog.DialogCode.Accepted:
+                dlg.persistChanges()
+        else:
+            # Qt <6.8
+            self.featurePermissionManager().showFeaturePermissionsDialog(self)
 
     @pyqtSlot()
     def __showZoomValuesDialog(self):
@@ -5392,9 +5401,9 @@
 
         if cls._webProfile is None:
             if private:
-                cls._webProfile = QWebEngineProfile()
+                cls._webProfile = QWebEngineProfile.defaultProfile()
             else:
-                cls._webProfile = QWebEngineProfile.defaultProfile()
+                cls._webProfile = QWebEngineProfile("eric7")
             cls._webProfile.downloadRequested.connect(cls.downloadRequested)
 
             # add the default user agent string
@@ -5439,6 +5448,9 @@
                     Preferences.getWebBrowser("SpellCheckLanguages")
                 )
 
+            # TODO: setPersistentPermissionPolicy for Qt 6.8+
+            #       setting key: "NoPersistentPermissions" for non-private only
+
             # configure notifications
             cls._webProfile.setNotificationPresenter(cls.__showWebNotification)
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/eric7/icons/breeze-dark/clipboard.svg	Wed Dec 18 16:52:16 2024 +0100
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg version="1.1" viewBox="0 0 22 22" xmlns="http://www.w3.org/2000/svg"><defs><style type="text/css">.ColorScheme-Text {
+        color:#eff0f1;
+      }</style></defs><path class="ColorScheme-Text" d="m5.8571 1v2.5h-3.8571v17.5h18v-17.5h-3.8571v-2.5zm-2.5714 3.75h1.2857v2.5h12.857v-2.5h1.2857v15h-15.429zm2.5714 3.75v1.25h10.286v-1.25zm0 3.75v1.25h7.7143v-1.25zm0 3.75v1.25h3.8571v-1.25z" color="#eff0f1" fill="currentColor"/></svg>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/eric7/icons/breeze-dark/font.svg	Wed Dec 18 16:52:16 2024 +0100
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   id="svg6"
+   version="1.1"
+   viewBox="0 0 22 22"
+   sodipodi:docname="font.svg"
+   inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview6"
+     pagecolor="#ffffff"
+     bordercolor="#000000"
+     borderopacity="0.25"
+     inkscape:showpageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:deskcolor="#d1d1d1"
+     showgrid="false"
+     inkscape:zoom="46.681818"
+     inkscape:cx="11.010711"
+     inkscape:cy="11.182084"
+     inkscape:window-width="2580"
+     inkscape:window-height="1271"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="svg6" />
+  <defs
+     id="defs3051">
+    <style
+       id="current-color-scheme"
+       type="text/css">.ColorScheme-Text { color: #fcfcfc; } </style>
+  </defs>
+  <path
+     id="path4"
+     class="ColorScheme-Text"
+     d="M 9.7285153,1 5.8616536,14.705357 5.7180989,15.285714 4,21 H 5.9345703 L 7.8304036,14.660714 H 14.169597 L 16.06543,21 H 18 L 16.281901,15.285714 16.138347,14.705357 12.271485,1 H 9.9791667 Z m 1.2897137,2.7678571 2.542968,9.0624999 H 8.4388021 Z"
+     fill="currentColor"
+     style="stroke-width:1.29099" />
+</svg>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/eric7/icons/breeze-light/clipboard.svg	Wed Dec 18 16:52:16 2024 +0100
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg version="1.1" viewBox="0 0 22 22" xmlns="http://www.w3.org/2000/svg"><defs><style type="text/css">.ColorScheme-Text {
+        color:#eff0f1;
+      }</style></defs><path class="ColorScheme-Text" d="m5.8571 1v2.5h-3.8571v17.5h18v-17.5h-3.8571v-2.5zm-2.5714 3.75h1.2857v2.5h12.857v-2.5h1.2857v15h-15.429zm2.5714 3.75v1.25h10.286v-1.25zm0 3.75v1.25h7.7143v-1.25zm0 3.75v1.25h3.8571v-1.25z" color="#eff0f1" fill="#232629"/></svg>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/eric7/icons/breeze-light/font.svg	Wed Dec 18 16:52:16 2024 +0100
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   id="svg6"
+   version="1.1"
+   viewBox="0 0 22 22"
+   sodipodi:docname="font.svg"
+   inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg">
+  <sodipodi:namedview
+     id="namedview6"
+     pagecolor="#ffffff"
+     bordercolor="#000000"
+     borderopacity="0.25"
+     inkscape:showpageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:deskcolor="#d1d1d1"
+     showgrid="false"
+     inkscape:zoom="46.681818"
+     inkscape:cx="11.010711"
+     inkscape:cy="11.117819"
+     inkscape:window-width="2580"
+     inkscape:window-height="1315"
+     inkscape:window-x="0"
+     inkscape:window-y="0"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="svg6" />
+  <defs
+     id="defs3051">
+    <style
+       id="current-color-scheme"
+       type="text/css">.ColorScheme-Text {
+        color:#232629;
+      }</style>
+  </defs>
+  <path
+     id="path4"
+     class="ColorScheme-Text"
+     d="M 9.365235,1 4.3935547,14.705357 4.2089843,15.285714 2,21 H 4.4873047 L 6.9248046,14.660714 H 15.075195 L 17.512696,21 H 20 L 17.791016,15.285714 17.606445,14.705357 12.634767,1 H 9.687501 Z m 1.658203,2.7678571 3.269531,9.0624999 H 7.707031 Z"
+     fill="currentColor"
+     style="stroke-width:1.46385" />
+</svg>

eric ide

mercurial