64 if date == QDate.currentDate(): |
64 if date == QDate.currentDate(): |
65 return self.tr("Earlier Today") |
65 return self.tr("Earlier Today") |
66 return date.toString("yyyy-MM-dd") |
66 return date.toString("yyyy-MM-dd") |
67 if index.column() == 1: |
67 if index.column() == 1: |
68 return self.tr( |
68 return self.tr( |
69 "%n item(s)", "", |
69 "%n item(s)", "", self.rowCount(index.sibling(index.row(), 0)) |
70 self.rowCount(index.sibling(index.row(), 0))) |
70 ) |
71 |
71 |
72 elif ( |
72 elif ( |
73 role == Qt.ItemDataRole.DecorationRole and |
73 role == Qt.ItemDataRole.DecorationRole |
74 index.column() == 0 and |
74 and index.column() == 0 |
75 not index.parent().isValid() |
75 and not index.parent().isValid() |
76 ): |
76 ): |
77 return UI.PixmapCache.getIcon("history") |
77 return UI.PixmapCache.getIcon("history") |
78 |
78 |
79 elif ( |
79 elif ( |
80 role == HistoryModel.DateRole and |
80 role == HistoryModel.DateRole |
81 index.column() == 0 and |
81 and index.column() == 0 |
82 index.internalId() == 0 |
82 and index.internalId() == 0 |
83 ): |
83 ): |
84 offset = self.__sourceDateRow(index.row()) |
84 offset = self.__sourceDateRow(index.row()) |
85 idx = self.sourceModel().index(offset, 0) |
85 idx = self.sourceModel().index(offset, 0) |
86 return idx.data(HistoryModel.DateRole) |
86 return idx.data(HistoryModel.DateRole) |
87 |
87 |
88 return QAbstractProxyModel.data(self, index, role) |
88 return QAbstractProxyModel.data(self, index, role) |
89 |
89 |
90 def columnCount(self, parent=None): |
90 def columnCount(self, parent=None): |
91 """ |
91 """ |
92 Public method to get the number of columns. |
92 Public method to get the number of columns. |
93 |
93 |
94 @param parent index of parent (QModelIndex) |
94 @param parent index of parent (QModelIndex) |
95 @return number of columns (integer) |
95 @return number of columns (integer) |
96 """ |
96 """ |
97 if parent is None: |
97 if parent is None: |
98 parent = QModelIndex() |
98 parent = QModelIndex() |
99 |
99 |
100 return self.sourceModel().columnCount(self.mapToSource(parent)) |
100 return self.sourceModel().columnCount(self.mapToSource(parent)) |
101 |
101 |
102 def rowCount(self, parent=None): |
102 def rowCount(self, parent=None): |
103 """ |
103 """ |
104 Public method to determine the number of rows. |
104 Public method to determine the number of rows. |
105 |
105 |
106 @param parent index of parent (QModelIndex) |
106 @param parent index of parent (QModelIndex) |
107 @return number of rows (integer) |
107 @return number of rows (integer) |
108 """ |
108 """ |
109 if parent is None: |
109 if parent is None: |
110 parent = QModelIndex() |
110 parent = QModelIndex() |
111 |
111 |
112 if ( |
112 if ( |
113 parent.internalId() != 0 or |
113 parent.internalId() != 0 |
114 parent.column() > 0 or |
114 or parent.column() > 0 |
115 self.sourceModel() is None |
115 or self.sourceModel() is None |
116 ): |
116 ): |
117 return 0 |
117 return 0 |
118 |
118 |
119 # row count OF dates |
119 # row count OF dates |
120 if not parent.isValid(): |
120 if not parent.isValid(): |
121 if self.__sourceRowCache: |
121 if self.__sourceRowCache: |
122 return len(self.__sourceRowCache) |
122 return len(self.__sourceRowCache) |
123 |
123 |
124 currentDate = QDate() |
124 currentDate = QDate() |
125 rows = 0 |
125 rows = 0 |
126 totalRows = self.sourceModel().rowCount() |
126 totalRows = self.sourceModel().rowCount() |
127 |
127 |
128 for row in range(totalRows): |
128 for row in range(totalRows): |
129 rowDate = self.sourceModel().index(row, 0).data( |
129 rowDate = self.sourceModel().index(row, 0).data(HistoryModel.DateRole) |
130 HistoryModel.DateRole) |
|
131 if rowDate != currentDate: |
130 if rowDate != currentDate: |
132 self.__sourceRowCache.append(row) |
131 self.__sourceRowCache.append(row) |
133 currentDate = rowDate |
132 currentDate = rowDate |
134 rows += 1 |
133 rows += 1 |
135 return rows |
134 return rows |
136 |
135 |
137 # row count FOR a date |
136 # row count FOR a date |
138 start = self.__sourceDateRow(parent.row()) |
137 start = self.__sourceDateRow(parent.row()) |
139 end = self.__sourceDateRow(parent.row() + 1) |
138 end = self.__sourceDateRow(parent.row() + 1) |
140 return end - start |
139 return end - start |
141 |
140 |
142 def __sourceDateRow(self, row): |
141 def __sourceDateRow(self, row): |
143 """ |
142 """ |
144 Private method to translate the top level date row into the offset |
143 Private method to translate the top level date row into the offset |
145 where that date starts. |
144 where that date starts. |
146 |
145 |
147 @param row row number of the date (integer) |
146 @param row row number of the date (integer) |
148 @return offset where that date starts (integer) |
147 @return offset where that date starts (integer) |
149 """ |
148 """ |
150 if row <= 0: |
149 if row <= 0: |
151 return 0 |
150 return 0 |
152 |
151 |
153 if len(self.__sourceRowCache) == 0: |
152 if len(self.__sourceRowCache) == 0: |
154 self.rowCount(QModelIndex()) |
153 self.rowCount(QModelIndex()) |
155 |
154 |
156 if row >= len(self.__sourceRowCache): |
155 if row >= len(self.__sourceRowCache): |
157 if self.sourceModel() is None: |
156 if self.sourceModel() is None: |
158 return 0 |
157 return 0 |
159 return self.sourceModel().rowCount() |
158 return self.sourceModel().rowCount() |
160 |
159 |
161 return self.__sourceRowCache[row] |
160 return self.__sourceRowCache[row] |
162 |
161 |
163 def mapToSource(self, proxyIndex): |
162 def mapToSource(self, proxyIndex): |
164 """ |
163 """ |
165 Public method to map an index to the source model index. |
164 Public method to map an index to the source model index. |
166 |
165 |
167 @param proxyIndex reference to a proxy model index (QModelIndex) |
166 @param proxyIndex reference to a proxy model index (QModelIndex) |
168 @return source model index (QModelIndex) |
167 @return source model index (QModelIndex) |
169 """ |
168 """ |
170 offset = proxyIndex.internalId() |
169 offset = proxyIndex.internalId() |
171 if offset == 0: |
170 if offset == 0: |
172 return QModelIndex() |
171 return QModelIndex() |
173 startDateRow = self.__sourceDateRow(offset - 1) |
172 startDateRow = self.__sourceDateRow(offset - 1) |
174 return self.sourceModel().index( |
173 return self.sourceModel().index( |
175 startDateRow + proxyIndex.row(), proxyIndex.column()) |
174 startDateRow + proxyIndex.row(), proxyIndex.column() |
176 |
175 ) |
|
176 |
177 def index(self, row, column, parent=None): |
177 def index(self, row, column, parent=None): |
178 """ |
178 """ |
179 Public method to create an index. |
179 Public method to create an index. |
180 |
180 |
181 @param row row number for the index (integer) |
181 @param row row number for the index (integer) |
182 @param column column number for the index (integer) |
182 @param column column number for the index (integer) |
183 @param parent index of the parent item (QModelIndex) |
183 @param parent index of the parent item (QModelIndex) |
184 @return requested index (QModelIndex) |
184 @return requested index (QModelIndex) |
185 """ |
185 """ |
186 if parent is None: |
186 if parent is None: |
187 parent = QModelIndex() |
187 parent = QModelIndex() |
188 |
188 |
189 if ( |
189 if ( |
190 row < 0 or |
190 row < 0 |
191 column < 0 or |
191 or column < 0 |
192 column >= self.columnCount(parent) or |
192 or column >= self.columnCount(parent) |
193 parent.column() > 0 |
193 or parent.column() > 0 |
194 ): |
194 ): |
195 return QModelIndex() |
195 return QModelIndex() |
196 |
196 |
197 if not parent.isValid(): |
197 if not parent.isValid(): |
198 return self.createIndex(row, column, 0) |
198 return self.createIndex(row, column, 0) |
199 return self.createIndex(row, column, parent.row() + 1) |
199 return self.createIndex(row, column, parent.row() + 1) |
200 |
200 |
201 def parent(self, index): |
201 def parent(self, index): |
202 """ |
202 """ |
203 Public method to get the parent index. |
203 Public method to get the parent index. |
204 |
204 |
205 @param index index of item to get parent (QModelIndex) |
205 @param index index of item to get parent (QModelIndex) |
206 @return index of parent (QModelIndex) |
206 @return index of parent (QModelIndex) |
207 """ |
207 """ |
208 offset = index.internalId() |
208 offset = index.internalId() |
209 if offset == 0 or not index.isValid(): |
209 if offset == 0 or not index.isValid(): |
210 return QModelIndex() |
210 return QModelIndex() |
211 return self.createIndex(offset - 1, 0, 0) |
211 return self.createIndex(offset - 1, 0, 0) |
212 |
212 |
213 def hasChildren(self, parent=None): |
213 def hasChildren(self, parent=None): |
214 """ |
214 """ |
215 Public method to check, if an entry has some children. |
215 Public method to check, if an entry has some children. |
216 |
216 |
217 @param parent index of the entry to check (QModelIndex) |
217 @param parent index of the entry to check (QModelIndex) |
218 @return flag indicating the presence of children (boolean) |
218 @return flag indicating the presence of children (boolean) |
219 """ |
219 """ |
220 if parent is None: |
220 if parent is None: |
221 parent = QModelIndex() |
221 parent = QModelIndex() |
222 |
222 |
223 grandparent = parent.parent() |
223 grandparent = parent.parent() |
224 if not grandparent.isValid(): |
224 if not grandparent.isValid(): |
225 return True |
225 return True |
226 return False |
226 return False |
227 |
227 |
228 def flags(self, index): |
228 def flags(self, index): |
229 """ |
229 """ |
230 Public method to get the item flags. |
230 Public method to get the item flags. |
231 |
231 |
232 @param index index of the item (QModelIndex) |
232 @param index index of the item (QModelIndex) |
233 @return flags (Qt.ItemFlags) |
233 @return flags (Qt.ItemFlags) |
234 """ |
234 """ |
235 return ( |
235 return ( |
236 Qt.ItemFlag.NoItemFlags |
236 Qt.ItemFlag.NoItemFlags |
237 if not index.isValid() else |
237 if not index.isValid() |
238 (Qt.ItemFlag.ItemIsSelectable | |
238 else ( |
239 Qt.ItemFlag.ItemIsEnabled | |
239 Qt.ItemFlag.ItemIsSelectable |
240 Qt.ItemFlag.ItemIsDragEnabled) |
240 | Qt.ItemFlag.ItemIsEnabled |
|
241 | Qt.ItemFlag.ItemIsDragEnabled |
|
242 ) |
241 ) |
243 ) |
242 |
244 |
243 def setSourceModel(self, sourceModel): |
245 def setSourceModel(self, sourceModel): |
244 """ |
246 """ |
245 Public method to set the source model. |
247 Public method to set the source model. |
246 |
248 |
247 @param sourceModel reference to the source model (QAbstractItemModel) |
249 @param sourceModel reference to the source model (QAbstractItemModel) |
248 """ |
250 """ |
249 if self.sourceModel() is not None: |
251 if self.sourceModel() is not None: |
250 self.sourceModel().modelReset.disconnect(self.__sourceReset) |
252 self.sourceModel().modelReset.disconnect(self.__sourceReset) |
251 self.sourceModel().layoutChanged.disconnect(self.__sourceReset) |
253 self.sourceModel().layoutChanged.disconnect(self.__sourceReset) |
252 self.sourceModel().rowsInserted.disconnect( |
254 self.sourceModel().rowsInserted.disconnect(self.__sourceRowsInserted) |
253 self.__sourceRowsInserted) |
|
254 self.sourceModel().rowsRemoved.disconnect(self.__sourceRowsRemoved) |
255 self.sourceModel().rowsRemoved.disconnect(self.__sourceRowsRemoved) |
255 |
256 |
256 super().setSourceModel(sourceModel) |
257 super().setSourceModel(sourceModel) |
257 |
258 |
258 if self.sourceModel() is not None: |
259 if self.sourceModel() is not None: |
259 self.__loaded = False |
260 self.__loaded = False |
260 self.sourceModel().modelReset.connect(self.__sourceReset) |
261 self.sourceModel().modelReset.connect(self.__sourceReset) |
261 self.sourceModel().layoutChanged.connect(self.__sourceReset) |
262 self.sourceModel().layoutChanged.connect(self.__sourceReset) |
262 self.sourceModel().rowsInserted.connect(self.__sourceRowsInserted) |
263 self.sourceModel().rowsInserted.connect(self.__sourceRowsInserted) |
263 self.sourceModel().rowsRemoved.connect(self.__sourceRowsRemoved) |
264 self.sourceModel().rowsRemoved.connect(self.__sourceRowsRemoved) |
264 |
265 |
265 self.beginResetModel() |
266 self.beginResetModel() |
266 self.endResetModel() |
267 self.endResetModel() |
267 |
268 |
268 def __sourceReset(self): |
269 def __sourceReset(self): |
269 """ |
270 """ |
270 Private slot to handle a reset of the source model. |
271 Private slot to handle a reset of the source model. |
271 """ |
272 """ |
272 self.beginResetModel() |
273 self.beginResetModel() |
273 self.__sourceRowCache = [] |
274 self.__sourceRowCache = [] |
274 self.endResetModel() |
275 self.endResetModel() |
275 |
276 |
276 def __sourceRowsInserted(self, parent, start, end): |
277 def __sourceRowsInserted(self, parent, start, end): |
277 """ |
278 """ |
278 Private slot to handle the insertion of data in the source model. |
279 Private slot to handle the insertion of data in the source model. |
279 |
280 |
280 @param parent reference to the parent index (QModelIndex) |
281 @param parent reference to the parent index (QModelIndex) |
281 @param start start row (integer) |
282 @param start start row (integer) |
282 @param end end row (integer) |
283 @param end end row (integer) |
283 """ |
284 """ |
284 if not parent.isValid(): |
285 if not parent.isValid(): |
285 if start != 0 or start != end: |
286 if start != 0 or start != end: |
286 self.beginResetModel() |
287 self.beginResetModel() |
287 self.__sourceRowCache = [] |
288 self.__sourceRowCache = [] |
288 self.endResetModel() |
289 self.endResetModel() |
289 return |
290 return |
290 |
291 |
291 self.__sourceRowCache = [] |
292 self.__sourceRowCache = [] |
292 treeIndex = self.mapFromSource(self.sourceModel().index(start, 0)) |
293 treeIndex = self.mapFromSource(self.sourceModel().index(start, 0)) |
293 treeParent = treeIndex.parent() |
294 treeParent = treeIndex.parent() |
294 if self.rowCount(treeParent) == 1: |
295 if self.rowCount(treeParent) == 1: |
295 self.beginInsertRows(QModelIndex(), 0, 0) |
296 self.beginInsertRows(QModelIndex(), 0, 0) |
296 self.endInsertRows() |
297 self.endInsertRows() |
297 else: |
298 else: |
298 self.beginInsertRows(treeParent, treeIndex.row(), |
299 self.beginInsertRows(treeParent, treeIndex.row(), treeIndex.row()) |
299 treeIndex.row()) |
|
300 self.endInsertRows() |
300 self.endInsertRows() |
301 |
301 |
302 def mapFromSource(self, sourceIndex): |
302 def mapFromSource(self, sourceIndex): |
303 """ |
303 """ |
304 Public method to map an index to the proxy model index. |
304 Public method to map an index to the proxy model index. |
305 |
305 |
306 @param sourceIndex reference to a source model index (QModelIndex) |
306 @param sourceIndex reference to a source model index (QModelIndex) |
307 @return proxy model index (QModelIndex) |
307 @return proxy model index (QModelIndex) |
308 """ |
308 """ |
309 if not sourceIndex.isValid(): |
309 if not sourceIndex.isValid(): |
310 return QModelIndex() |
310 return QModelIndex() |
311 |
311 |
312 if len(self.__sourceRowCache) == 0: |
312 if len(self.__sourceRowCache) == 0: |
313 self.rowCount(QModelIndex()) |
313 self.rowCount(QModelIndex()) |
314 |
314 |
315 try: |
315 try: |
316 row = self.__sourceRowCache.index(sourceIndex.row()) |
316 row = self.__sourceRowCache.index(sourceIndex.row()) |
317 except ValueError: |
317 except ValueError: |
318 row = bisect.bisect_left(self.__sourceRowCache, sourceIndex.row()) |
318 row = bisect.bisect_left(self.__sourceRowCache, sourceIndex.row()) |
319 if ( |
319 if ( |
320 row == len(self.__sourceRowCache) or |
320 row == len(self.__sourceRowCache) |
321 self.__sourceRowCache[row] != sourceIndex.row() |
321 or self.__sourceRowCache[row] != sourceIndex.row() |
322 ): |
322 ): |
323 row -= 1 |
323 row -= 1 |
324 dateRow = max(0, row) |
324 dateRow = max(0, row) |
325 row = sourceIndex.row() - self.__sourceRowCache[dateRow] |
325 row = sourceIndex.row() - self.__sourceRowCache[dateRow] |
326 return self.createIndex(row, sourceIndex.column(), dateRow + 1) |
326 return self.createIndex(row, sourceIndex.column(), dateRow + 1) |
327 |
327 |
328 def removeRows(self, row, count, parent=None): |
328 def removeRows(self, row, count, parent=None): |
329 """ |
329 """ |
330 Public method to remove entries from the model. |
330 Public method to remove entries from the model. |
331 |
331 |
332 @param row row of the first entry to remove (integer) |
332 @param row row of the first entry to remove (integer) |
333 @param count number of entries to remove (integer) |
333 @param count number of entries to remove (integer) |
334 @param parent index of the parent entry (QModelIndex) |
334 @param parent index of the parent entry (QModelIndex) |
335 @return flag indicating successful removal (boolean) |
335 @return flag indicating successful removal (boolean) |
336 """ |
336 """ |
337 if parent is None: |
337 if parent is None: |
338 parent = QModelIndex() |
338 parent = QModelIndex() |
339 |
339 |
340 if ( |
340 if row < 0 or count <= 0 or row + count > self.rowCount(parent): |
341 row < 0 or |
|
342 count <= 0 or |
|
343 row + count > self.rowCount(parent) |
|
344 ): |
|
345 return False |
341 return False |
346 |
342 |
347 self.__removingDown = True |
343 self.__removingDown = True |
348 if parent.isValid() and self.rowCount(parent) == count - row: |
344 if parent.isValid() and self.rowCount(parent) == count - row: |
349 self.beginRemoveRows(QModelIndex(), parent.row(), parent.row()) |
345 self.beginRemoveRows(QModelIndex(), parent.row(), parent.row()) |
350 else: |
346 else: |
351 self.beginRemoveRows(parent, row, row + count - 1) |
347 self.beginRemoveRows(parent, row, row + count - 1) |