Skip to content

Commit

Permalink
add Favourites to TimeLineWidget
Browse files Browse the repository at this point in the history
this allows the user to group important timelines together so that he
can compare them better
  • Loading branch information
lievenhey committed Oct 2, 2023
1 parent 6c81a69 commit 1daf271
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 5 deletions.
76 changes: 72 additions & 4 deletions src/models/eventmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,19 @@ enum class Tag : quint8
Processes,
Threads,
Tracepoints,
Favorites,
};

enum OverViewRow : quint8
{
Cpu_Row,
Process_Row,
Tracepoint_Row,
Favorite_Row,
};
constexpr auto numRows = Tracepoint_Row + 1;
constexpr auto numRows = Favorite_Row + 1;

constexpr auto LAST_TAG = Tag::Tracepoints;
constexpr auto LAST_TAG = Tag::Favorites;

const auto DATATAG_SHIFT = sizeof(Tag) * 8;
const auto DATATAG_UNSHIFT = (sizeof(quintptr) - sizeof(Tag)) * 8;
Expand Down Expand Up @@ -88,6 +90,7 @@ int EventModel::rowCount(const QModelIndex& parent) const
case Tag::Cpus:
case Tag::Threads:
case Tag::Tracepoints:
case Tag::Favorites:
return 0;
break;
case Tag::Processes:
Expand All @@ -100,6 +103,8 @@ int EventModel::rowCount(const QModelIndex& parent) const
return m_processes.size();
case OverViewRow::Tracepoint_Row:
return m_data.tracepoints.size();
case OverViewRow::Favorite_Row:
return m_favourites.size();
default:
Q_UNREACHABLE();
}
Expand Down Expand Up @@ -168,6 +173,8 @@ QVariant EventModel::data(const QModelIndex& index, int role) const
return tr("Processes");
case OverViewRow::Tracepoint_Row:
return tr("Tracepoints");
case OverViewRow::Favorite_Row:
return tr("Favorites");
}
} else if (role == Qt::ToolTipRole) {
switch (static_cast<OverViewRow>(index.row())) {
Expand All @@ -178,6 +185,8 @@ QVariant EventModel::data(const QModelIndex& index, int role) const
return tr("Event timelines for the individual threads and processes.");
case OverViewRow::Tracepoint_Row:
return tr("Event timelines for tracepoints");
case OverViewRow::Favorite_Row:
return tr("A list of favourites to group important events");
}
} else if (role == SortRole) {
return index.row();
Expand Down Expand Up @@ -245,6 +254,9 @@ QVariant EventModel::data(const QModelIndex& index, int role) const
Q_ASSERT(thread);
} else if (tag == Tag::Tracepoints) {
tracepoint = &m_data.tracepoints[index.row()];
} else if (tag == Tag::Favorites) {
const auto& favourite = m_favourites[index.row()];
return data(favourite.siblingAtColumn(index.column()), role);
}

