Skip to content

Commit 1daf271

Browse files
committed
add Favourites to TimeLineWidget
this allows the user to group important timelines together so that he can compare them better
1 parent 6c81a69 commit 1daf271

File tree

6 files changed

+90
-5
lines changed

6 files changed

+90
-5
lines changed

src/models/eventmodel.cpp

Lines changed: 72 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,19 @@ enum class Tag : quint8
2424
Processes,
2525
Threads,
2626
Tracepoints,
27+
Favorites,
2728
};
2829

2930
enum OverViewRow : quint8
3031
{
3132
Cpu_Row,
3233
Process_Row,
3334
Tracepoint_Row,
35+
Favorite_Row,
3436
};
35-
constexpr auto numRows = Tracepoint_Row + 1;
37+
constexpr auto numRows = Favorite_Row + 1;
3638

37-
constexpr auto LAST_TAG = Tag::Tracepoints;
39+
constexpr auto LAST_TAG = Tag::Favorites;
3840

3941
const auto DATATAG_SHIFT = sizeof(Tag) * 8;
4042
const auto DATATAG_UNSHIFT = (sizeof(quintptr) - sizeof(Tag)) * 8;
@@ -88,6 +90,7 @@ int EventModel::rowCount(const QModelIndex& parent) const
8890
case Tag::Cpus:
8991
case Tag::Threads:
9092
case Tag::Tracepoints:
93+
case Tag::Favorites:
9194
return 0;
9295
break;
9396
case Tag::Processes:
@@ -100,6 +103,8 @@ int EventModel::rowCount(const QModelIndex& parent) const
100103
return m_processes.size();
101104
case OverViewRow::Tracepoint_Row:
102105
return m_data.tracepoints.size();
106+
case OverViewRow::Favorite_Row:
107+
return m_favourites.size();
103108
default:
104109
Q_UNREACHABLE();
105110
}
@@ -168,6 +173,8 @@ QVariant EventModel::data(const QModelIndex& index, int role) const
168173
return tr("Processes");
169174
case OverViewRow::Tracepoint_Row:
170175
return tr("Tracepoints");
176+
case OverViewRow::Favorite_Row:
177+
return tr("Favorites");
171178
}
172179
} else if (role == Qt::ToolTipRole) {
173180
switch (static_cast<OverViewRow>(index.row())) {
@@ -178,6 +185,8 @@ QVariant EventModel::data(const QModelIndex& index, int role) const
178185
return tr("Event timelines for the individual threads and processes.");
179186
case OverViewRow::Tracepoint_Row:
180187
return tr("Event timelines for tracepoints");
188+
case OverViewRow::Favorite_Row:
189+
return tr("A list of favourites to group important events");
181190
}
182191
} else if (role == SortRole) {
183192
return index.row();
@@ -245,6 +254,9 @@ QVariant EventModel::data(const QModelIndex& index, int role) const
245254
Q_ASSERT(thread);
246255
} else if (tag == Tag::Tracepoints) {
247256
tracepoint = &m_data.tracepoints[index.row()];
257+
} else if (tag == Tag::Favorites) {
258+
const auto& favourite = m_favourites[index.row()];
259+
return data(favourite.siblingAtColumn(index.column()), role);
248260
}
249261

