src/eric7/WebBrowser/TabManager/TabManagerWidget.py

branch
eric7
changeset 9221
bf71ee032bb4
parent 9209
b99e7fd55fd3
child 9413
80c06d472826
--- a/src/eric7/WebBrowser/TabManager/TabManagerWidget.py	Wed Jul 13 11:16:20 2022 +0200
+++ b/src/eric7/WebBrowser/TabManager/TabManagerWidget.py	Wed Jul 13 14:55:47 2022 +0200
@@ -18,7 +18,12 @@
 from PyQt6.QtCore import pyqtSignal, pyqtSlot, Qt, QPoint, QTimer, QRect
 from PyQt6.QtGui import QAction
 from PyQt6.QtWidgets import (
-    QWidget, QVBoxLayout, QTreeWidget, QTreeWidgetItem, QMenu, QStyle
+    QWidget,
+    QVBoxLayout,
+    QTreeWidget,
+    QTreeWidgetItem,
+    QMenu,
+    QStyle,
 )
 
 from EricNetwork import EricTldExtractor, EricNetworkUtilities
@@ -34,24 +39,25 @@
 class TabManagerWidget(QWidget):
     """
     Class implementing a window for managing the web browser tabs.
-    
+
     @signal groupTypeChanged(int) emitted when the 'Group By' value was changed
     """
+
     GroupByWindow = 0
     GroupByDomain = 1
     GroupByHost = 2
-    
+
     WebBrowserRole = Qt.ItemDataRole.UserRole + 1
     WebWindowRole = Qt.ItemDataRole.UserRole + 2
-    
+
     groupTypeChanged = pyqtSignal(int)
-    
+
     _tldExtractor = None
-    
+
     def __init__(self, mainWindow, parent=None, defaultWidget=False):
         """
         Constructor
-        
+
         @param mainWindow reference to the main window
         @type WebBrowserWindow
         @param parent reference to the parent widget
@@ -61,103 +67,101 @@
         """
         super().__init__(parent)
         self.setWindowFlags(Qt.WindowType.Window)
-        
+
         self.__layout = QVBoxLayout(self)
         self.__layout.setContentsMargins(0, 0, 0, 0)
         self.__tree = QTreeWidget(self)
         self.__tree.setHeaderHidden(True)
         self.__tree.setExpandsOnDoubleClick(False)
-        self.__tree.setContextMenuPolicy(
-            Qt.ContextMenuPolicy.CustomContextMenu)
+        self.__tree.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
         self.__layout.addWidget(self.__tree)
-        
+
         self.setWindowTitle(self.tr("Tab Manager"))
-        
+
         self.__mw = mainWindow
         self.__page = None
-        
+
         self.__isRefreshing = False
         self.__refreshBlocked = False
         self.__waitForRefresh = False
         self.__isDefaultWidget = defaultWidget
         self.__groupType = Preferences.getWebBrowser("TabManagerGroupByType")
-        
+
         if TabManagerWidget._tldExtractor is None:
             TabManagerWidget._tldExtractor = EricTldExtractor.instance()
-            TabManagerWidget._tldExtractor.setDataSearchPaths([
-                os.path.join(Utilities.getConfigDir(), "web_browser")])
-        
+            TabManagerWidget._tldExtractor.setDataSearchPaths(
+                [os.path.join(Utilities.getConfigDir(), "web_browser")]
+            )
+
         self.__tree.itemDoubleClicked.connect(self.__itemDoubleClicked)
         self.__tree.customContextMenuRequested.connect(
-            self.__customContextMenuRequested)
-        
+            self.__customContextMenuRequested
+        )
+
         self.resize(400, 600)
-    
+
     def closeSelectedBrowsers(self, browsersDict):
         """
         Public method to close the selected browsers.
-        
+
         @param browsersDict dictionary containing the browsers per window
         @type dict with WebBrowserWindow as key and list of WebBrowserView
             as value
         """
         if not browsersDict:
             return
-        
+
         for mainWindow in browsersDict:
             tabWidget = mainWindow.tabWidget()
             for browser in browsersDict[mainWindow]:
                 tabWidget.closeBrowserAt(tabWidget.indexOf(browser))
