Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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
lievenhey committed Sep 21, 2023
1 parent c897a66 commit 5e1dd33
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
@@ -29,6 +29,7 @@ enum class Tag : quint8
Processes,
Threads,
Tracepoints,
Favorites,
LAST_TAG,
};
const auto DATATAG_SHIFT = sizeof(Tag) * 8;
@@ -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:
@@ -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);
};
@@ -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) {
@@ -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();
@@ -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) {
@@ -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()));
}
@@ -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
@@ -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;
13 changes: 13 additions & 0 deletions src/models/timelinedelegate.cpp
Original file line number Diff line number Diff line change
@@ -13,6 +13,7 @@
#include <QHelpEvent>
#include <QMenu>
#include <QPainter>
#include <QSortFilterProxyModel>
#include <QToolTip>

#include "../util.h"
@@ -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);
}
}
@@ -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); });
1 change: 1 addition & 0 deletions src/models/timelinedelegate.h
Original file line number Diff line number Diff line change
@@ -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;
3 changes: 3 additions & 0 deletions src/timelinewidget.cpp
Original file line number Diff line number Diff line change
@@ -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;
2 changes: 1 addition & 1 deletion tests/modeltests/tst_models.cpp
Original file line number Diff line number Diff line change
@@ -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);

0 comments on commit 5e1dd33

Please sign in to comment.