250262
if (role == ThreadStartRole) {
@@ -258,6 +270,9 @@ QVariant EventModel::data(const QModelIndex& index, int role) const
258270
case Tag::Processes:
259271
case Tag::Tracepoints:
260272
return m_time.start;
273+
case Tag::Favorites:
274+
// they are handled elsewhere
275+
Q_UNREACHABLE();
261276
}
262277
} else if (role == ThreadEndRole) {
263278
switch (tag) {
@@ -270,6 +285,9 @@ QVariant EventModel::data(const QModelIndex& index, int role) const
270285
case Tag::Processes:
271286
case Tag::Tracepoints:
272287
return m_time.end;
288+
case Tag::Favorites:
289+
// they are handled elsewhere
290+
Q_UNREACHABLE();
273291
}
274292
} else if (role == ThreadNameRole) {
275293
switch (tag) {
@@ -283,6 +301,9 @@ QVariant EventModel::data(const QModelIndex& index, int role) const
283301
case Tag::Processes:
284302
case Tag::Tracepoints:
285303
return {};
304+
case Tag::Favorites:
305+
// they are handled elsewhere
306+
Q_UNREACHABLE();
286307
}
287308
} else if (role == ThreadIdRole) {
288309
switch (tag) {
@@ -295,6 +316,9 @@ QVariant EventModel::data(const QModelIndex& index, int role) const
295316
case Tag::Processes:
296317
case Tag::Tracepoints:
297318
return Data::INVALID_TID;
319+
case Tag::Favorites:
320+
// they are handled elsewhere
321+
Q_UNREACHABLE();
298322
}
299323
} else if (role == ProcessIdRole) {
300324
switch (tag) {
@@ -307,6 +331,9 @@ QVariant EventModel::data(const QModelIndex& index, int role) const
307331
case Tag::Processes:
308332
case Tag::Tracepoints:
309333
return Data::INVALID_PID;
334+
case Tag::Favorites:
335+
// they are handled elsewhere
336+
Q_UNREACHABLE();
310337
}
311338
} else if (role == CpuIdRole) {
312339
switch (tag) {
@@ -319,6 +346,9 @@ QVariant EventModel::data(const QModelIndex& index, int role) const
319346
case Tag::Threads:
320347
case Tag::Tracepoints:
321348
return Data::INVALID_CPU_ID;
349+
case Tag::Favorites:
350+
// they are handled elsewhere
351+
Q_UNREACHABLE();
322352
}
323353
} else if (role == EventsRole) {
324354
switch (tag) {
@@ -333,6 +363,9 @@ QVariant EventModel::data(const QModelIndex& index, int role) const
333363
case Tag::Overview:
334364
case Tag::Processes:
335365
return QVariant::fromValue(Data::Events());
366+
case Tag::Favorites:
367+
// they are handled elsewhere
368+
Q_UNREACHABLE();
336369
}
337370
} else if (role == SortRole) {
338371
if (index.column() == ThreadColumn) {
@@ -348,6 +381,9 @@ QVariant EventModel::data(const QModelIndex& index, int role) const
348381
case Tag::Overview:
349382
case Tag::Processes:
350383
return {};
384+
case Tag::Favorites:
385+
// they are handled elsewhere
386+
Q_UNREACHABLE();
351387
}
352388
} else {
353389
switch (tag) {
@@ -362,6 +398,9 @@ QVariant EventModel::data(const QModelIndex& index, int role) const
362398
case Tag::Overview:
363399
case Tag::Processes:
364400
return {};
401+
case Tag::Favorites:
402+
// they are handled elsewhere
403+
Q_UNREACHABLE();
365404
}
366405
}
367406
}
@@ -381,6 +420,9 @@ QVariant EventModel::data(const QModelIndex& index, int role) const
381420
case Tag::Overview:
382421
case Tag::Processes:
383422
return {};
423+
case Tag::Favorites:
424+
// they are handled elsewhere
425+
Q_UNREACHABLE();
384426
}
385427
} else if (role == Qt::ToolTipRole) {
386428
QString tooltip;
@@ -421,6 +463,9 @@ QVariant EventModel::data(const QModelIndex& index, int role) const
421463
case Tag::Overview:
422464
case Tag::Processes:
423465
break;
466+
case Tag::Favorites:
467+
// they are handled elsewhere
468+
Q_UNREACHABLE();
424469
}
425470

426471
tooltip += tr("Number of Events: %1 (%2% of the total)")
@@ -442,6 +487,9 @@ QVariant EventModel::data(const QModelIndex& index, int role) const
442487
case Tag::Overview:
443488
case Tag::Processes:
444489
return {};
490+
case Tag::Favorites:
491+
// they are handled elsewhere
492+
Q_UNREACHABLE();
445493
}
446494
}
447495
break;
@@ -456,6 +504,8 @@ QVariant EventModel::data(const QModelIndex& index, int role) const
456504
void EventModel::setData(const Data::EventResults& data)
457505
{
458506
beginResetModel();
507+
m_favourites.clear();
508+
459509
m_data = data;
460510
m_totalEvents = 0;
461511
m_maxCost = 0;
@@ -516,6 +566,7 @@ QModelIndex EventModel::index(int row, int column, const QModelIndex& parent) co
516566
case Tag::Cpus:
517567
case Tag::Tracepoints:
518568
case Tag::Threads:
569+
case Tag::Favorites:
519570
break;
520571
case Tag::Root: // root has the 1st level children: Overview
521572
return createIndex(row, column, static_cast<quintptr>(Tag::Overview));
@@ -527,6 +578,8 @@ QModelIndex EventModel::index(int row, int column, const QModelIndex& parent) co
527578
return createIndex(row, column, static_cast<quintptr>(Tag::Processes));
528579
case OverViewRow::Tracepoint_Row:
529580
return createIndex(row, column, static_cast<quintptr>(Tag::Tracepoints));
581+
case OverViewRow::Favorite_Row:
582+
return createIndex(row, column, static_cast<quintptr>(Tag::Favorites));
530583
}
531584
Q_UNREACHABLE();
532585
case Tag::Processes: // 3rd level children: Threads
@@ -549,11 +602,26 @@ QModelIndex EventModel::parent(const QModelIndex& child) const
549602
return createIndex(OverViewRow::Process_Row, 0, static_cast<quintptr>(Tag::Overview));
550603
case Tag::Tracepoints:
551604
return createIndex(OverViewRow::Tracepoint_Row, 0, static_cast<qintptr>(Tag::Overview));
552-
case Tag::Threads: {
605+
case Tag::Favorites:
606+
return createIndex(OverViewRow::Favorite_Row, 0, static_cast<qintptr>(Tag::Overview));
607+
case Tag::Threads:
553608
const auto parentRow = tagData(child.internalId());
554609
return createIndex(parentRow, 0, static_cast<quintptr>(Tag::Processes));
555610
}
556-
}
557611