-    
+
     def bookmarkSelectedBrowsers(self, browsersDict):
         """
         Public method to bookmark the selected browsers.
-        
+
         @param browsersDict dictionary containing the browsers per window
         @type dict with WebBrowserWindow as key and list of WebBrowserView
             as value
         """
         if not browsersDict:
             return
-        
+
         from ..Bookmarks.BookmarkNode import BookmarkNode
         from ..Bookmarks.AddBookmarkDialog import AddBookmarkDialog
-        
+
         dlg = AddBookmarkDialog()
         dlg.setFolder(True)
         dlg.setTitle(self.tr("Saved Tabs"))
         dlg.exec()
-        
+
         folder = dlg.addedNode()
         if folder is None:
             return
-        
+
         for mainWin in browsersDict:
             for browser in browsersDict[mainWin]:
-                if (
-                    not browser.url().isEmpty() and
-                    browser.url().scheme() != "eric"
-                ):
+                if not browser.url().isEmpty() and browser.url().scheme() != "eric":
                     bookmark = BookmarkNode(BookmarkNode.Bookmark)
                     bookmark.url = bytes(browser.url().toEncoded()).decode()
                     bookmark.title = browser.title()
-                    
+
                     self.__mw.bookmarksManager().addBookmark(folder, bookmark)
-    
+
     def __setGroupType(self, groupType):
         """
         Private method to set the 'Group By' type.
-        
+
         @param groupType 'Group By' type to be set
         @type int (0 - 2)
         """
         self.__groupType = groupType
         Preferences.setWebBrowser("TabManagerGroupByType", groupType)
-    
+
     def domainFromUrl(self, url, useHostName=False):
         """
         Public method to extract the domain from an URL.
-        
+
         @param url URL to extract the domain from
         @type QUrl
         @param useHostName flag indicating to use the host name
@@ -167,67 +171,65 @@
         """
         appendStr = ":"
         urlString = url.toString()
-        
+
         if url.scheme() == "file":
             return self.tr("Local File System:")
         elif url.scheme() == "eric" or not urlString:
             return self.tr("eric Web Browser:")
         elif url.scheme() == "ftp":
             appendStr = self.tr(" [FTP]:")
-        
+
         host = url.host()
         if not host:
             return urlString + appendStr
-        
+
         if useHostName or EricNetworkUtilities.isValidAddress(host):
             if host.lower().startswith("www."):
                 host = host[4:]
         else:
-            registeredDomain = (
-                TabManagerWidget._tldExtractor.registrableDomain(host)
-            )
+            registeredDomain = TabManagerWidget._tldExtractor.registrableDomain(host)
             if registeredDomain:
                 host = registeredDomain
-        
+
         return host + appendStr
-    
+
     def delayedRefreshTree(self, page=None):
         """
         Public slot to do a delyed refresh of the tree.
-        
+
         @param page reference to the web page
         @type WebBrowserPage
         """
         if self.__refreshBlocked or self.__waitForRefresh:
             return
-        
+
         if self.__isRefreshing and not page:
             return
-        
+
         self.__page = page
         self.__waitForRefresh = True
         QTimer.singleShot(50, self.__refreshTree)
-    
+
     def changeGroupType(self, act):
         """
         Public slot to change the 'Group By' type.
-        
+
         @param act reference to the action that was triggered
         @type QAction
         """
         if act is None:
             return
-        
+
         groupType = act.data()
         if self.__groupType != groupType:
             self.__setGroupType(groupType)
             self.delayedRefreshTree()
             self.groupTypeChanged.emit(self.__groupType)
-    
+
     def __createEmptyItem(self, parent=None, addToTree=True):
         """
         Private method to create an empty tree item.
-        
+
         @param parent reference to the parent item
         @type QTreeWidgetItem or QTreeWidget
         @param addToTree flag indicating to add the item to the tree
@@ -245,32 +247,32 @@
         itm = QTreeWidgetItem(parentItem)
         addFlags = (
             Qt.ItemFlag.ItemIsUserCheckable
-            if parent else
-            (Qt.ItemFlag.ItemIsUserCheckable | Qt.ItemFlag.ItemIsAutoTristate)
+            if parent
+            else (Qt.ItemFlag.ItemIsUserCheckable | Qt.ItemFlag.ItemIsAutoTristate)
         )
         itm.setFlags(itm.flags() | addFlags)
         itm.setCheckState(0, Qt.CheckState.Unchecked)
-        
+
         return itm
-    
+
     def __groupByDomainName(self, useHostName=False):
         """
         Private method to group the tree items by domain name.