if (role == ThreadStartRole) {
Expand All @@ -258,6 +270,9 @@ QVariant EventModel::data(const QModelIndex& index, int role) const
case Tag::Processes:
case Tag::Tracepoints:
return m_time.start;
case Tag::Favorites:
// they are handled elsewhere
Q_UNREACHABLE();
}
} else if (role == ThreadEndRole) {
switch (tag) {
Expand All @@ -270,6 +285,9 @@ QVariant EventModel::data(const QModelIndex& index, int role) const
case Tag::Processes:
case Tag::Tracepoints:
return m_time.end;
case Tag::Favorites:
// they are handled elsewhere
Q_UNREACHABLE();
}
} else if (role == ThreadNameRole) {
switch (tag) {
Expand All @@ -283,6 +301,9 @@ QVariant EventModel::data(const QModelIndex& index, int role) const
case Tag::Processes:
case Tag::Tracepoints:
return {};
case Tag::Favorites:
// they are handled elsewhere
Q_UNREACHABLE();
}
} else if (role == ThreadIdRole) {
switch (tag) {
Expand All @@ -295,6 +316,9 @@ QVariant EventModel::data(const QModelIndex& index, int role) const
case Tag::Processes:
case Tag::Tracepoints:
return Data::INVALID_TID;
case Tag::Favorites:
// they are handled elsewhere
Q_UNREACHABLE();
}
} else if (role == ProcessIdRole) {
switch (tag) {
Expand All @@ -307,6 +331,9 @@ QVariant EventModel::data(const QModelIndex& index, int role) const
case Tag::Processes:
case Tag::Tracepoints:
return Data::INVALID_PID;
case Tag::Favorites:
// they are handled elsewhere
Q_UNREACHABLE();
}
} else if (role == CpuIdRole) {
switch (tag) {
Expand All @@ -319,6 +346,9 @@ QVariant EventModel::data(const QModelIndex& index, int role) const
case Tag::Threads:
case Tag::Tracepoints:
return Data::INVALID_CPU_ID;
case Tag::Favorites:
// they are handled elsewhere
Q_UNREACHABLE();
}
} else if (role == EventsRole) {
switch (tag) {
Expand All @@ -333,6 +363,9 @@ QVariant EventModel::data(const QModelIndex& index, int role) const
case Tag::Overview:
case Tag::Processes:
return QVariant::fromValue(Data::Events());
case Tag::Favorites:
// they are handled elsewhere
Q_UNREACHABLE();
}
} else if (role == SortRole) {
if (index.column() == ThreadColumn) {
Expand All @@ -348,6 +381,9 @@ QVariant EventModel::data(const QModelIndex& index, int role) const
case Tag::Overview:
case Tag::Processes:
return {};
case Tag::Favorites:
// they are handled elsewhere
Q_UNREACHABLE();
}
} else {
switch (tag) {
Expand All @@ -362,6 +398,9 @@ QVariant EventModel::data(const QModelIndex& index, int role) const
case Tag::Overview:
case Tag::Processes:
return {};
case Tag::Favorites:
// they are handled elsewhere
Q_UNREACHABLE();
}
}
}
Expand All @@ -381,6 +420,9 @@ QVariant EventModel::data(const QModelIndex& index, int role) const
case Tag::Overview:
case Tag::Processes:
return {};
case Tag::Favorites:
// they are handled elsewhere
Q_UNREACHABLE();
}
} else if (role == Qt::ToolTipRole) {
QString tooltip;
Expand Down Expand Up @@ -421,6 +463,9 @@ QVariant EventModel::data(const QModelIndex& index, int role) const
case Tag::Overview:
case Tag::Processes:
break;
case Tag::Favorites:
// they are handled elsewhere
Q_UNREACHABLE();
}

tooltip += tr("Number of Events: %1 (%2% of the total)")
Expand All @@ -442,6 +487,9 @@ QVariant EventModel::data(const QModelIndex& index, int role) const
case Tag::Overview:
case Tag::Processes:
return {};
case Tag::Favorites:
// they are handled elsewhere
Q_UNREACHABLE();
}
}
break;
Expand All @@ -456,6 +504,8 @@ QVariant EventModel::data(const QModelIndex& index, int role) const
void EventModel::setData(const Data::EventResults& data)
{
beginResetModel();
m_favourites.clear();

m_data = data;
m_totalEvents = 0;
m_maxCost = 0;
Expand Down Expand Up @@ -516,6 +566,7 @@ QModelIndex EventModel::index(int row, int column, const QModelIndex& parent) co
case Tag::Cpus:
case Tag::Tracepoints:
case Tag::Threads:
case Tag::Favorites:
break;
case Tag::Root: // root has the 1st level children: Overview
return createIndex(row, column, static_cast<quintptr>(Tag::Overview));
Expand All @@ -527,6 +578,8 @@ QModelIndex EventModel::index(int row, int column, const QModelIndex& parent) co
return createIndex(row, column, static_cast<quintptr>(Tag::Processes));
case OverViewRow::Tracepoint_Row:
return createIndex(row, column, static_cast<quintptr>(Tag::Tracepoints));
case OverViewRow::Favorite_Row:
return createIndex(row, column, static_cast<quintptr>(Tag::Favorites));
}
Q_UNREACHABLE();
case Tag::Processes: // 3rd level children: Threads
Expand All @@ -549,11 +602,26 @@ QModelIndex EventModel::parent(const QModelIndex& child) const
return createIndex(OverViewRow::Process_Row, 0, static_cast<quintptr>(Tag::Overview));
case Tag::Tracepoints:
return createIndex(OverViewRow::Tracepoint_Row, 0, static_cast<qintptr>(Tag::Overview));
case Tag::Threads: {
case Tag::Favorites:
return createIndex(OverViewRow::Favorite_Row, 0, static_cast<qintptr>(Tag::Overview));
case Tag::Threads:
const auto parentRow = tagData(child.internalId());
return createIndex(parentRow, 0, static_cast<quintptr>(Tag::Processes));
}
}