558612
return {};
559613
}
614+
615+
void EventModel::addToFavorites(const QModelIndex& index)
616+
{
617+
Q_ASSERT(index.model() == this);
618+
619+
if (m_favourites.contains(index)) {
620+
return;
621+
}
622+
623+
const int position = m_favourites.size();
624+
beginInsertRows(createIndex(Favorite_Row, 0, static_cast<quintptr>(Tag::Overview)), position, position);
625+
m_favourites.push_back(index);
626+
endInsertRows();
627+
}

src/models/eventmodel.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,13 @@ class EventModel : public QAbstractItemModel
7171
QString name;
7272
};
7373

74+
public:
75+
void addToFavorites(const QModelIndex& index);
76+
7477
private:
7578
Data::EventResults m_data;
7679
QVector<Process> m_processes;
80+
QVector<QModelIndex> m_favourites;
7781
Data::TimeRange m_time;
7882
quint64 m_totalOnCpuTime = 0;
7983
quint64 m_totalOffCpuTime = 0;

src/models/timelinedelegate.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <QHelpEvent>
1414
#include <QMenu>
1515
#include <QPainter>
16+
#include <QSortFilterProxyModel>
1617
#include <QToolTip>
1718

1819
#include "../util.h"
@@ -459,6 +460,14 @@ bool TimeLineDelegate::eventFilter(QObject* watched, QEvent* event)
459460
const auto isMainThread = threadStartTime == minTime && threadEndTime == maxTime;
460461
const auto cpuId = index.data(EventModel::CpuIdRole).value<quint32>();
461462
const auto numCpus = index.data(EventModel::NumCpusRole).value<uint>();
463+
464+
contextMenu->addAction(QIcon::fromTheme(QStringLiteral("favorite")), tr("Add to favorites"), this,
465+
[this, index] {
466+
auto model = qobject_cast<const QSortFilterProxyModel*>(index.model());
467+
Q_ASSERT(model);
468+
emit addToFavorites(model->mapToSource(index));
469+
});
470+
462471
if (isTimeSpanSelected && (minTime != timeSlice.start || maxTime != timeSlice.end)) {
463472
contextMenu->addAction(QIcon::fromTheme(QStringLiteral("zoom-in")), tr("Zoom In On Selection"), this,
464473
[this, timeSlice]() { m_filterAndZoomStack->zoomIn(timeSlice); });

src/models/timelinedelegate.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ class TimeLineDelegate : public QStyledItemDelegate
6464

6565
signals:
6666
void stacksHovered(const QSet<qint32>& stacks);
67+
void addToFavorites(const QModelIndex& index);
6768

6869
protected:
6970
bool eventFilter(QObject* watched, QEvent* event) override;

src/timelinewidget.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,9 @@ TimeLineWidget::TimeLineWidget(PerfParser* parser, QMenu* filterMenu, FilterAndZ
110110
m_timeLineDelegate->setEventType(typeId);
111111
});
112112

113+
connect(m_timeLineDelegate, &TimeLineDelegate::addToFavorites, this,
114+
[eventModel](const QModelIndex& index) { eventModel->addToFavorites(index); });
115+
113116
connect(m_timeLineDelegate, &TimeLineDelegate::stacksHovered, this, [this](const QSet<qint32>& stackIds) {
114117
if (stackIds.isEmpty()) {
115118
++m_currentHoverStacksJobId;

tests/modeltests/tst_models.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -537,7 +537,7 @@ private slots:
537537
model.setData(events);
538538

539539
QCOMPARE(model.columnCount(), static_cast<int>(EventModel::NUM_COLUMNS));
540-
QCOMPARE(model.rowCount(), 2);
540+
QCOMPARE(model.rowCount(), 4);
541541

542542
auto simplifiedEvents = events;
543543
simplifiedEvents.cpus.remove(1);

0 commit comments

Comments
 (0)