-        
+
         @param useHostName flag indicating to use the host name
         @type bool
         """
         windows = self.__mw.mainWindows()
-        
+
         tabsGroupedByDomain = {}
-        
+
         for mainWin in windows:
             for browser in mainWin.tabWidget().browsers():
                 if self.__page == browser.page():
                     self.__page = None
                     continue
                 domain = self.domainFromUrl(browser.url(), useHostName)
-                
+
                 if domain not in tabsGroupedByDomain:
                     groupItem = self.__createEmptyItem(None, False)
                     groupItem.setText(0, domain)
@@ -280,7 +282,7 @@
                     groupItem.setFont(0, font)
                     tabsGroupedByDomain[domain] = groupItem
                 groupItem = tabsGroupedByDomain[domain]
-                
+
                 tabItem = self.__createEmptyItem(groupItem)
                 if browser == mainWin.tabWidget().currentBrowser():
                     font = tabItem.font(0)
@@ -292,22 +294,22 @@
                     tabItem.setIcon(0, UI.PixmapCache.getIcon("loading"))
                 tabItem.setText(0, browser.title())
                 tabItem.setToolTip(0, browser.title())
-                
+
                 tabItem.setData(0, TabManagerWidget.WebBrowserRole, browser)
                 tabItem.setData(0, TabManagerWidget.WebWindowRole, mainWin)
-                
+
                 self.__makeWebBrowserViewConnections(browser)
-        
+
         self.__tree.insertTopLevelItems(0, tabsGroupedByDomain.values())
-    
+
     def __groupByWindow(self):
         """
         Private method to group the tree items by window.
         """
         windows = self.__mw.mainWindows()
-        
+
         self.__isRefreshing = True
-        
+
         for winCount, mainWin in enumerate(windows, start=1):
             winItem = self.__createEmptyItem()
             winItem.setText(0, self.tr("Window {0}").format(winCount))
@@ -317,12 +319,12 @@
                 font.setBold(True)
                 winItem.setFont(0, font)
             winItem.setData(0, TabManagerWidget.WebWindowRole, mainWin)
-            
+
             for browser in mainWin.tabWidget().browsers():
                 if self.__page == browser.page():
                     self.__page = None
                     continue
-                
+
                 tabItem = self.__createEmptyItem(winItem)
                 if browser == mainWin.tabWidget().currentBrowser():
                     font = tabItem.font(0)
@@ -334,16 +336,16 @@
                     tabItem.setIcon(0, UI.PixmapCache.getIcon("loading"))
                 tabItem.setText(0, browser.title())
                 tabItem.setToolTip(0, browser.title())
-                
+
                 tabItem.setData(0, TabManagerWidget.WebBrowserRole, browser)
                 tabItem.setData(0, TabManagerWidget.WebWindowRole, mainWin)
-                
+
                 self.__makeWebBrowserViewConnections(browser)
-    
+
     def __makeWebBrowserViewConnections(self, view):
         """
         Private method to create the signal connections to the web view.
-        
+
         @param view reference to the web view
         @type WebBrowserView
         """
@@ -352,7 +354,7 @@
             view.loadStarted.connect(self.delayedRefreshTree)
             view.titleChanged.connect(self.delayedRefreshTree)
             view.faviconChanged.connect(self.delayedRefreshTree)
-    
+
     @pyqtSlot()
     def __refreshTree(self):
         """