return {};
}

void EventModel::addToFavorites(const QModelIndex& index)
{
Q_ASSERT(index.model() == this);

if (m_favourites.contains(index)) {
return;
}

const int position = m_favourites.size();
beginInsertRows(createIndex(Favorite_Row, 0, static_cast<quintptr>(Tag::Overview)), position, position);
m_favourites.push_back(index);
endInsertRows();
}
4 changes: 4 additions & 0 deletions src/models/eventmodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,13 @@ class EventModel : public QAbstractItemModel
QString name;
};

public:
void addToFavorites(const QModelIndex& index);

private:
Data::EventResults m_data;
QVector<Process> m_processes;
QVector<QModelIndex> m_favourites;
Data::TimeRange m_time;
quint64 m_totalOnCpuTime = 0;
quint64 m_totalOffCpuTime = 0;
Expand Down
9 changes: 9 additions & 0 deletions src/models/timelinedelegate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <QHelpEvent>
#include <QMenu>
#include <QPainter>
#include <QSortFilterProxyModel>
#include <QToolTip>

#include "../util.h"
Expand Down Expand Up @@ -459,6 +460,14 @@ bool TimeLineDelegate::eventFilter(QObject* watched, QEvent* event)
const auto isMainThread = threadStartTime == minTime && threadEndTime == maxTime;
const auto cpuId = index.data(EventModel::CpuIdRole).value<quint32>();
const auto numCpus = index.data(EventModel::NumCpusRole).value<uint>();

contextMenu->addAction(QIcon::fromTheme(QStringLiteral("favorite")), tr("Add to favorites"), this,
[this, index] {
auto model = qobject_cast<const QSortFilterProxyModel*>(index.model());
Q_ASSERT(model);
emit addToFavorites(model->mapToSource(index));
});

if (isTimeSpanSelected && (minTime != timeSlice.start || maxTime != timeSlice.end)) {
contextMenu->addAction(QIcon::fromTheme(QStringLiteral("zoom-in")), tr("Zoom In On Selection"), this,
[this, timeSlice]() { m_filterAndZoomStack->zoomIn(timeSlice); });
Expand Down
1 change: 1 addition & 0 deletions src/models/timelinedelegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ class TimeLineDelegate : public QStyledItemDelegate

signals:
void stacksHovered(const QSet<qint32>& stacks);
void addToFavorites(const QModelIndex& index);

protected:
bool eventFilter(QObject* watched, QEvent* event) override;
Expand Down
3 changes: 3 additions & 0 deletions src/timelinewidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@ TimeLineWidget::TimeLineWidget(PerfParser* parser, QMenu* filterMenu, FilterAndZ
m_timeLineDelegate->setEventType(typeId);
});

connect(m_timeLineDelegate, &TimeLineDelegate::addToFavorites, this,
[eventModel](const QModelIndex& index) { eventModel->addToFavorites(index); });

connect(m_timeLineDelegate, &TimeLineDelegate::stacksHovered, this, [this](const QSet<qint32>& stackIds) {
if (stackIds.isEmpty()) {
++m_currentHoverStacksJobId;
Expand Down
2 changes: 1 addition & 1 deletion tests/modeltests/tst_models.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -537,7 +537,7 @@ private slots:
model.setData(events);

QCOMPARE(model.columnCount(), static_cast<int>(EventModel::NUM_COLUMNS));
QCOMPARE(model.rowCount(), 2);
QCOMPARE(model.rowCount(), 4);

auto simplifiedEvents = events;
simplifiedEvents.cpus.remove(1);
Expand Down

0 comments on commit 1daf271

Please sign in to comment.