Changeset View
Changeset View
Standalone View
Standalone View
libtaskmanager/tasksmodel.cpp
Show First 20 Lines • Show All 64 Lines • ▼ Show 20 Line(s) | 46 | public: | |||
---|---|---|---|---|---|
65 | int screen = -1; | 65 | int screen = -1; | ||
66 | QString activity; | 66 | QString activity; | ||
67 | 67 | | |||
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 | QList<int> sortedPreFilterRows; | 74 | QList<int> sortedPreFilterRows; | ||
74 | QVector<int> sortRowInsertQueue; | 75 | QVector<int> sortRowInsertQueue; | ||
75 | QHash<QString, int> activityTaskCounts; | 76 | QHash<QString, int> activityTaskCounts; | ||
76 | static ActivityInfo* activityInfo; | 77 | static ActivityInfo* activityInfo; | ||
77 | static int activityInfoUsers; | 78 | static int activityInfoUsers; | ||
78 | 79 | | |||
79 | bool groupInline = false; | 80 | bool groupInline = false; | ||
80 | int groupingWindowTasksThreshold = -1; | 81 | int groupingWindowTasksThreshold = -1; | ||
▲ Show 20 Lines • Show All 280 Lines • ▼ Show 20 Line(s) | 356 | [this](const QModelIndex &parent, int first, int last) { | |||
361 | for (int i = first; i <= last; ++i) { | 362 | for (int i = first; i <= last; ++i) { | ||
362 | const QModelIndex &sourceIndex = groupingProxyModel->index(i, 0); | 363 | const QModelIndex &sourceIndex = groupingProxyModel->index(i, 0); | ||
363 | 364 | | |||
364 | if (sourceIndex.data(AbstractTasksModel::IsDemandingAttention).toBool()) { | 365 | if (sourceIndex.data(AbstractTasksModel::IsDemandingAttention).toBool()) { | ||
365 | updateAnyTaskDemandsAttention(); | 366 | updateAnyTaskDemandsAttention(); | ||
366 | } | 367 | } | ||
367 | 368 | | |||
368 | // When a window or startup task is removed, we have to trigger a re-filter of | 369 | // When a window or startup task is removed, we have to trigger a re-filter of | ||
369 | // matching launchers to (possibly) pop them back in. | 370 | // our launchers to (possibly) pop them back in. | ||
370 | if (!launcherTasksModel | 371 | // NOTE: An older revision of this code compared the window and startup tasks | ||
371 | || !(sourceIndex.data(AbstractTasksModel::IsWindow).toBool() | 372 | // to the launchers to figure out which launchers should be re-filtered. This | ||
373 | // was fine until we discovered that certain applications (e.g. Google Chrome) | ||||
374 | // change their window metadata specifically during tear-down, sometimes | ||||
375 | // breaking TaskTools::appsMatch (it's a race) and causing the associated | ||||
376 | // launcher to remain hidden. Therefore we now consider any top-level window or | ||||
377 | // startup task removal a trigger to re-filter all launchers. We don't do this | ||||
378 | // in response to the window metadata changes (even though it would be strictly | ||||
379 | // more correct, as then-ending identity match-up was what caused the launcher | ||||
380 | // to be hidden) because we don't want the launcher and window/startup task to | ||||
381 | // briefly co-exist in the model. | ||||
382 | if (!launcherCheckNeeded | ||||
383 | && launcherTasksModel | ||||
384 | && (sourceIndex.data(AbstractTasksModel::IsWindow).toBool() | ||||
372 | || sourceIndex.data(AbstractTasksModel::IsStartup).toBool())) { | 385 | || sourceIndex.data(AbstractTasksModel::IsStartup).toBool())) { | ||
373 | continue; | 386 | launcherCheckNeeded = true; | ||
374 | } | 387 | } | ||
375 | | ||||
376 | for (int j = 0; j < launcherTasksModel->rowCount(); ++j) { | | |||
377 | const QModelIndex &launcherIndex = launcherTasksModel->index(j, 0); | | |||
378 | | ||||
379 | if (appsMatch(sourceIndex, launcherIndex)) { | | |||
380 | QMetaObject::invokeMethod(launcherTasksModel, "dataChanged", Qt::QueuedConnection, | | |||
381 | Q_ARG(QModelIndex, launcherIndex), Q_ARG(QModelIndex, launcherIndex)); | | |||
382 | } | 388 | } | ||
383 | } | 389 | } | ||
390 | ); | ||||
391 | | ||||
392 | QObject::connect(filterProxyModel, &QAbstractItemModel::rowsRemoved, q, | ||||
393 | [this](const QModelIndex &parent, int first, int last) { | ||||
394 | Q_UNUSED(parent) | ||||
395 | Q_UNUSED(first) | ||||
396 | Q_UNUSED(last) | ||||
397 | | ||||
398 | if (launcherCheckNeeded) { | ||||
399 | QMetaObject::invokeMethod(launcherTasksModel, "dataChanged", | ||||
400 | Q_ARG(QModelIndex, launcherTasksModel->index(0, 0)), | ||||
401 | Q_ARG(QModelIndex, launcherTasksModel->index(launcherTasksModel->rowCount() - 1, 0))); | ||||
402 | | ||||
403 | launcherCheckNeeded = false; | ||||
384 | } | 404 | } | ||
385 | } | 405 | } | ||
386 | ); | 406 | ); | ||
387 | 407 | | |||
388 | // Update anyTaskDemandsAttention on source data changes. | 408 | // Update anyTaskDemandsAttention on source data changes. | ||
davidedmundson: I think it's a bit weird that we have a pair:
groupingProxyModel::aboutToRemove… | |||||
389 | QObject::connect(groupingProxyModel, &QAbstractItemModel::dataChanged, q, | 409 | QObject::connect(groupingProxyModel, &QAbstractItemModel::dataChanged, q, | ||
390 | [this](const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles) { | 410 | [this](const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles) { | ||
391 | Q_UNUSED(bottomRight) | 411 | Q_UNUSED(bottomRight) | ||
392 | 412 | | |||
393 | // We can ignore group members. | 413 | // We can ignore group members. | ||
394 | if (topLeft.parent().isValid()) { | 414 | if (topLeft.parent().isValid()) { | ||
395 | return; | 415 | return; | ||
396 | } | 416 | } | ||
▲ Show 20 Lines • Show All 1246 Lines • Show Last 20 Lines |
I think it's a bit weird that we have a pair:
groupingProxyModel::aboutToRemove
filterProxyModel:rowsRemoved
As it doesn't match up evenly.
It'll work, but having them both the same will be less confusing long term.
I think changing the first connect to filterProxyModel might result in logic being overall simpler. You'd be processing the launcher every time any window got removed, but that might fix what's in the bug reports.
Other than that, the change looks good.