Helpviewer/AdBlock/AdBlockTreeWidget.py

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

eric ide

mercurial