Changeset View
Changeset View
Standalone View
Standalone View
libtaskmanager/tasksmodel.cpp
Show First 20 Lines • Show All 74 Lines • ▼ Show 20 Line(s) | 46 | public: | |||
---|---|---|---|---|---|
75 | QVector<int> sortRowInsertQueue; | 75 | QVector<int> sortRowInsertQueue; | ||
76 | QHash<QString, int> activityTaskCounts; | 76 | QHash<QString, int> activityTaskCounts; | ||
77 | static ActivityInfo* activityInfo; | 77 | static ActivityInfo* activityInfo; | ||
78 | static int activityInfoUsers; | 78 | static int activityInfoUsers; | ||
79 | 79 | | |||
80 | bool groupInline = false; | 80 | bool groupInline = false; | ||
81 | int groupingWindowTasksThreshold = -1; | 81 | int groupingWindowTasksThreshold = -1; | ||
82 | 82 | | |||
83 | bool usedByQml = false; | ||||
84 | bool componentComplete = false; | ||||
85 | | ||||
83 | void initModels(); | 86 | void initModels(); | ||
84 | void initLauncherTasksModel(); | 87 | void initLauncherTasksModel(); | ||
85 | void updateAnyTaskDemandsAttention(); | 88 | void updateAnyTaskDemandsAttention(); | ||
86 | void updateManualSortMap(); | 89 | void updateManualSortMap(); | ||
87 | void consolidateManualSortMapForGroup(const QModelIndex &groupingProxyIndex); | 90 | void consolidateManualSortMapForGroup(const QModelIndex &groupingProxyIndex); | ||
88 | void updateGroupInline(); | 91 | void updateGroupInline(); | ||
89 | QModelIndex preFilterIndex(const QModelIndex &sourceIndex) const; | 92 | QModelIndex preFilterIndex(const QModelIndex &sourceIndex) const; | ||
90 | void updateActivityTaskCounts(); | 93 | void updateActivityTaskCounts(); | ||
▲ Show 20 Lines • Show All 342 Lines • ▼ Show 20 Line(s) | 426 | [this](const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles) { | |||
433 | } | 436 | } | ||
434 | } | 437 | } | ||
435 | ); | 438 | ); | ||
436 | 439 | | |||
437 | // Update anyTaskDemandsAttention on source model resets. | 440 | // Update anyTaskDemandsAttention on source model resets. | ||
438 | QObject::connect(groupingProxyModel, &QAbstractItemModel::modelReset, q, | 441 | QObject::connect(groupingProxyModel, &QAbstractItemModel::modelReset, q, | ||
439 | [this]() { updateAnyTaskDemandsAttention(); } | 442 | [this]() { updateAnyTaskDemandsAttention(); } | ||
440 | ); | 443 | ); | ||
441 | | ||||
442 | abstractTasksSourceModel = groupingProxyModel; | | |||
443 | q->setSourceModel(groupingProxyModel); | | |||
444 | | ||||
445 | QObject::connect(q, &QAbstractItemModel::rowsInserted, q, &TasksModel::updateLauncherCount); | | |||
446 | QObject::connect(q, &QAbstractItemModel::rowsRemoved, q, &TasksModel::updateLauncherCount); | | |||
447 | QObject::connect(q, &QAbstractItemModel::modelReset, q, &TasksModel::updateLauncherCount); | | |||
448 | | ||||
449 | QObject::connect(q, &QAbstractItemModel::rowsInserted, q, &TasksModel::countChanged); | | |||
450 | QObject::connect(q, &QAbstractItemModel::rowsRemoved, q, &TasksModel::countChanged); | | |||
451 | QObject::connect(q, &QAbstractItemModel::modelReset, q, &TasksModel::countChanged); | | |||
452 | } | 444 | } | ||
453 | 445 | | |||
454 | void TasksModel::Private::updateAnyTaskDemandsAttention() | 446 | void TasksModel::Private::updateAnyTaskDemandsAttention() | ||
455 | { | 447 | { | ||
456 | bool taskFound = false; | 448 | bool taskFound = false; | ||
457 | 449 | | |||
458 | for (int i = 0; i < groupingProxyModel->rowCount(); ++i) { | 450 | for (int i = 0; i < groupingProxyModel->rowCount(); ++i) { | ||
459 | if (groupingProxyModel->index(i, 0).data(AbstractTasksModel::IsDemandingAttention).toBool()) { | 451 | if (groupingProxyModel->index(i, 0).data(AbstractTasksModel::IsDemandingAttention).toBool()) { | ||
▲ Show 20 Lines • Show All 172 Lines • ▼ Show 20 Line(s) | 620 | for (int i = 1; i < childCount; ++i) { | |||
632 | const int childPos = sortedPreFilterRows.indexOf(preFilterChild.row()); | 624 | const int childPos = sortedPreFilterRows.indexOf(preFilterChild.row()); | ||
633 | const int insertPos = (leaderPos + i) + ((leaderPos + i) > childPos ? -1 : 0); | 625 | const int insertPos = (leaderPos + i) + ((leaderPos + i) > childPos ? -1 : 0); | ||
634 | sortedPreFilterRows.move(childPos, insertPos); | 626 | sortedPreFilterRows.move(childPos, insertPos); | ||
635 | } | 627 | } | ||
636 | } | 628 | } | ||
637 | 629 | | |||
638 | void TasksModel::Private::updateGroupInline() | 630 | void TasksModel::Private::updateGroupInline() | ||
639 | { | 631 | { | ||
632 | if (usedByQml && !componentComplete) { | ||||
davidedmundson: . | |||||
633 | return; | ||||
634 | } | ||||
635 | | ||||
636 | bool hadSourceModel = (q->sourceModel() != nullptr); | ||||
637 | | ||||
640 | if (q->groupMode() != GroupDisabled && groupInline) { | 638 | if (q->groupMode() != GroupDisabled && groupInline) { | ||
641 | if (flattenGroupsProxyModel) { | 639 | if (flattenGroupsProxyModel) { | ||
642 | return; | 640 | return; | ||
643 | } | 641 | } | ||
644 | 642 | | |||
645 | // Exempting tasks which demand attention from grouping is not | 643 | // Exempting tasks which demand attention from grouping is not | ||
646 | // necessary when all group children are shown inline anyway | 644 | // necessary when all group children are shown inline anyway | ||
647 | // and would interfere with our sort-tasks-together goals. | 645 | // and would interfere with our sort-tasks-together goals. | ||
648 | groupingProxyModel->setGroupDemandingAttention(true); | 646 | groupingProxyModel->setGroupDemandingAttention(true); | ||
649 | 647 | | |||
650 | // Likewise, ignore the window tasks threshold when making | 648 | // Likewise, ignore the window tasks threshold when making | ||
651 | // grouping decisions. | 649 | // grouping decisions. | ||
652 | groupingProxyModel->setWindowTasksThreshold(-1); | 650 | groupingProxyModel->setWindowTasksThreshold(-1); | ||
653 | 651 | | |||
654 | flattenGroupsProxyModel = new FlattenTaskGroupsProxyModel(q); | 652 | flattenGroupsProxyModel = new FlattenTaskGroupsProxyModel(q); | ||
655 | flattenGroupsProxyModel->setSourceModel(groupingProxyModel); | 653 | flattenGroupsProxyModel->setSourceModel(groupingProxyModel); | ||
656 | 654 | | |||
657 | abstractTasksSourceModel = flattenGroupsProxyModel; | 655 | abstractTasksSourceModel = flattenGroupsProxyModel; | ||
658 | q->setSourceModel(flattenGroupsProxyModel); | 656 | q->setSourceModel(flattenGroupsProxyModel); | ||
659 | 657 | | |||
660 | if (sortMode == SortManual) { | 658 | if (sortMode == SortManual) { | ||
661 | forceResort(); | 659 | forceResort(); | ||
662 | } | 660 | } | ||
663 | } else { | 661 | } else { | ||
664 | if (!flattenGroupsProxyModel) { | 662 | if (hadSourceModel && !flattenGroupsProxyModel) { | ||
665 | return; | 663 | return; | ||
666 | } | 664 | } | ||
667 | 665 | | |||
668 | groupingProxyModel->setGroupDemandingAttention(false); | 666 | groupingProxyModel->setGroupDemandingAttention(false); | ||
669 | groupingProxyModel->setWindowTasksThreshold(groupingWindowTasksThreshold); | 667 | groupingProxyModel->setWindowTasksThreshold(groupingWindowTasksThreshold); | ||
670 | 668 | | |||
671 | abstractTasksSourceModel = groupingProxyModel; | 669 | abstractTasksSourceModel = groupingProxyModel; | ||
672 | q->setSourceModel(groupingProxyModel); | 670 | q->setSourceModel(groupingProxyModel); | ||
673 | 671 | | |||
674 | delete flattenGroupsProxyModel; | 672 | delete flattenGroupsProxyModel; | ||
675 | flattenGroupsProxyModel = nullptr; | 673 | flattenGroupsProxyModel = nullptr; | ||
676 | 674 | | |||
677 | if (sortMode == SortManual) { | 675 | if (hadSourceModel && sortMode == SortManual) { | ||
678 | forceResort(); | 676 | forceResort(); | ||
679 | } | 677 | } | ||
680 | } | 678 | } | ||
679 | | ||||
680 | // Minor optimization: We only make these connections after we populate for | ||||
681 | // the first time to avoid some churn. | ||||
682 | if (!hadSourceModel) { | ||||
683 | QObject::connect(q, &QAbstractItemModel::rowsInserted, q, | ||||
684 | &TasksModel::updateLauncherCount, Qt::UniqueConnection); | ||||
685 | QObject::connect(q, &QAbstractItemModel::rowsRemoved, q, | ||||
686 | &TasksModel::updateLauncherCount, Qt::UniqueConnection); | ||||
687 | QObject::connect(q, &QAbstractItemModel::modelReset, q, | ||||
688 | &TasksModel::updateLauncherCount, Qt::UniqueConnection); | ||||
689 | | ||||
690 | QObject::connect(q, &QAbstractItemModel::rowsInserted, q, | ||||
691 | &TasksModel::countChanged, Qt::UniqueConnection); | ||||
692 | QObject::connect(q, &QAbstractItemModel::rowsRemoved, q, | ||||
693 | &TasksModel::countChanged, Qt::UniqueConnection); | ||||
694 | QObject::connect(q, &QAbstractItemModel::modelReset, q, | ||||
695 | &TasksModel::countChanged, Qt::UniqueConnection); | ||||
696 | } | ||||
681 | } | 697 | } | ||
682 | 698 | | |||
683 | QModelIndex TasksModel::Private::preFilterIndex(const QModelIndex &sourceIndex) const { | 699 | QModelIndex TasksModel::Private::preFilterIndex(const QModelIndex &sourceIndex) const { | ||
684 | // Only in inline grouping mode, we have an additional proxy layer. | 700 | // Only in inline grouping mode, we have an additional proxy layer. | ||
685 | if (flattenGroupsProxyModel) { | 701 | if (flattenGroupsProxyModel) { | ||
686 | return filterProxyModel->mapToSource(groupingProxyModel->mapToSource(flattenGroupsProxyModel->mapToSource(sourceIndex))); | 702 | return filterProxyModel->mapToSource(groupingProxyModel->mapToSource(flattenGroupsProxyModel->mapToSource(sourceIndex))); | ||
687 | } else { | 703 | } else { | ||
688 | return filterProxyModel->mapToSource(groupingProxyModel->mapToSource(sourceIndex)); | 704 | return filterProxyModel->mapToSource(groupingProxyModel->mapToSource(sourceIndex)); | ||
▲ Show 20 Lines • Show All 199 Lines • ▼ Show 20 Line(s) | |||||
888 | TasksModel::TasksModel(QObject *parent) | 904 | TasksModel::TasksModel(QObject *parent) | ||
889 | : QSortFilterProxyModel(parent) | 905 | : QSortFilterProxyModel(parent) | ||
890 | , d(new Private(this)) | 906 | , d(new Private(this)) | ||
891 | { | 907 | { | ||
892 | d->initModels(); | 908 | d->initModels(); | ||
893 | 909 | | |||
894 | // Start sorting. | 910 | // Start sorting. | ||
895 | sort(0); | 911 | sort(0); | ||
912 | | ||||
913 | // Private::updateGroupInline() sets our source model, populating the model. We | ||||
914 | // delay running this until the QML runtime had a chance to call our implementation | ||||
915 | // of QQmlParserStatus::classBegin(), setting Private::usedByQml to true. If used | ||||
916 | // by QML, Private::updateGroupInline() will abort if the component is not yet | ||||
917 | // complete, instead getting called through QQmlParserStatus::componentComplete() | ||||
918 | // only after all properties have been set. This avoids delegate churn in Qt Quick | ||||
919 | // views using the model. If not used by QML, Private::updateGroupInline() will run | ||||
920 | // directly. | ||||
921 | QTimer::singleShot(0, this, [this]() { | ||||
may as well QTimer:;singleShot(0, this, [this](... just in case you get deleted in the same space. davidedmundson: may as well QTimer:;singleShot(0, this, [this](...
just in case you get deleted in the same… | |||||
922 | d->updateGroupInline(); | ||||
923 | }); | ||||
896 | } | 924 | } | ||
897 | 925 | | |||
898 | TasksModel::~TasksModel() | 926 | TasksModel::~TasksModel() | ||
899 | { | 927 | { | ||
900 | } | 928 | } | ||
901 | 929 | | |||
902 | QHash<int, QByteArray> TasksModel::roleNames() const | 930 | QHash<int, QByteArray> TasksModel::roleNames() const | ||
903 | { | 931 | { | ||
▲ Show 20 Lines • Show All 775 Lines • ▼ Show 20 Line(s) | 1704 | } else { | |||
1679 | if (childRow < rowCount(parent)) { | 1707 | if (childRow < rowCount(parent)) { | ||
1680 | return parent.child(childRow, 0); | 1708 | return parent.child(childRow, 0); | ||
1681 | } | 1709 | } | ||
1682 | } | 1710 | } | ||
1683 | 1711 | | |||
1684 | return QModelIndex(); | 1712 | return QModelIndex(); | ||
1685 | } | 1713 | } | ||
1686 | 1714 | | |||
1715 | void TasksModel::classBegin() | ||||
1716 | { | ||||
1717 | d->usedByQml = true; | ||||
1718 | } | ||||
1719 | | ||||
1720 | void TasksModel::componentComplete() | ||||
1721 | { | ||||
1722 | d->componentComplete = true; | ||||
1723 | | ||||
1724 | // Sets our source model, populating the model. | ||||
1725 | d->updateGroupInline(); | ||||
1726 | } | ||||
1727 | | ||||
1687 | bool TasksModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const | 1728 | bool TasksModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const | ||
1688 | { | 1729 | { | ||
1689 | // All our filtering occurs at the top-level; anything below always | 1730 | // All our filtering occurs at the top-level; anything below always | ||
1690 | // goes through. | 1731 | // goes through. | ||
1691 | if (sourceParent.isValid()) { | 1732 | if (sourceParent.isValid()) { | ||
1692 | return true; | 1733 | return true; | ||
1693 | } | 1734 | } | ||
1694 | 1735 | | |||
▲ Show 20 Lines • Show All 59 Lines • Show Last 20 Lines |
.