eric6/WebBrowser/AdBlock/AdBlockTreeWidget.py

changeset 6942
2602857055c5
parent 6645
ad476851d7e0
child 7229
53054eb5b15a
equal deleted inserted replaced
6941:f99d60d6b59b 6942:2602857055c5
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2012 - 2019 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a tree widget for the AdBlock configuration dialog.
8 """
9
10 from __future__ import unicode_literals
11
12 from PyQt5.QtCore import Qt
13 from PyQt5.QtGui import QFont, QColor
14 from PyQt5.QtWidgets import QAbstractItemView, QTreeWidgetItem, QInputDialog, \
15 QLineEdit, QMenu, QApplication
16
17 from E5Gui.E5TreeWidget import E5TreeWidget
18
19
20 class AdBlockTreeWidget(E5TreeWidget):
21 """
22 Class implementing a tree widget for the AdBlock configuration dialog.
23 """
24 def __init__(self, subscription, parent=None):
25 """
26 Constructor
27
28 @param subscription reference to the subscription
29 @type AdBlockSubscription
30 @param parent reference to the parent widget
31 @type QWidget
32 """
33 super(AdBlockTreeWidget, self).__init__(parent)
34
35 self.__subscription = subscription
36 self.__topItem = None
37 self.__ruleToBeSelected = ""
38 self.__itemChangingBlock = False
39
40 self.setContextMenuPolicy(Qt.CustomContextMenu)
41 self.setDefaultItemShowMode(E5TreeWidget.ItemsExpanded)
42 self.setHeaderHidden(True)
43 self.setAlternatingRowColors(True)
44
45 self.customContextMenuRequested.connect(self.__contextMenuRequested)
46 self.itemChanged.connect(self.__itemChanged)
47 self.__subscription.changed.connect(self.__subscriptionChanged)
48 self.__subscription.rulesChanged.connect(self.__subscriptionChanged)
49
50 def subscription(self):
51 """
52 Public method to get a reference to the subscription.
53
54 @return reference to the subscription
55 @rtype AdBlockSubscription
56 """
57 return self.__subscription
58
59 def showRule(self, rule):
60 """
61 Public method to highlight the given rule.
62
63 @param rule AdBlock rule to be shown
64 @type AdBlockRule
65 """
66 if not bool(self.__topItem) and bool(rule):
67 self.__ruleToBeSelected = rule.filter()
68 elif self.__ruleToBeSelected:
69 items = self.findItems(self.__ruleToBeSelected, Qt.MatchRecursive)
70 if items:
71 item = items[0]
72 self.setCurrentItem(item)
73 self.scrollToItem(item, QAbstractItemView.PositionAtCenter)
74
75 self.__ruleToBeSelected = ""
76
77 def refresh(self):
78 """
79 Public method to refresh the tree.
80 """
81 QApplication.setOverrideCursor(Qt.WaitCursor)
82 self.__itemChangingBlock = True
83 self.clear()
84
85 boldFont = QFont()
86 boldFont.setBold(True)
87
88 self.__topItem = QTreeWidgetItem(self)
89 self.__topItem.setText(0, self.__subscription.title())
90 self.__topItem.setFont(0, boldFont)
91 self.addTopLevelItem(self.__topItem)
92
93 allRules = self.__subscription.allRules()
94
95 index = 0
96 for rule in allRules:
97 item = QTreeWidgetItem(self.__topItem)
98 item.setText(0, rule.filter())
99 item.setData(0, Qt.UserRole, index)
100 if self.__subscription.canEditRules():
101 item.setFlags(item.flags() | Qt.ItemIsEditable)
102 self.__adjustItemFeatures(item, rule)
103 index += 1
104
105 self.expandAll()
106 self.showRule(None)
107 self.__itemChangingBlock = False
108 QApplication.restoreOverrideCursor()
109 QApplication.processEvents()
110
111 def addRule(self, filterRule=""):
112 """
113 Public slot to add a new rule.
114
115 @param filterRule filter to be added
116 @type str
117 """
118 if not self.__subscription.canEditRules():
119 return
120
121 if not filterRule:
122 filterRule, ok = QInputDialog.getText(
123 self,
124 self.tr("Add Custom Rule"),
125 self.tr("Write your rule here:"),
126 QLineEdit.Normal)
127 if not ok or filterRule == "":
128 return
129
130 from .AdBlockRule import AdBlockRule
131 rule = AdBlockRule(filterRule, self.__subscription)
132 self.__subscription.addRule(rule)
133
134 def removeRule(self):
135 """
136 Public slot to remove the current rule.
137 """
138 item = self.currentItem()
139 if item is None or \
140 not self.__subscription.canEditRules() or \
141 item == self.__topItem:
142 return
143
144 offset = item.data(0, Qt.UserRole)
145 self.__subscription.removeRule(offset)
146 self.deleteItem(item)
147
148 def __contextMenuRequested(self, pos):
149 """
150 Private slot to show the context menu.
151
152 @param pos position for the menu
153 @type QPoint
154 """
155 if not self.__subscription.canEditRules():
156 return
157
158 item = self.itemAt(pos)
159 if item is None:
160 return
161
162 menu = QMenu()
163 menu.addAction(self.tr("Add Rule"), self.addRule)
164 menu.addSeparator()
165 act = menu.addAction(self.tr("Remove Rule"), self.removeRule)
166 if item.parent() is None:
167 act.setDisabled(True)
168
169 menu.exec_(self.viewport().mapToGlobal(pos))
170
171 def __itemChanged(self, itm):
172 """
173 Private slot to handle the change of an item.
174
175 @param itm changed item
176 @type QTreeWidgetItem
177 """
178 if itm is None or self.__itemChangingBlock:
179 return
180
181 self.__itemChangingBlock = True
182
183 offset = itm.data(0, Qt.UserRole)
184 oldRule = self.__subscription.rule(offset)
185
186 if itm.checkState(0) == Qt.Unchecked and oldRule.isEnabled():
187 # Disable rule
188 rule = self.__subscription.setRuleEnabled(offset, False)
189 self.__adjustItemFeatures(itm, rule)
190 elif itm.checkState(0) == Qt.Checked and not oldRule.isEnabled():
191 # Enable rule
192 rule = self.__subscription.setRuleEnabled(offset, True)
193 self.__adjustItemFeatures(itm, rule)
194 elif self.__subscription.canEditRules():
195 from .AdBlockRule import AdBlockRule
196 # Custom rule has been changed
197 rule = self.__subscription.replaceRule(
198 AdBlockRule(itm.text(0), self.__subscription), offset)
199 self.__adjustItemFeatures(itm, rule)
200
201 self.__itemChangingBlock = False
202
203 def __copyFilter(self):
204 """
205 Private slot to copy the current filter to the clipboard.
206 """
207 item = self.currentItem()
208 if item is not None:
209 QApplication.clipboard().setText(item.text(0))
210
211 def __subscriptionChanged(self):
212 """
213 Private slot handling a subscription change.
214 """
215 self.refresh()
216
217 self.__itemChangingBlock = True
218 self.__topItem.setText(
219 0, self.tr("{0} (recently updated)").format(
220 self.__subscription.title()))
221 self.__itemChangingBlock = False
222
223 def __adjustItemFeatures(self, itm, rule):
224 """
225 Private method to adjust an item.
226
227 @param itm item to be adjusted
228 @type QTreeWidgetItem
229 @param rule rule for the adjustment
230 @type AdBlockRule
231 """
232 if not rule.isEnabled():
233 font = QFont()
234 font.setItalic(True)
235 itm.setForeground(0, QColor(Qt.gray))
236
237 if not rule.isComment() and not rule.isHeader():
238 itm.setFlags(itm.flags() | Qt.ItemIsUserCheckable)
239 itm.setCheckState(0, Qt.Unchecked)
240 itm.setFont(0, font)
241
242 return
243
244 itm.setFlags(itm.flags() | Qt.ItemIsUserCheckable)
245 itm.setCheckState(0, Qt.Checked)
246
247 if rule.isCSSRule():
248 itm.setForeground(0, QColor(Qt.darkBlue))
249 itm.setFont(0, QFont())
250 elif rule.isException():
251 itm.setForeground(0, QColor(Qt.darkGreen))
252 itm.setFont(0, QFont())
253 else:
254 itm.setForeground(0, QColor())
255 itm.setFont(0, QFont())
256
257 def keyPressEvent(self, evt):
258 """
259 Protected method handling key presses.
260
261 @param evt key press event
262 @type QKeyEvent
263 """
264 if evt.key() == Qt.Key_C and \
265 evt.modifiers() & Qt.ControlModifier:
266 self.__copyFilter()
267 elif evt.key() == Qt.Key_Delete:
268 self.removeRule()
269 else:
270 super(AdBlockTreeWidget, self).keyPressEvent(evt)

eric ide

mercurial