|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2009 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Module implementing a model for the AdBlock dialog. |
|
8 """ |
|
9 |
|
10 from PyQt4.QtCore import * |
|
11 from PyQt4.QtGui import * |
|
12 |
|
13 import Helpviewer.HelpWindow |
|
14 |
|
15 class AdBlockModel(QAbstractItemModel): |
|
16 """ |
|
17 Class implementing a model for the AdBlock dialog. |
|
18 """ |
|
19 def __init__(self, parent = None): |
|
20 """ |
|
21 Constructor |
|
22 |
|
23 @param parent reference to the parent object (QObject) |
|
24 """ |
|
25 QAbstractItemModel.__init__(self, parent) |
|
26 |
|
27 self.__manager = Helpviewer.HelpWindow.HelpWindow.adblockManager() |
|
28 self.connect(self.__manager, SIGNAL("rulesChanged()"), self.__rulesChanged) |
|
29 |
|
30 def __rulesChanged(self): |
|
31 """ |
|
32 Private slot to handle changes in rules. |
|
33 """ |
|
34 self.reset() |
|
35 |
|
36 def rule(self, index): |
|
37 """ |
|
38 Public method to get the rule given it's index. |
|
39 |
|
40 @param index index of the rule (QModelIndex) |
|
41 @return reference to the rule (AdBlockRule) |
|
42 """ |
|
43 parent = index.internalPointer() |
|
44 return parent.allRules()[index.row()] |
|
45 |
|
46 def subscription(self, index): |
|
47 """ |
|
48 Public method to get the subscription given it's index. |
|
49 |
|
50 @param index index of the subscription (QModelIndex) |
|
51 @return reference to the subscription (AdBlockSubscription) |
|
52 """ |
|
53 parent = index.internalPointer() |
|
54 if parent is not None: |
|
55 return None |
|
56 row = index.row() |
|
57 if row < 0 or row >= len(self.__manager.subscriptions()): |
|
58 return None |
|
59 return self.__manager.subscriptions()[row] |
|
60 |
|
61 def subscriptionIndex(self, subscription): |
|
62 """ |
|
63 Public method to get the index of a subscription. |
|
64 |
|
65 @param subscription reference to the subscription (AdBlockSubscription) |
|
66 @return index of the subscription (QModelIndex) |
|
67 """ |
|
68 try: |
|
69 row = self.__manager.subscriptions().index(subscription) |
|
70 if row < 0 or row >= len(self.__manager.subscriptions()): |
|
71 return QModelIndex() |
|
72 return self.createIndex(row, 0, 0) |
|
73 except ValueError: |
|
74 return QModelIndex() |
|
75 |
|
76 def headerData(self, section, orientation, role = Qt.DisplayRole): |
|
77 """ |
|
78 Public method to get the header data. |
|
79 |
|
80 @param section section number (integer) |
|
81 @param orientation header orientation (Qt.Orientation) |
|
82 @param role data role (integer) |
|
83 @return header data (QVariant) |
|
84 """ |
|
85 if orientation == Qt.Horizontal and role == Qt.DisplayRole: |
|
86 if section == 0: |
|
87 return QVariant(self.trUtf8("Rule")) |
|
88 return QAbstractItemModel.headerData(self, section, orientation, role) |
|
89 |
|
90 def data(self, index, role = Qt.DisplayRole): |
|
91 """ |
|
92 Public method to get data from the model. |
|
93 |
|
94 @param index index of bookmark to get data for (QModelIndex) |
|
95 @param role data role (integer) |
|
96 @return bookmark data (QVariant) |
|
97 """ |
|
98 if not index.isValid() or index.model() != self or index.column() != 0: |
|
99 return QVariant() |
|
100 |
|
101 if role in [Qt.EditRole, Qt.DisplayRole]: |
|
102 if index.parent().isValid(): |
|
103 r = self.rule(index) |
|
104 return QVariant(r.filter()) |
|
105 else: |
|
106 sub = self.subscription(index) |
|
107 if sub is not None: |
|
108 return QVariant(sub.title()) |
|
109 |
|
110 elif role == Qt.CheckStateRole: |
|
111 if index.parent().isValid(): |
|
112 r = self.rule(index) |
|
113 if r.isEnabled(): |
|
114 return QVariant(Qt.Checked) |
|
115 else: |
|
116 return QVariant(Qt.Unchecked) |
|
117 else: |
|
118 sub = self.subscription(index) |
|
119 if sub is not None: |
|
120 if sub.isEnabled(): |
|
121 return QVariant(Qt.Checked) |
|
122 else: |
|
123 return QVariant(Qt.Unchecked) |
|
124 |
|
125 return QVariant() |
|
126 |
|
127 def columnCount(self, parent = QModelIndex()): |
|
128 """ |
|
129 Public method to get the number of columns. |
|
130 |
|
131 @param parent index of parent (QModelIndex) |
|
132 @return number of columns (integer) |
|
133 """ |
|
134 if parent.column() > 0: |
|
135 return 0 |
|
136 else: |
|
137 return 1 |
|
138 |
|
139 def rowCount(self, parent = QModelIndex()): |
|
140 """ |
|
141 Public method to determine the number of rows. |
|
142 |
|
143 @param parent index of parent (QModelIndex) |
|
144 @return number of rows (integer) |
|
145 """ |
|
146 if parent.column() > 0: |
|
147 return 0 |
|
148 |
|
149 if not parent.isValid(): |
|
150 return len(self.__manager.subscriptions()) |
|
151 |
|
152 if parent.internalPointer() is not None: |
|
153 return 0 |
|
154 |
|
155 parentNode = self.subscription(parent) |
|
156 if parentNode is not None: |
|
157 return len(parentNode.allRules()) |
|
158 |
|
159 return 0 |
|
160 |
|
161 def index(self, row, column, parent = QModelIndex()): |
|
162 """ |
|
163 Public method to get a model index for a node cell. |
|
164 |
|
165 @param row row number (integer) |
|
166 @param column column number (integer) |
|
167 @param parent index of the parent (QModelIndex) |
|
168 @return index (QModelIndex) |
|
169 """ |
|
170 if row < 0 or column < 0 or \ |
|
171 row >= self.rowCount(parent) or column >= self.columnCount(parent): |
|
172 return QModelIndex() |
|
173 |
|
174 if not parent.isValid(): |
|
175 return self.createIndex(row, column, None) |
|
176 |
|
177 parentNode = self.subscription(parent) |
|
178 return self.createIndex(row, column, parentNode) |
|
179 |
|
180 def parent(self, index = QModelIndex()): |
|
181 """ |
|
182 Public method to get the index of the parent node. |
|
183 |
|
184 @param index index of the child node (QModelIndex) |
|
185 @return index of the parent node (QModelIndex) |
|
186 """ |
|
187 if not index.isValid(): |
|
188 return QModelIndex() |
|
189 |
|
190 parent = index.internalPointer() |
|
191 if parent is None: |
|
192 return QModelIndex() |
|
193 |
|
194 parentRow = self.__manager.subscriptions().index(parent) |
|
195 return self.createIndex(parentRow, 0, None) |
|
196 |
|
197 def flags(self, index): |
|
198 """ |
|
199 Public method to get flags for a node cell. |
|
200 |
|
201 @param index index of the node cell (QModelIndex) |
|
202 @return flags (Qt.ItemFlags) |
|
203 """ |
|
204 if not index.isValid(): |
|
205 return Qt.NoItemFlags |
|
206 |
|
207 flags = Qt.ItemIsSelectable |
|
208 |
|
209 if index.parent().isValid(): |
|
210 flags |= Qt.ItemIsUserCheckable | Qt.ItemIsEditable |
|
211 |
|
212 parentNode = self.subscription(index.parent()) |
|
213 if parentNode is not None and parentNode.isEnabled(): |
|
214 flags |= Qt.ItemIsEnabled |
|
215 else: |
|
216 flags |= Qt.ItemIsUserCheckable | Qt.ItemIsEditable | Qt.ItemIsEnabled |
|
217 |
|
218 return flags |
|
219 |
|
220 def removeRows(self, row, count, parent = QModelIndex()): |
|
221 """ |
|
222 Public method to remove bookmarks from the model. |
|
223 |
|
224 @param row row of the first bookmark to remove (integer) |
|
225 @param count number of bookmarks to remove (integer) |
|
226 @param index of the parent bookmark node (QModelIndex) |
|
227 @return flag indicating successful removal (boolean) |
|
228 """ |
|
229 if row < 0 or count <= 0 or row + count > self.rowCount(parent): |
|
230 return False |
|
231 |
|
232 if not parent.isValid(): |
|
233 self.disconnect(self.__manager, SIGNAL("rulesChanged()"), |
|
234 self.__rulesChanged) |
|
235 self.beginRemoveRows(QModelIndex(), row, row + count - 1) |
|
236 for subscription in self.__manager.subscriptions()[row:row + count]: |
|
237 self.__manager.removeSubscription(subscription) |
|
238 self.endRemoveRows() |
|
239 self.connect(self.__manager, SIGNAL("rulesChanged()"), |
|
240 self.__rulesChanged) |
|
241 return True |
|
242 else: |
|
243 sub = self.subscription(parent) |
|
244 if sub is not None: |
|
245 self.disconnect(self.__manager, SIGNAL("rulesChanged()"), |
|
246 self.__rulesChanged) |
|
247 self.beginRemoveRows(parent, row, row + count - 1) |
|
248 for i in reversed(range(row, row + count)): |
|
249 sub.removeRule(i) |
|
250 self.endRemoveRows() |
|
251 self.connect(self.__manager, SIGNAL("rulesChanged()"), |
|
252 self.__rulesChanged) |
|
253 return True |
|
254 |
|
255 return False |
|
256 |
|
257 def setData(self, index, value, role = Qt.EditRole): |
|
258 """ |
|
259 Public method to set the data of a node cell. |
|
260 |
|
261 @param index index of the node cell (QModelIndex) |
|
262 @param value value to be set (QVariant) |
|
263 @param role role of the data (integer) |
|
264 @return flag indicating success (boolean) |
|
265 """ |
|
266 if not index.isValid() or \ |
|
267 index.model() != self or \ |
|
268 index.column() != 0 or \ |
|
269 (self.flags(index) & Qt.ItemIsEditable) == 0: |
|
270 return False |
|
271 |
|
272 self.disconnect(self.__manager, SIGNAL("rulesChanged()"), self.__rulesChanged) |
|
273 changed = False |
|
274 |
|
275 if role in [Qt.EditRole, Qt.DisplayRole]: |
|
276 if index.parent().isValid(): |
|
277 sub = self.subscription(index.parent()) |
|
278 if sub is not None: |
|
279 r = self.rule(index) |
|
280 r.setFilter(value.toString()) |
|
281 sub.replaceRule(r, index.row()) |
|
282 self.emit(SIGNAL("dataChanged(const QModelIndex&, const QModelIndex&)"), |
|
283 index, index) |
|
284 changed = True |
|
285 else: |
|
286 sub = self.subscription(index) |
|
287 if sub is not None: |
|
288 sub.setTitle(value.toString()) |
|
289 self.emit(SIGNAL("dataChanged(const QModelIndex&, const QModelIndex&)"), |
|
290 index, index) |
|
291 changed = True |
|
292 |
|
293 elif role == Qt.CheckStateRole: |
|
294 if index.parent().isValid(): |
|
295 sub = self.subscription(index.parent()) |
|
296 if sub is not None: |
|
297 r = self.rule(index) |
|
298 r.setEnabled(value == Qt.Checked) |
|
299 sub.replaceRule(r, index.row()) |
|
300 self.emit(SIGNAL("dataChanged(const QModelIndex&, const QModelIndex&)"), |
|
301 index, index) |
|
302 changed = True |
|
303 else: |
|
304 sub = self.subscription(index) |
|
305 if sub is not None: |
|
306 sub.setEnabled(value == Qt.Checked) |
|
307 self.emit(SIGNAL("dataChanged(const QModelIndex&, const QModelIndex&)"), |
|
308 index, index) |
|
309 changed = True |
|
310 |
|
311 self.connect(self.__manager, SIGNAL("rulesChanged()"), self.__rulesChanged) |
|
312 return changed |
|
313 |
|
314 def hasChildren(self, parent = QModelIndex()): |
|
315 """ |
|
316 Public method to check, if a parent node has some children. |
|
317 |
|
318 @param parent index of the parent node (QModelIndex) |
|
319 @return flag indicating the presence of children (boolean) |
|
320 """ |
|
321 if not parent.isValid(): |
|
322 return True |
|
323 |
|
324 if parent.internalPointer() is None: |
|
325 return True |
|
326 |
|
327 return False |