src/eric7/WebBrowser/AdBlock/AdBlockTreeWidget.py

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

eric ide

mercurial