@@ -360,26 +362,27 @@
         """
         if self.__refreshBlocked:
             return
-        
+
         if self.__isRefreshing and not self.__page:
             return
-        
+
         # store selected items
         selectedBrowsers = []
         for index in range(self.__tree.topLevelItemCount()):
             winItem = self.__tree.topLevelItem(index)
             if winItem.checkState(0) == Qt.CheckState.Unchecked:
                 continue
-            
+
             for row in range(winItem.childCount()):
                 tabItem = winItem.child(row)
                 if tabItem.checkState(0) == Qt.CheckState.Unchecked:
                     continue
                 selectedBrowsers.append(
-                    tabItem.data(0, TabManagerWidget.WebBrowserRole))
-        
+                    tabItem.data(0, TabManagerWidget.WebBrowserRole)
+                )
+
         self.__tree.clear()
-        
+
         if self.__groupType == TabManagerWidget.GroupByHost:
             self.__groupByDomainName(True)
         elif self.__groupType == TabManagerWidget.GroupByDomain:
@@ -388,67 +391,67 @@
             # default is group by window
             self.__setGroupType(TabManagerWidget.GroupByWindow)
             self.__groupByWindow()
-        
+
         # restore selected items
         for index in range(self.__tree.topLevelItemCount()):
             winItem = self.__tree.topLevelItem(index)
-            
+
             for row in range(winItem.childCount()):
                 tabItem = winItem.child(row)
                 if tabItem.data(0, TabManagerWidget.WebBrowserRole) in (
                     selectedBrowsers
                 ):
                     tabItem.setCheckState(0, Qt.CheckState.Checked)
-        
+
         self.__tree.expandAll()
         self.__isRefreshing = False
         self.__waitForRefresh = False
-    
+
     @pyqtSlot()
     def __processActions(self, act):
         """
         Private slot to process the actions.
-        
+
         @param act reference to the action that triggered
         @type QAction
         """
         self.__refreshBlocked = True
-        
+
         selectedBrowsers = collections.defaultdict(list)
-        
+
         command = act.objectName()
-        
+
         for index in range(self.__tree.topLevelItemCount()):
             winItem = self.__tree.topLevelItem(index)
             if winItem.checkState(0) == Qt.CheckState.Unchecked:
                 continue
-            
+
             for row in range(winItem.childCount()):
                 tabItem = winItem.child(row)
                 if tabItem.checkState(0) == Qt.CheckState.Unchecked:
                     continue
-                
+
                 mainWin = tabItem.data(0, TabManagerWidget.WebWindowRole)
                 browser = tabItem.data(0, TabManagerWidget.WebBrowserRole)
-                
+
                 selectedBrowsers[mainWin].append(browser)
-            
+
             winItem.setCheckState(0, Qt.CheckState.Unchecked)
-        
+
         if selectedBrowsers:
             if command == "closeSelection":
                 self.closeSelectedBrowsers(selectedBrowsers)
             elif command == "bookmarkSelection":
                 self.bookmarkSelectedBrowsers(selectedBrowsers)
-        
+
         self.__refreshBlocked = False
         self.delayedRefreshTree()
-    
+
     @pyqtSlot(QTreeWidgetItem, int)
     def __itemDoubleClicked(self, itm, column):
         """
         Private slot to handle double clicking a tree item.
-        
+
         @param itm reference to the item having been double clicked
         @type QTreeWidgetItem
         @param column column of the double click
@@ -456,13 +459,13 @@
         """
         if not itm:
             return
-        
+
         mainWin = itm.data(0, TabManagerWidget.WebWindowRole)
         browser = itm.data(0, TabManagerWidget.WebBrowserRole)
-        
+
         if not mainWin:
             return
-        
+
         if mainWin.isMinimized():
             mainWin.showNormal()
         else:
@@ -470,17 +473,17 @@
         mainWin.activateWindow()
         mainWin.raise_()
         mainWin.setFocus()
-        
+
         tabWidget = mainWin.tabWidget()
         if browser and browser != tabWidget.currentWidget():
             tabWidget.setCurrentWidget(browser)
             browser.setFocus()
-    
+
     @pyqtSlot()
     def __isBrowserSelected(self):
         """
         Private slot to check, if any browser entry is selected.
-        
+
         @return flag indicating the existence of a selected entry
         @rtype bool
         """
@@ -490,14 +493,14 @@
             if topItm.checkState(0) != Qt.CheckState.Unchecked:
                 selected = True
                 break
-        
+
         return selected
-    
+
     @pyqtSlot(QPoint)
     def __customContextMenuRequested(self, pos):
         """
         Private slot to show the context menu.
