Changeset View
Changeset View
Standalone View
Standalone View
libtaskmanager/tasksmodel.cpp
Show First 20 Lines • Show All 67 Lines • ▼ Show 20 Line(s) | 46 | public: | |||
---|---|---|---|---|---|
68 | SortMode sortMode = SortAlpha; | 68 | SortMode sortMode = SortAlpha; | ||
69 | bool separateLaunchers = true; | 69 | bool separateLaunchers = true; | ||
70 | bool launchInPlace = false; | 70 | bool launchInPlace = false; | ||
71 | bool launchersEverSet = false; | 71 | bool launchersEverSet = false; | ||
72 | bool launcherSortingDirty = false; | 72 | bool launcherSortingDirty = false; | ||
73 | bool launcherCheckNeeded = false; | 73 | bool launcherCheckNeeded = false; | ||
74 | QList<int> sortedPreFilterRows; | 74 | QList<int> sortedPreFilterRows; | ||
75 | QVector<int> sortRowInsertQueue; | 75 | QVector<int> sortRowInsertQueue; | ||
76 | bool sortRowInsertQueueStale = false; | ||||
76 | QHash<QString, int> activityTaskCounts; | 77 | QHash<QString, int> activityTaskCounts; | ||
77 | static ActivityInfo* activityInfo; | 78 | static ActivityInfo* activityInfo; | ||
78 | static int activityInfoUsers; | 79 | static int activityInfoUsers; | ||
79 | 80 | | |||
80 | bool groupInline = false; | 81 | bool groupInline = false; | ||
81 | int groupingWindowTasksThreshold = -1; | 82 | int groupingWindowTasksThreshold = -1; | ||
82 | 83 | | |||
83 | bool usedByQml = false; | 84 | bool usedByQml = false; | ||
▲ Show 20 Lines • Show All 102 Lines • ▼ Show 20 Line(s) | 184 | [this](const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles) { | |||
186 | 187 | | |||
187 | if (sortMode == SortActivity && roles.contains(AbstractTasksModel::Activities)) { | 188 | if (sortMode == SortActivity && roles.contains(AbstractTasksModel::Activities)) { | ||
188 | updateActivityTaskCounts(); | 189 | updateActivityTaskCounts(); | ||
189 | } | 190 | } | ||
190 | 191 | | |||
191 | if (roles.contains(AbstractTasksModel::IsActive)) { | 192 | if (roles.contains(AbstractTasksModel::IsActive)) { | ||
192 | emit q->activeTaskChanged(); | 193 | emit q->activeTaskChanged(); | ||
193 | } | 194 | } | ||
195 | | ||||
196 | // In manual sort mode, updateManualSortMap() may consult the sortRowInsertQueue | ||||
197 | // for new tasks to sort in. Hidden tasks remain in the queue to potentially sort | ||||
198 | // them later, when they are are actually revealed to the user. | ||||
199 | // This is particularly useful in concert with taskmanagerrulesrc's SkipTaskbar | ||||
200 | // key, which is used to hide window tasks which update from bogus to useful | ||||
201 | // window metadata early in startup. The role change then coincides with positive | ||||
202 | // app identication, which is when updateManualSortMap() becomes able to sort the | ||||
203 | // task adjacent to its launcher when required to do so. | ||||
204 | if (sortMode == SortManual && roles.contains(AbstractTasksModel::SkipTaskbar)) { | ||||
205 | updateManualSortMap(); | ||||
206 | } | ||||
194 | } | 207 | } | ||
195 | ); | 208 | ); | ||
196 | 209 | | |||
197 | if (!startupTasksModel) { | 210 | if (!startupTasksModel) { | ||
198 | startupTasksModel = new StartupTasksModel(); | 211 | startupTasksModel = new StartupTasksModel(); | ||
199 | } | 212 | } | ||
200 | 213 | | |||
201 | concatProxyModel = new ConcatenateTasksProxyModel(q); | 214 | concatProxyModel = new ConcatenateTasksProxyModel(q); | ||
Show All 21 Lines | 235 | if (it.value() >= start) { | |||
223 | it.setValue(it.value() + delta); | 236 | it.setValue(it.value() + delta); | ||
224 | } | 237 | } | ||
225 | } | 238 | } | ||
226 | 239 | | |||
227 | for (int i = start; i <= end; ++i) { | 240 | for (int i = start; i <= end; ++i) { | ||
228 | sortedPreFilterRows.append(i); | 241 | sortedPreFilterRows.append(i); | ||
229 | 242 | | |||
230 | if (!separateLaunchers) { | 243 | if (!separateLaunchers) { | ||
244 | if (sortRowInsertQueueStale) { | ||||
245 | sortRowInsertQueue.clear(); | ||||
246 | sortRowInsertQueueStale = false; | ||||
247 | } | ||||
248 | | ||||
231 | sortRowInsertQueue.append(sortedPreFilterRows.count() - 1); | 249 | sortRowInsertQueue.append(sortedPreFilterRows.count() - 1); | ||
232 | } | 250 | } | ||
233 | } | 251 | } | ||
234 | } | 252 | } | ||
235 | ); | 253 | ); | ||
236 | 254 | | |||
237 | // If we're in manual sort mode, we need to update the sort map on row insertions. | 255 | // If we're in manual sort mode, we need to update the sort map on row insertions. | ||
238 | QObject::connect(concatProxyModel, &QAbstractItemModel::rowsInserted, q, | 256 | QObject::connect(concatProxyModel, &QAbstractItemModel::rowsInserted, q, | ||
Show All 12 Lines | |||||
251 | QObject::connect(concatProxyModel, &QAbstractItemModel::rowsRemoved, q, | 269 | QObject::connect(concatProxyModel, &QAbstractItemModel::rowsRemoved, q, | ||
252 | [this](const QModelIndex &parent, int first, int last) { | 270 | [this](const QModelIndex &parent, int first, int last) { | ||
253 | Q_UNUSED(parent) | 271 | Q_UNUSED(parent) | ||
254 | 272 | | |||
255 | if (sortMode != SortManual) { | 273 | if (sortMode != SortManual) { | ||
256 | return; | 274 | return; | ||
257 | } | 275 | } | ||
258 | 276 | | |||
277 | if (sortRowInsertQueueStale) { | ||||
278 | sortRowInsertQueue.clear(); | ||||
279 | sortRowInsertQueueStale = false; | ||||
280 | } | ||||
281 | | ||||
259 | for (int i = first; i <= last; ++i) { | 282 | for (int i = first; i <= last; ++i) { | ||
260 | sortedPreFilterRows.removeOne(i); | 283 | sortedPreFilterRows.removeOne(i); | ||
261 | } | 284 | } | ||
262 | 285 | | |||
263 | const int delta = (last - first) + 1; | 286 | const int delta = (last - first) + 1; | ||
264 | QMutableListIterator<int> it(sortedPreFilterRows); | 287 | QMutableListIterator<int> it(sortedPreFilterRows); | ||
265 | 288 | | |||
266 | while (it.hasNext()) { | 289 | while (it.hasNext()) { | ||
▲ Show 20 Lines • Show All 267 Lines • ▼ Show 20 Line(s) | 530 | { | |||
534 | // Existing map; check whether launchers need sorting by launcher list position. | 557 | // Existing map; check whether launchers need sorting by launcher list position. | ||
535 | if (separateLaunchers) { | 558 | if (separateLaunchers) { | ||
536 | // Sort only launchers. | 559 | // Sort only launchers. | ||
537 | TasksModelLessThan lt(concatProxyModel, q, true); | 560 | TasksModelLessThan lt(concatProxyModel, q, true); | ||
538 | std::stable_sort(sortedPreFilterRows.begin(), sortedPreFilterRows.end(), lt); | 561 | std::stable_sort(sortedPreFilterRows.begin(), sortedPreFilterRows.end(), lt); | ||
539 | // Otherwise process any entries in the insert queue and move them intelligently | 562 | // Otherwise process any entries in the insert queue and move them intelligently | ||
540 | // in the sort map. | 563 | // in the sort map. | ||
541 | } else { | 564 | } else { | ||
542 | while (sortRowInsertQueue.count()) { | 565 | QMutableVectorIterator<int> i(sortRowInsertQueue); | ||
543 | const int row = sortRowInsertQueue.takeFirst(); | 566 | | ||
567 | while (i.hasNext()) { | ||||
568 | i.next(); | ||||
569 | | ||||
570 | const int row = i.value(); | ||||
544 | const QModelIndex &idx = concatProxyModel->index(sortedPreFilterRows.at(row), 0); | 571 | const QModelIndex &idx = concatProxyModel->index(sortedPreFilterRows.at(row), 0); | ||
545 | 572 | | |||
573 | // If a window task is currently hidden, we may want to keep it in the queue | ||||
574 | // to sort it in later once it gets revealed. | ||||
575 | // This is important in concert with taskmanagerrulesrc's SkipTaskbar key, which | ||||
576 | // is used to hide window tasks which update from bogus to useful window metadata | ||||
577 | // early in startup. Once the task no longer uses bogus metadata listed in the | ||||
578 | // config key, its SkipTaskbar role changes to false, and then is it possible to | ||||
579 | // sort the task adjacent to its launcher in the code below. | ||||
580 | if (idx.data(AbstractTasksModel::IsWindow).toBool() && idx.data(AbstractTasksModel::SkipTaskbar).toBool()) { | ||||
581 | // Since we're going to keep a row in the queue for now, make sure to | ||||
582 | // mark the queue as stale so it's cleared on appends or row removals | ||||
583 | // when they follow this sorting attempt. This frees us from having to | ||||
584 | // update the indices in the queue to keep them valid. | ||||
585 | // This means windowing system changes such as the opening or closing | ||||
586 | // of a window task which happen during the time period that a window | ||||
587 | // task has known bogus metadata, can upset what we're trying to | ||||
588 | // achieve with this exception. However, due to the briefness of the | ||||
589 | // time period and usage patterns, this is improbable, making this | ||||
590 | // likely good enough. If it turns out not to be, this decision may be | ||||
591 | // revisited later. | ||||
592 | sortRowInsertQueueStale = true; | ||||
593 | | ||||
594 | break; | ||||
595 | } else { | ||||
596 | i.remove(); | ||||
597 | } | ||||
598 | | ||||
546 | bool moved = false; | 599 | bool moved = false; | ||
547 | 600 | | |||
548 | // Try to move the task up to its right-most app sibling, unless this | 601 | // Try to move the task up to its right-most app sibling, unless this | ||
549 | // is us sorting in a launcher list for the first time. | 602 | // is us sorting in a launcher list for the first time. | ||
550 | if (launchersEverSet && !idx.data(AbstractTasksModel::IsLauncher).toBool()) { | 603 | if (launchersEverSet && !idx.data(AbstractTasksModel::IsLauncher).toBool()) { | ||
551 | for (int i = (row - 1); i >= 0; --i) { | 604 | for (int i = (row - 1); i >= 0; --i) { | ||
552 | const QModelIndex &concatProxyIndex = concatProxyModel->index(sortedPreFilterRows.at(i), 0); | 605 | const QModelIndex &concatProxyIndex = concatProxyModel->index(sortedPreFilterRows.at(i), 0); | ||
553 | 606 | | |||
▲ Show 20 Lines • Show All 1253 Lines • Show Last 20 Lines |