eric6/Helpviewer/AdBlock/AdBlockTreeWidget.py

changeset 6942
2602857055c5
parent 6645
ad476851d7e0
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 (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, filterRule=""):
110 """
111 Public slot to add a new rule.
112
113 @param filterRule filter to be added (string)
114 """
115 if not self.__subscription.canEditRules():
116 return
117
118 if not filterRule:
119 filterRule, ok = QInputDialog.getText(
120 self,
121 self.tr("Add Custom Rule"),
122 self.tr("Write your rule here:"),
123 QLineEdit.Normal)
124 if not ok or filterRule == "":
125 return
126
127 from .AdBlockRule import AdBlockRule
128 rule = AdBlockRule(filterRule, self.__subscription)
129 self.__subscription.addRule(rule)
130
131 def removeRule(self):
132 """
133 Public slot to remove the current rule.
134 """
135 item = self.currentItem()
136 if item is None or \
137 not self.__subscription.canEditRules() or \
138 item == self.__topItem:
139 return
140
141 offset = item.data(0, Qt.UserRole)
142 self.__subscription.removeRule(offset)
143 self.deleteItem(item)
144
145 def __contextMenuRequested(self, pos):
146 """
147 Private slot to show the context menu.
148
149 @param pos position for the menu (QPoint)
150 """
151 if not self.__subscription.canEditRules():
152 return
153
154 item = self.itemAt(pos)
155 if item is None:
156 return
157
158 menu = QMenu()
159 menu.addAction(self.tr("Add Rule"), self.addRule)
160 menu.addSeparator()
161 act = menu.addAction(self.tr("Remove Rule"), self.removeRule)
162 if item.parent() is None:
163 act.setDisabled(True)
164
165 menu.exec_(self.viewport().mapToGlobal(pos))
166
167 def __itemChanged(self, itm):
168 """
169 Private slot to handle the change of an item.
170
171 @param itm changed item (QTreeWidgetItem)
172 """
173 if itm is None or self.__itemChangingBlock:
174 return
175
176 self.__itemChangingBlock = True
177
178 offset = itm.data(0, Qt.UserRole)
179 oldRule = self.__subscription.rule(offset)
180
181 if itm.checkState(0) == Qt.Unchecked and oldRule.isEnabled():
182 # Disable rule
183 rule = self.__subscription.setRuleEnabled(offset, False)
184 self.__adjustItemFeatures(itm, rule)
185 elif itm.checkState(0) == Qt.Checked and not oldRule.isEnabled():
186 # Enable rule
187 rule = self.__subscription.setRuleEnabled(offset, True)
188 self.__adjustItemFeatures(itm, rule)
189 elif self.__subscription.canEditRules():
190 from .AdBlockRule import AdBlockRule
191 # Custom rule has been changed
192 rule = self.__subscription.replaceRule(
193 AdBlockRule(itm.text(0), self.__subscription), offset)
194 self.__adjustItemFeatures(itm, rule)
195
196 self.__itemChangingBlock = False
197
198 def __copyFilter(self):
199 """
200 Private slot to copy the current filter to the clipboard.
201 """
202 item = self.currentItem()
203 if item is not None:
204 QApplication.clipboard().setText(item.text(0))
205
206 def __subscriptionChanged(self):
207 """
208 Private slot handling a subscription change.
209 """
210 self.refresh()
211
212 self.__itemChangingBlock = True
213 self.__topItem.setText(
214 0, self.tr("{0} (recently updated)").format(
215 self.__subscription.title()))
216 self.__itemChangingBlock = False
217
218 def __adjustItemFeatures(self, itm, rule):
219 """
220 Private method to adjust an item.
221
222 @param itm item to be adjusted (QTreeWidgetItem)
223 @param rule rule for the adjustment (AdBlockRule)
224 """
225 if not rule.isEnabled():
226 font = QFont()
227 font.setItalic(True)
228 itm.setForeground(0, QColor(Qt.gray))
229
230 if not rule.isComment() and not rule.isHeader():
231 itm.setFlags(itm.flags() | Qt.ItemIsUserCheckable)
232 itm.setCheckState(0, Qt.Unchecked)
233 itm.setFont(0, font)
234
235 return
236
237 itm.setFlags(itm.flags() | Qt.ItemIsUserCheckable)
238 itm.setCheckState(0, Qt.Checked)
239
240 if rule.isCSSRule():
241 itm.setForeground(0, QColor(Qt.darkBlue))
242 itm.setFont(0, QFont())
243 elif rule.isException():
244 itm.setForeground(0, QColor(Qt.darkGreen))
245 itm.setFont(0, QFont())
246 else:
247 itm.setForeground(0, QColor())
248 itm.setFont(0, QFont())
249
250 def keyPressEvent(self, evt):
251 """
252 Protected method handling key presses.
253
254 @param evt key press event (QKeyEvent)
255 """
256 if evt.key() == Qt.Key_C and \
257 evt.modifiers() & Qt.ControlModifier:
258 self.__copyFilter()
259 elif evt.key() == Qt.Key_Delete:
260 self.removeRule()
261 else:
262 super(AdBlockTreeWidget, self).keyPressEvent(evt)

eric ide

mercurial