diff --git a/src/models/eventmodel.cpp b/src/models/eventmodel.cpp index b4a3e01a..c0cf3f05 100644 --- a/src/models/eventmodel.cpp +++ b/src/models/eventmodel.cpp @@ -187,6 +187,8 @@ QVariant EventModel::data(const QModelIndex& index, int role) const } } else if (role == SortRole) { return index.row(); + } else if (role == IsFavoritesSectionRole) { + return index.row() == OverviewRow::FavoriteRow; } return {}; } else if (tag == Tag::Processes) { diff --git a/src/models/eventmodel.h b/src/models/eventmodel.h index bd2b9567..23e7a552 100644 --- a/src/models/eventmodel.h +++ b/src/models/eventmodel.h @@ -43,6 +43,7 @@ class EventModel : public QAbstractItemModel TotalCostsRole, EventResultsRole, IsFavoriteRole, + IsFavoritesSectionRole, }; int rowCount(const QModelIndex& parent = {}) const override; diff --git a/src/models/eventmodelproxy.cpp b/src/models/eventmodelproxy.cpp index 12a547ba..19e96a81 100644 --- a/src/models/eventmodelproxy.cpp +++ b/src/models/eventmodelproxy.cpp @@ -16,6 +16,7 @@ EventModelProxy::EventModelProxy(QObject* parent) setSortRole(EventModel::SortRole); setFilterKeyColumn(EventModel::ThreadColumn); setFilterRole(Qt::DisplayRole); + sort(0); } EventModelProxy::~EventModelProxy() = default; @@ -41,3 +42,18 @@ bool EventModelProxy::filterAcceptsRow(int source_row, const QModelIndex& source return QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent); } + +bool EventModelProxy::lessThan(const QModelIndex& source_left, const QModelIndex& source_right) const +{ + const auto lhsIsFavoritesSection = source_left.data(EventModel::IsFavoritesSectionRole).toBool(); + const auto rhsIsFavoritesSection = source_right.data(EventModel::IsFavoritesSectionRole).toBool(); + if (lhsIsFavoritesSection != rhsIsFavoritesSection) { + // always put the favorites section on the top + if (sortOrder() == Qt::AscendingOrder) + return lhsIsFavoritesSection > rhsIsFavoritesSection; + else + return lhsIsFavoritesSection < rhsIsFavoritesSection; + } + + return QSortFilterProxyModel::lessThan(source_left, source_right); +} diff --git a/src/models/eventmodelproxy.h b/src/models/eventmodelproxy.h index a720fd58..eaedf37a 100644 --- a/src/models/eventmodelproxy.h +++ b/src/models/eventmodelproxy.h @@ -18,4 +18,5 @@ class EventModelProxy : public QSortFilterProxyModel protected: bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const override; + bool lessThan(const QModelIndex& source_left, const QModelIndex& source_right) const override; }; diff --git a/tests/modeltests/tst_models.cpp b/tests/modeltests/tst_models.cpp index 48358956..f9d3e69b 100644 --- a/tests/modeltests/tst_models.cpp +++ b/tests/modeltests/tst_models.cpp @@ -701,7 +701,26 @@ private slots: QCOMPARE(proxy.rowCount(), 3); + { + // verify that favorites remain at the top + QCOMPARE(proxy.sortOrder(), Qt::AscendingOrder); + QCOMPARE(proxy.sortColumn(), 0); + + // favorites on top + QVERIFY(proxy.index(0, 0, proxy.index(0, 0)).data(EventModel::IsFavoriteRole).toBool()); + // followed by CPUs + QCOMPARE(proxy.index(0, 0, proxy.index(1, 0)).data(EventModel::CpuIdRole).value(), 1); + + proxy.sort(0, Qt::DescendingOrder); + + // favorites are still on top + QVERIFY(proxy.index(0, 0, proxy.index(0, 0)).data(EventModel::IsFavoriteRole).toBool()); + // followed by processes + QCOMPARE(proxy.index(0, 0, proxy.index(1, 0)).data(EventModel::ProcessIdRole).value(), 1234); + } + model.removeFromFavorites(model.index(0, 0, favoritesIndex)); + QCOMPARE(proxy.rowCount(), 2); } @@ -952,9 +971,9 @@ private slots: { Data::EventResults events; events.cpus.resize(3); - events.cpus[0].cpuId = 0; - events.cpus[1].cpuId = 1; // empty - events.cpus[2].cpuId = 2; + events.cpus[0].cpuId = 1; + events.cpus[1].cpuId = 2; // empty + events.cpus[2].cpuId = 3; const quint64 endTime = 1000; const quint64 deltaTime = 10; @@ -997,13 +1016,13 @@ private slots: event.time = time; ++costSummary.sampleCount; costSummary.totalPeriod += event.cost; - events.cpus[cpuId].events << event; + events.cpus[cpuId - 1].events << event; return event; }; for (quint64 time = 0; time < endTime; time += deltaTime) { - thread1.events << generateEvent(time, 0); + thread1.events << generateEvent(time, 1); if (thread2.time.contains(time)) { - thread2.events << generateEvent(time, 2); + thread2.events << generateEvent(time, 3); } } events.totalCosts = {costSummary};