-        
+
         @param pos position the menu should be shown at
         @type QPoint
         """
@@ -507,40 +510,40 @@
         act.setData(TabManagerWidget.GroupByWindow)
         act.setCheckable(True)
         act.setChecked(self.__groupType == TabManagerWidget.GroupByWindow)
-        
+
         act = groupTypeSubMenu.addAction(self.tr("&Domain"))
         act.setData(TabManagerWidget.GroupByDomain)
         act.setCheckable(True)
         act.setChecked(self.__groupType == TabManagerWidget.GroupByDomain)
-        
+
         act = groupTypeSubMenu.addAction(self.tr("&Host"))
         act.setData(TabManagerWidget.GroupByHost)
         act.setCheckable(True)
         act.setChecked(self.__groupType == TabManagerWidget.GroupByHost)
         groupTypeSubMenu.triggered.connect(self.changeGroupType)
-        
+
         menu.addMenu(groupTypeSubMenu)
-        
+
         menu.addSeparator()
-        
+
         if self.__isBrowserSelected():
             act1 = menu.addAction(
-                UI.PixmapCache.getIcon("bookmark22"),
-                self.tr("&Bookmark checked tabs"))
+                UI.PixmapCache.getIcon("bookmark22"), self.tr("&Bookmark checked tabs")
+            )
             act1.setObjectName("bookmarkSelection")
             act1.triggered.connect(lambda: self.__processActions(act1))
             act2 = menu.addAction(
-                UI.PixmapCache.getIcon("tabClose"),
-                self.tr("&Close checked tabs"))
+                UI.PixmapCache.getIcon("tabClose"), self.tr("&Close checked tabs")
+            )
             act2.setObjectName("closeSelection")
             act2.triggered.connect(lambda: self.__processActions(act2))
-        
+
         menu.exec(self.__tree.viewport().mapToGlobal(pos))
-    
+
     def mainWindowCreated(self, mainWin, refresh=True):
         """
         Public method to act on the creation of a new web browser window.
-        
+
         @param mainWin reference to the web browser window
         @type WebBrowserWindow
         @param refresh flag indicating to refresh the widget
@@ -552,26 +555,25 @@
         mainWin.webBrowserClosed.connect(self.delayedRefreshTree)
         mainWin.tabWidget().currentUrlChanged.connect(self.delayedRefreshTree)
         mainWin.tabWidget().currentChanged.connect(self.delayedRefreshTree)
-    
+
     def createStatusBarIcon(self):
         """
         Public method to create a status bar icon.
-        
+
         @return generated icon
         @rtype EricClickableLabel
         """
         icon = EricClickableLabel()
-        icon.setPixmap(
-            UI.PixmapCache.getPixmap("tabManager").scaled(16, 16))
+        icon.setPixmap(UI.PixmapCache.getPixmap("tabManager").scaled(16, 16))
         icon.setToolTip(self.tr("Show Tab Manager"))
         icon.clicked.connect(lambda: self.raiseTabManager(icon))
-        
+
         return icon
-    
+
     def raiseTabManager(self, icon):
         """
         Public slot to show the tab manager.
-        
+
         @param icon reference to the clicked icon
         @type EricClickableLabel or QAction
         """
@@ -580,24 +582,27 @@
             window = icon.window()
         elif isinstance(icon, QAction):
             window = icon.parent()
-        
+
         if window is not None:
             titleBarHeight = self.style().pixelMetric(
-                QStyle.PixelMetric.PM_TitleBarHeight)
-            
+                QStyle.PixelMetric.PM_TitleBarHeight
+            )
+
             y = max(0, window.frameGeometry().top() + titleBarHeight + 1)
-            
+
             availableGeometry = ericApp().primaryScreen().availableGeometry()
             windowFrameGeometry = window.frameGeometry()
-            if (availableGeometry.width() - windowFrameGeometry.right() - 1 >
-                    self.frameGeometry().width()):
+            if (
+                availableGeometry.width() - windowFrameGeometry.right() - 1
+                > self.frameGeometry().width()
+            ):
                 x = windowFrameGeometry.right() + 1
             else:
                 x = windowFrameGeometry.x() - 1 - self.frameGeometry().width()
-            
+
             newGeo = QRect(x, y, self.width(), window.height())
             self.setGeometry(newGeo)
-        
+
         self.activateWindow()
         self.showNormal()
         self.raise_()

eric ide

mercurial