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 Sep 21, 2023
1 parent c897a66 commit 5e1dd33
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 9 deletions.
42 changes: 34 additions & 8 deletions src/models/eventmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ enum class Tag : quint8
Processes,
Threads,
Tracepoints,
Favorites,
LAST_TAG,
};
const auto DATATAG_SHIFT = sizeof(Tag) * 8;
Expand Down Expand Up @@ -83,6 +84,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 @@ -95,11 +97,13 @@ int EventModel::rowCount(const QModelIndex& parent) const
return m_processes.size();
case 2:
return m_data.tracepoints.size();
case 3:
return m_favourites.size();
default:
Q_ASSERT(false);
}
case Tag::Root:
return m_data.tracepoints.isEmpty() ? 2 : 3;
return 4;
case Tag::LAST_TAG:
Q_ASSERT(false);
};
Expand Down Expand Up @@ -166,6 +170,8 @@ QVariant EventModel::data(const QModelIndex& index, int role) const
return tr("Processes");
case 2:
return tr("Tracepoints");
case 3:
return tr("Favorites");
}
} else if (role == Qt::ToolTipRole) {
if (index.row() == 0) {
Expand All @@ -175,6 +181,8 @@ QVariant EventModel::data(const QModelIndex& index, int role) const
return tr("Event timelines for the individual threads and processes.");
} else if (index.row() == 2) {
return tr("Event timelines for tracepoints");
} else if (index.row() == 3) {
return tr("A list of favourites to group important events");
}
} else if (role == SortRole) {
return index.row();
Expand Down Expand Up @@ -244,6 +252,10 @@ QVariant EventModel::data(const QModelIndex& index, int role) const
} else if (tag == Tag::Tracepoints) {
tracepoint = &m_data.tracepoints[index.row()];
Q_ASSERT(tracepoint);
} else if (tag == Tag::Favorites) {
auto& favourite = m_favourites[index.row()];
auto res = data(favourite, role);
return res;
}

if (role == ThreadStartRole) {
Expand Down Expand Up @@ -467,17 +479,21 @@ 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));
case Tag::Overview: // 2nd level children: Cpus and the Processes
if (parent.row() == 0)
if (parent.row() == 0) {
return createIndex(row, column, static_cast<quintptr>(Tag::Cpus));
else if (parent.row() == 1)
} else if (parent.row() == 1) {
return createIndex(row, column, static_cast<quintptr>(Tag::Processes));
else {
} else if (parent.row() == 2) {
return createIndex(row, column, static_cast<quintptr>(Tag::Tracepoints));
} else if (parent.row() == 3) {
return createIndex(row, column, static_cast<quintptr>(Tag::Favorites));
}
break;
case Tag::Processes: // 3rd level children: Threads
return createIndex(row, column, combineDataTag(Tag::Threads, parent.row()));
}
Expand All @@ -497,14 +513,24 @@ QModelIndex EventModel::parent(const QModelIndex& child) const
return createIndex(0, 0, static_cast<quintptr>(Tag::Overview));
case Tag::Processes:
return createIndex(1, 0, static_cast<quintptr>(Tag::Overview));
case Tag::Tracepoints: {
case Tag::Tracepoints:
return createIndex(2, 0, static_cast<qintptr>(Tag::Overview));
}
case Tag::Threads: {
case Tag::Favorites:
return createIndex(3, 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::addToFavourites(const QModelIndex& index)
{
const int position = m_favourites.size();
beginInsertRows(createIndex(3, 0), position, position + 1);
m_favourites.push_back(index);
endInsertRows();
beginResetModel();
endResetModel();
}
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 addToFavourites(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
13 changes: 13 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 @@ -133,6 +134,11 @@ Data::Events::const_iterator findEvent(const Data::Events::const_iterator& begin
auto it = std::lower_bound(begin, end, time, byTime);
// it points to the first item for which our predicate returns false, we want to find the item before that
// so decrement it if possible or return begin otherwise

// it can be end so it->time cases an buffer overflow
if (it == end) {
return end;
}
return (it == begin || it->time == time) ? it : (it - 1);
}
}
Expand Down Expand Up @@ -456,6 +462,13 @@ 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());
emit addToFavourites(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 addToFavourites(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::addToFavourites, this,
[eventModel](const QModelIndex& index) { eventModel->addToFavourites(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 5e1dd33

Please sign in to comment.