src/eric7/WebBrowser/Bookmarks/BookmarksMenu.py

branch
eric7
changeset 9209
b99e7fd55fd3
parent 8881
54e42bc2437a
child 9221
bf71ee032bb4
diff -r 3fc8dfeb6ebe -r b99e7fd55fd3 src/eric7/WebBrowser/Bookmarks/BookmarksMenu.py
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/eric7/WebBrowser/Bookmarks/BookmarksMenu.py	Thu Jul 07 11:23:56 2022 +0200
@@ -0,0 +1,383 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2009 - 2022 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing the bookmarks menu.
+"""
+
+from PyQt6.QtCore import pyqtSignal, Qt, QUrl
+from PyQt6.QtGui import QCursor
+from PyQt6.QtWidgets import QMenu
+
+from EricWidgets.EricModelMenu import EricModelMenu
+
+from .BookmarksModel import BookmarksModel
+from .BookmarkNode import BookmarkNode
+
+
+class BookmarksMenu(EricModelMenu):
+    """
+    Class implementing the bookmarks menu base class.
+    
+    @signal openUrl(QUrl, str) emitted to open a URL with the given title in
+        the current tab
+    @signal newTab(QUrl, str) emitted to open a URL with the given title in a
+        new tab
+    @signal newWindow(QUrl, str) emitted to open a URL with the given title in
+        a new window
+    """
+    openUrl = pyqtSignal(QUrl, str)
+    newTab = pyqtSignal(QUrl, str)
+    newWindow = pyqtSignal(QUrl, str)
+    
+    def __init__(self, parent=None):
+        """
+        Constructor
+        
+        @param parent reference to the parent widget (QWidget)
+        """
+        EricModelMenu.__init__(self, parent)
+        
+        self.activated.connect(self.__activated)
+        self.setStatusBarTextRole(BookmarksModel.UrlStringRole)
+        self.setSeparatorRole(BookmarksModel.SeparatorRole)
+        
+        self.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
+        self.customContextMenuRequested.connect(self.__contextMenuRequested)
+    
+    def createBaseMenu(self):
+        """
+        Public method to get the menu that is used to populate sub menu's.
+        
+        @return reference to the menu (BookmarksMenu)
+        """
+        menu = BookmarksMenu(self)
+        menu.openUrl.connect(self.openUrl)
+        menu.newTab.connect(self.newTab)
+        menu.newWindow.connect(self.newWindow)
+        return menu
+    
+    def __updateVisitCount(self, idx):
+        """
+        Private method to update the visit count of a bookmark.
+        
+        @param idx index of the bookmark item (QModelIndex)
+        """
+        from WebBrowser.WebBrowserWindow import WebBrowserWindow
+        
+        bookmarkNode = self.model().node(idx)
+        manager = WebBrowserWindow.bookmarksManager()
+        manager.incVisitCount(bookmarkNode)
+    
+    def __activated(self, idx):
+        """
+        Private slot handling the activated signal.
+        
+        @param idx index of the activated item (QModelIndex)
+        """
+        if self._keyboardModifiers & Qt.KeyboardModifier.ControlModifier:
+            self.newTab.emit(
+                idx.data(BookmarksModel.UrlRole),
+                idx.data(Qt.ItemDataRole.DisplayRole))
+        elif self._keyboardModifiers & Qt.KeyboardModifier.ShiftModifier:
+            self.newWindow.emit(
+                idx.data(BookmarksModel.UrlRole),
+                idx.data(Qt.ItemDataRole.DisplayRole))
+        else:
+            self.openUrl.emit(
+                idx.data(BookmarksModel.UrlRole),
+                idx.data(Qt.ItemDataRole.DisplayRole))
+        self.__updateVisitCount(idx)
+    
+    def postPopulated(self):
+        """
+        Public method to add any actions after the tree.
+        """
+        if self.isEmpty():
+            return
+        
+        parent = self.rootIndex()
+        
+        hasBookmarks = False
+        
+        for i in range(parent.model().rowCount(parent)):
+            child = parent.model().index(i, 0, parent)
+            
+            if child.data(BookmarksModel.TypeRole) == BookmarkNode.Bookmark:
+                hasBookmarks = True
+                break
+        
+        if not hasBookmarks:
+            return
+        
+        self.addSeparator()
+        act = self.addAction(self.tr("Open all in Tabs"))
+        act.triggered.connect(lambda: self.openAll(act))
+    
+    def openAll(self, act):
+        """
+        Public slot to open all the menu's items.
+        
+        @param act reference to the action object
+        @type QAction
+        """
+        menu = act.parent()
+        if menu is None:
+            return
+        
+        parent = menu.rootIndex()
+        if not parent.isValid():
+            return
+        
+        for i in range(parent.model().rowCount(parent)):
+            child = parent.model().index(i, 0, parent)
+            
+            if child.data(BookmarksModel.TypeRole) != BookmarkNode.Bookmark:
+                continue
+            
+            if i == 0:
+                self.openUrl.emit(
+                    child.data(BookmarksModel.UrlRole),
+                    child.data(Qt.ItemDataRole.DisplayRole))
+            else:
+                self.newTab.emit(
+                    child.data(BookmarksModel.UrlRole),
+                    child.data(Qt.ItemDataRole.DisplayRole))
+            self.__updateVisitCount(child)
+    
+    def __contextMenuRequested(self, pos):
+        """
+        Private slot to handle the context menu request.
+        
+        @param pos position the context menu shall be shown (QPoint)
+        """
+        act = self.actionAt(pos)
+        
+        if (
+            act is not None and
+            act not in self.menuActions and
+            self.index(act).isValid()
+        ):
+            menu = QMenu()
+            v = act.data()
+            
+            act2 = menu.addAction(self.tr("Open"))
+            act2.setData(v)
+            act2.triggered.connect(
+                lambda: self.__openBookmark(act2))
+            act2 = menu.addAction(self.tr("Open in New Tab\tCtrl+LMB"))
+            act2.setData(v)
+            act2.triggered.connect(
+                lambda: self.__openBookmarkInNewTab(act2))
+            act2 = menu.addAction(self.tr("Open in New Window"))
+            act2.setData(v)
+            act2.triggered.connect(
+                lambda: self.__openBookmarkInNewWindow(act2))
+            act2 = menu.addAction(self.tr("Open in New Private Window"))
+            act2.setData(v)
+            act2.triggered.connect(
+                lambda: self.__openBookmarkInPrivateWindow(act2))
+            menu.addSeparator()
+            
+            act2 = menu.addAction(self.tr("Remove"))
+            act2.setData(v)
+            act2.triggered.connect(lambda: self.__removeBookmark(act2))
+            menu.addSeparator()
+            
+            act2 = menu.addAction(self.tr("Properties..."))
+            act2.setData(v)
+            act2.triggered.connect(lambda: self.__edit(act2))
+            
+            execAct = menu.exec(QCursor.pos())
+            if execAct is not None:
+                self.close()
+                parent = self.parent()
+                while parent is not None and isinstance(parent, QMenu):
+                    parent.close()
+                    parent = parent.parent()
+    
+    def __openBookmark(self, act):
+        """
+        Private slot to open a bookmark in the current browser tab.
+        
+        @param act reference to the triggering action
+        @type QAction
+        """
+        idx = self.index(act)
+        
+        self.openUrl.emit(
+            idx.data(BookmarksModel.UrlRole),
+            idx.data(Qt.ItemDataRole.DisplayRole))
+        self.__updateVisitCount(idx)
+    
+    def __openBookmarkInNewTab(self, act):
+        """
+        Private slot to open a bookmark in a new browser tab.
+        
+        @param act reference to the triggering action
+        @type QAction
+        """
+        idx = self.index(act)
+        
+        self.newTab.emit(
+            idx.data(BookmarksModel.UrlRole),
+            idx.data(Qt.ItemDataRole.DisplayRole))
+        self.__updateVisitCount(idx)
+    
+    def __openBookmarkInNewWindow(self, act):
+        """
+        Private slot to open a bookmark in a new window.
+        
+        @param act reference to the triggering action
+        @type QAction
+        """
+        idx = self.index(act)
+        url = idx.data(BookmarksModel.UrlRole)
+        
+        from WebBrowser.WebBrowserWindow import WebBrowserWindow
+        WebBrowserWindow.mainWindow().newWindow(url)
+        self.__updateVisitCount(idx)
+    
+    def __openBookmarkInPrivateWindow(self, act):
+        """
+        Private slot to open a bookmark in a new private window.
+        
+        @param act reference to the triggering action
+        @type QAction
+        """
+        idx = self.index(act)
+        url = idx.data(BookmarksModel.UrlRole)
+        
+        from WebBrowser.WebBrowserWindow import WebBrowserWindow
+        WebBrowserWindow.mainWindow().newPrivateWindow(url)
+        self.__updateVisitCount(idx)
+    
+    def __removeBookmark(self, act):
+        """
+        Private slot to remove a bookmark.
+        
+        @param act reference to the triggering action
+        @type QAction
+        """
+        idx = self.index(act)
+        self.removeEntry(idx)
+    
+    def __edit(self, act):
+        """
+        Private slot to edit a bookmarks properties.
+        
+        @param act reference to the triggering action
+        @type QAction
+        """
+        from .BookmarkPropertiesDialog import BookmarkPropertiesDialog
+        
+        idx = self.index(act)
+        node = self.model().node(idx)
+        dlg = BookmarkPropertiesDialog(node)
+        dlg.exec()
+
+##############################################################################
+
+
+class BookmarksMenuBarMenu(BookmarksMenu):
+    """
+    Class implementing a dynamically populated menu for bookmarks.
+    
+    @signal openUrl(QUrl, str) emitted to open a URL with the given title in
+        the current tab
+    """
+    openUrl = pyqtSignal(QUrl, str)
+    
+    def __init__(self, parent=None):
+        """
+        Constructor
+        
+        @param parent reference to the parent widget (QWidget)
+        """
+        BookmarksMenu.__init__(self, parent)
+        
+        self.__initialActions = []
+    
+    def prePopulated(self):
+        """
+        Public method to add any actions before the tree.
+       
+        @return flag indicating if any actions were added (boolean)
+        """
+        from WebBrowser.WebBrowserWindow import WebBrowserWindow
+        
+        manager = WebBrowserWindow.bookmarksManager()
+        self.setModel(manager.bookmarksModel())
+        self.setRootIndex(manager.bookmarksModel().nodeIndex(manager.menu()))
+        
+        # initial actions
+        for act in self.__initialActions:
+            if act == "--SEPARATOR--":
+                self.addSeparator()
+            else:
+                self.addAction(act)
+        if len(self.__initialActions) != 0:
+            self.addSeparator()
+        
+        self.createMenu(
+            manager.bookmarksModel().nodeIndex(manager.toolbar()),
+            1, self)
+        return True
+    
+    def postPopulated(self):
+        """
+        Public method to add any actions after the tree.
+        """
+        if self.isEmpty():
+            return
+        
+        parent = self.rootIndex()
+        
+        hasBookmarks = False
+        
+        for i in range(parent.model().rowCount(parent)):
+            child = parent.model().index(i, 0, parent)
+            
+            if child.data(BookmarksModel.TypeRole) == BookmarkNode.Bookmark:
+                hasBookmarks = True
+                break
+        
+        if not hasBookmarks:
+            return
+        
+        self.addSeparator()
+        act_1 = self.addAction(self.tr("Default Home Page"))
+        act_1.setData("eric:home")
+        act_1.triggered.connect(
+            lambda: self.__defaultBookmarkTriggered(act_1))
+        act_2 = self.addAction(self.tr("Speed Dial"))
+        act_2.setData("eric:speeddial")
+        act_2.triggered.connect(
+            lambda: self.__defaultBookmarkTriggered(act_2))
+        self.addSeparator()
+        act_3 = self.addAction(self.tr("Open all in Tabs"))
+        act_3.triggered.connect(lambda: self.openAll(act_3))
+    
+    def setInitialActions(self, actions):
+        """
+        Public method to set the list of actions that should appear first in
+        the menu.
+        
+        @param actions list of initial actions (list of QAction)
+        """
+        self.__initialActions = actions[:]
+        for act in self.__initialActions:
+            self.addAction(act)
+    
+    def __defaultBookmarkTriggered(self, act):
+        """
+        Private slot handling the default bookmark menu entries.
+        
+        @param act reference to the action object
+        @type QAction
+        """
+        urlStr = act.data()
+        if urlStr.startswith("eric:"):
+            self.openUrl.emit(QUrl(urlStr), "")

eric ide

mercurial