eric6/WebBrowser/AdBlock/AdBlockTreeWidget.py

changeset 6942
2602857055c5
parent 6645
ad476851d7e0
child 7229
53054eb5b15a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/eric6/WebBrowser/AdBlock/AdBlockTreeWidget.py	Sun Apr 14 15:09:21 2019 +0200
@@ -0,0 +1,270 @@
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2012 - 2019 Detlev Offenbach <detlev@die-offenbachs.de>
+#
+
+"""
+Module implementing a tree widget for the AdBlock configuration dialog.
+"""
+
+from __future__ import unicode_literals
+
+from PyQt5.QtCore import Qt
+from PyQt5.QtGui import QFont, QColor
+from PyQt5.QtWidgets import QAbstractItemView, QTreeWidgetItem, QInputDialog, \
+    QLineEdit, QMenu, QApplication
+
+from E5Gui.E5TreeWidget import E5TreeWidget
+
+
+class AdBlockTreeWidget(E5TreeWidget):
+    """
+    Class implementing a tree widget for the AdBlock configuration dialog.
+    """
+    def __init__(self, subscription, parent=None):
+        """
+        Constructor
+        
+        @param subscription reference to the subscription
+        @type AdBlockSubscription
+        @param parent reference to the parent widget
+        @type QWidget
+        """
+        super(AdBlockTreeWidget, self).__init__(parent)
+        
+        self.__subscription = subscription
+        self.__topItem = None
+        self.__ruleToBeSelected = ""
+        self.__itemChangingBlock = False
+        
+        self.setContextMenuPolicy(Qt.CustomContextMenu)
+        self.setDefaultItemShowMode(E5TreeWidget.ItemsExpanded)
+        self.setHeaderHidden(True)
+        self.setAlternatingRowColors(True)
+        
+        self.customContextMenuRequested.connect(self.__contextMenuRequested)
+        self.itemChanged.connect(self.__itemChanged)
+        self.__subscription.changed.connect(self.__subscriptionChanged)
+        self.__subscription.rulesChanged.connect(self.__subscriptionChanged)
+    
+    def subscription(self):
+        """
+        Public method to get a reference to the subscription.
+        
+        @return reference to the subscription
+        @rtype AdBlockSubscription
+        """
+        return self.__subscription
+    
+    def showRule(self, rule):
+        """
+        Public method to highlight the given rule.
+        
+        @param rule AdBlock rule to be shown
+        @type AdBlockRule
+        """
+        if not bool(self.__topItem) and bool(rule):
+            self.__ruleToBeSelected = rule.filter()
+        elif self.__ruleToBeSelected:
+            items = self.findItems(self.__ruleToBeSelected, Qt.MatchRecursive)
+            if items:
+                item = items[0]
+                self.setCurrentItem(item)
+                self.scrollToItem(item, QAbstractItemView.PositionAtCenter)
+            
+            self.__ruleToBeSelected = ""
+    
+    def refresh(self):
+        """
+        Public method to refresh the tree.
+        """
+        QApplication.setOverrideCursor(Qt.WaitCursor)
+        self.__itemChangingBlock = True
+        self.clear()
+        
+        boldFont = QFont()
+        boldFont.setBold(True)
+        
+        self.__topItem = QTreeWidgetItem(self)
+        self.__topItem.setText(0, self.__subscription.title())
+        self.__topItem.setFont(0, boldFont)
+        self.addTopLevelItem(self.__topItem)
+        
+        allRules = self.__subscription.allRules()
+        
+        index = 0
+        for rule in allRules:
+            item = QTreeWidgetItem(self.__topItem)
+            item.setText(0, rule.filter())
+            item.setData(0, Qt.UserRole, index)
+            if self.__subscription.canEditRules():
+                item.setFlags(item.flags() | Qt.ItemIsEditable)
+            self.__adjustItemFeatures(item, rule)
+            index += 1
+        
+        self.expandAll()
+        self.showRule(None)
+        self.__itemChangingBlock = False
+        QApplication.restoreOverrideCursor()
+        QApplication.processEvents()
+    
+    def addRule(self, filterRule=""):
+        """
+        Public slot to add a new rule.
+        
+        @param filterRule filter to be added
+        @type str
+        """
+        if not self.__subscription.canEditRules():
+            return
+        
+        if not filterRule:
+            filterRule, ok = QInputDialog.getText(
+                self,
+                self.tr("Add Custom Rule"),
+                self.tr("Write your rule here:"),
+                QLineEdit.Normal)
+            if not ok or filterRule == "":
+                return
+        
+        from .AdBlockRule import AdBlockRule
+        rule = AdBlockRule(filterRule, self.__subscription)
+        self.__subscription.addRule(rule)
+    
+    def removeRule(self):
+        """
+        Public slot to remove the current rule.
+        """
+        item = self.currentItem()
+        if item is None or \
+           not self.__subscription.canEditRules() or \
+           item == self.__topItem:
+            return
+        
+        offset = item.data(0, Qt.UserRole)
+        self.__subscription.removeRule(offset)
+        self.deleteItem(item)
+    
+    def __contextMenuRequested(self, pos):
+        """
+        Private slot to show the context menu.
+        
+        @param pos position for the menu
+        @type QPoint
+        """
+        if not self.__subscription.canEditRules():
+            return
+        
+        item = self.itemAt(pos)
+        if item is None:
+            return
+        
+        menu = QMenu()
+        menu.addAction(self.tr("Add Rule"), self.addRule)
+        menu.addSeparator()
+        act = menu.addAction(self.tr("Remove Rule"), self.removeRule)
+        if item.parent() is None:
+            act.setDisabled(True)
+        
+        menu.exec_(self.viewport().mapToGlobal(pos))
+    
+    def __itemChanged(self, itm):
+        """
+        Private slot to handle the change of an item.
+        
+        @param itm changed item
+        @type QTreeWidgetItem
+        """
+        if itm is None or self.__itemChangingBlock:
+            return
+        
+        self.__itemChangingBlock = True
+        
+        offset = itm.data(0, Qt.UserRole)
+        oldRule = self.__subscription.rule(offset)
+        
+        if itm.checkState(0) == Qt.Unchecked and oldRule.isEnabled():
+            # Disable rule
+            rule = self.__subscription.setRuleEnabled(offset, False)
+            self.__adjustItemFeatures(itm, rule)
+        elif itm.checkState(0) == Qt.Checked and not oldRule.isEnabled():
+            # Enable rule
+            rule = self.__subscription.setRuleEnabled(offset, True)
+            self.__adjustItemFeatures(itm, rule)
+        elif self.__subscription.canEditRules():
+            from .AdBlockRule import AdBlockRule
+            # Custom rule has been changed
+            rule = self.__subscription.replaceRule(
+                AdBlockRule(itm.text(0), self.__subscription), offset)
+            self.__adjustItemFeatures(itm, rule)
+        
+        self.__itemChangingBlock = False
+    
+    def __copyFilter(self):
+        """
+        Private slot to copy the current filter to the clipboard.
+        """
+        item = self.currentItem()
+        if item is not None:
+            QApplication.clipboard().setText(item.text(0))
+    
+    def __subscriptionChanged(self):
+        """
+        Private slot handling a subscription change.
+        """
+        self.refresh()
+        
+        self.__itemChangingBlock = True
+        self.__topItem.setText(
+            0, self.tr("{0} (recently updated)").format(
+                self.__subscription.title()))
+        self.__itemChangingBlock = False
+    
+    def __adjustItemFeatures(self, itm, rule):
+        """
+        Private method to adjust an item.
+        
+        @param itm item to be adjusted
+        @type QTreeWidgetItem
+        @param rule rule for the adjustment
+        @type AdBlockRule
+        """
+        if not rule.isEnabled():
+            font = QFont()
+            font.setItalic(True)
+            itm.setForeground(0, QColor(Qt.gray))
+            
+            if not rule.isComment() and not rule.isHeader():
+                itm.setFlags(itm.flags() | Qt.ItemIsUserCheckable)
+                itm.setCheckState(0, Qt.Unchecked)
+                itm.setFont(0, font)
+            
+            return
+        
+        itm.setFlags(itm.flags() | Qt.ItemIsUserCheckable)
+        itm.setCheckState(0, Qt.Checked)
+        
+        if rule.isCSSRule():
+            itm.setForeground(0, QColor(Qt.darkBlue))
+            itm.setFont(0, QFont())
+        elif rule.isException():
+            itm.setForeground(0, QColor(Qt.darkGreen))
+            itm.setFont(0, QFont())
+        else:
+            itm.setForeground(0, QColor())
+            itm.setFont(0, QFont())
+    
+    def keyPressEvent(self, evt):
+        """
+        Protected method handling key presses.
+        
+        @param evt key press event
+        @type QKeyEvent
+        """
+        if evt.key() == Qt.Key_C and \
+           evt.modifiers() & Qt.ControlModifier:
+            self.__copyFilter()
+        elif evt.key() == Qt.Key_Delete:
+            self.removeRule()
+        else:
+            super(AdBlockTreeWidget, self).keyPressEvent(evt)

eric ide

mercurial