WebBrowser/AdBlock/AdBlockTreeWidget.py

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

eric ide

mercurial