Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Diff view #330

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ set(HOTSPOT_SRCS
resultscallercalleepage.cpp
resultsdisassemblypage.cpp
resultsutil.cpp
resultspagediff.cpp
costheaderview.cpp
timelinewidget.cpp
dockwidgetsetup.cpp
Expand All @@ -52,6 +53,7 @@ set(HOTSPOT_SRCS
perfoutputwidgettext.cpp
perfoutputwidgetkonsole.cpp
costcontextmenu.cpp
diffreportdialog.cpp
# ui files:
mainwindow.ui
aboutdialog.ui
Expand All @@ -64,13 +66,15 @@ set(HOTSPOT_SRCS
resultsflamegraphpage.ui
resultscallercalleepage.ui
resultsdisassemblypage.ui
resultspagediff.ui
timelinewidget.ui
unwindsettingspage.ui
flamegraphsettingspage.ui
debuginfodpage.ui
callgraphwidget.ui
callgraphsettingspage.ui
frequencypage.ui
diffreportdialog.ui
# resources:
resources.qrc
)
Expand Down
33 changes: 33 additions & 0 deletions src/diffreportdialog.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
SPDX-FileCopyrightText: Lieven Hey <[email protected]>
SPDX-FileCopyrightText: 2022 Klarälvdalens Datakonsult AB, a KDAB Group company, [email protected]
SPDX-License-Identifier: GPL-2.0-or-later
*/

#include "diffreportdialog.h"
lievenhey marked this conversation as resolved.
Show resolved Hide resolved
#include "ui_diffreportdialog.h"

DiffReportDialog::DiffReportDialog(QWidget* parent)
: QDialog(parent)
, ui(new Ui::DiffReportDialog)
{
ui->setupUi(this);
const auto filterString = QStringLiteral("perf*.data\nperf.data*");
ui->file_a->setFilter(filterString);
ui->file_b->setFilter(filterString);

connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accepted);
connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &QDialog::close);
}

DiffReportDialog::~DiffReportDialog() = default;

QString DiffReportDialog::fileA() const
{
return ui->file_a->url().toLocalFile();
}

QString DiffReportDialog::fileB() const
{
return ui->file_b->url().toLocalFile();
}
27 changes: 27 additions & 0 deletions src/diffreportdialog.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
SPDX-FileCopyrightText: Lieven Hey <[email protected]>
SPDX-FileCopyrightText: 2022 Klarälvdalens Datakonsult AB, a KDAB Group company, [email protected]
SPDX-License-Identifier: GPL-2.0-or-later
*/

#pragma once

#include <QDialog>

namespace Ui {
class DiffReportDialog;
}

class DiffReportDialog : public QDialog
{
Q_OBJECT
public:
explicit DiffReportDialog(QWidget* parent = nullptr);
~DiffReportDialog();

QString fileA() const;
QString fileB() const;

private:
QScopedPointer<Ui::DiffReportDialog> ui;
};
70 changes: 70 additions & 0 deletions src/diffreportdialog.ui
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DiffReportDialog</class>
<widget class="QDialog" name="DiffReportDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</height>
</rect>
</property>
<property name="windowTitle">
<string>Diff two files</string>
</property>
<property name="sizeGripEnabled">
<bool>false</bool>
</property>
<layout class="QFormLayout" name="formLayout">
<property name="leftMargin">
<number>6</number>
</property>
<property name="topMargin">
<number>6</number>
</property>
<property name="rightMargin">
<number>6</number>
</property>
<property name="bottomMargin">
<number>6</number>
</property>
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>File A:</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>File B:</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="KUrlRequester" name="file_a"/>
</item>
<item row="1" column="1">
<widget class="KUrlRequester" name="file_b"/>
</item>
<item row="2" column="1">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Open</set>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>KUrlRequester</class>
<extends>QWidget</extends>
<header>kurlrequester.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>
12 changes: 12 additions & 0 deletions src/dockwidgetsetup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@

#include "dockwidgetsetup.h"

#include <QAction>

#include <kddockwidgets/Config.h>
#include <kddockwidgets/DockWidget.h>
#include <kddockwidgets/FrameworkWidgetFactory.h>
#include <kddockwidgets/MainWindow.h>

Expand Down Expand Up @@ -53,4 +56,13 @@ KDDockWidgets::MainWindow* createDockingArea(const QString& id, QWidget* parent)
return ret;
}

KDDockWidgets::DockWidget* dockify(QWidget* widget, const QString& id, const QString& title, const QString& shortcut)
{
auto* dock = new KDDockWidgets::DockWidget(id);
dock->setWidget(widget);
dock->setTitle(title);
dock->toggleAction()->setShortcut(shortcut);
return dock;
}

#include "dockwidgetsetup.moc"
2 changes: 2 additions & 0 deletions src/dockwidgetsetup.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@

namespace KDDockWidgets {
class MainWindow;
class DockWidget;
}

class QWidget;
class QString;

void setupDockWidgets();
KDDockWidgets::MainWindow* createDockingArea(const QString& id, QWidget* parent);
KDDockWidgets::DockWidget* dockify(QWidget* widget, const QString& id, const QString& title, const QString& shortcut);
13 changes: 13 additions & 0 deletions src/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include "costcontextmenu.h"
#include "recordpage.h"
#include "resultspage.h"
#include "resultspagediff.h"
#include "settings.h"
#include "settingsdialog.h"
#include "startpage.h"
Expand Down Expand Up @@ -45,6 +46,7 @@
#include <kddockwidgets/LayoutSaver.h>

#include "aboutdialog.h"
#include "diffreportdialog.h"

#include "parsers/perf/perfparser.h"

Expand Down Expand Up @@ -103,13 +105,16 @@ MainWindow::MainWindow(QWidget* parent)
, m_startPage(new StartPage(this))
, m_recordPage(new RecordPage(this))
, m_resultsPage(new ResultsPage(m_parser, this))
, m_resultsPageDiff(new ResultsPageDiff(this))
, m_settingsDialog(new SettingsDialog(this))
, m_diffReportDialog(new DiffReportDialog(this))
{
ui->setupUi(this);

m_pageStack->addWidget(m_startPage);
m_pageStack->addWidget(m_resultsPage);
m_pageStack->addWidget(m_recordPage);
m_pageStack->addWidget(m_resultsPageDiff);

QVBoxLayout* layout = new QVBoxLayout;
layout->setContentsMargins(0, 0, 0, 0);
Expand Down Expand Up @@ -137,6 +142,7 @@ MainWindow::MainWindow(QWidget* parent)
connect(m_startPage, &StartPage::recordButtonClicked, this, &MainWindow::onRecordButtonClicked);
connect(m_startPage, &StartPage::stopParseButtonClicked, this,
static_cast<void (MainWindow::*)()>(&MainWindow::clear));
connect(m_startPage, &StartPage::createDiffReportButtonClicked, this, [this] { m_diffReportDialog->show(); });
connect(m_parser, &PerfParser::progress, m_startPage, &StartPage::onParseFileProgress);
connect(m_parser, &PerfParser::debugInfoDownloadProgress, m_startPage, &StartPage::onDebugInfoDownloadProgress);
connect(this, &MainWindow::openFileError, m_startPage, &StartPage::onOpenFileError);
Expand Down Expand Up @@ -262,6 +268,13 @@ MainWindow::MainWindow(QWidget* parent)

const auto restored = serializer.restoredDockWidgets();
m_resultsPage->initDockWidgets(restored);

connect(m_diffReportDialog, &QDialog::accepted, this, [this] {
m_diffReportDialog->close();
clear();
m_pageStack->setCurrentWidget(m_resultsPageDiff);
m_resultsPageDiff->createDiffReport(m_diffReportDialog->fileA(), m_diffReportDialog->fileB());
});
}

MainWindow::~MainWindow() = default;
Expand Down
4 changes: 4 additions & 0 deletions src/mainwindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@ class KRecentFilesAction;

class StartPage;
class ResultsPage;
class ResultsPageDiff;
class RecordPage;
class SettingsDialog;
class DiffReportDialog;

class MainWindow : public KParts::MainWindow
{
Expand Down Expand Up @@ -77,7 +79,9 @@ public slots:
StartPage* m_startPage;
RecordPage* m_recordPage;
ResultsPage* m_resultsPage;
ResultsPageDiff* m_resultsPageDiff;
SettingsDialog* m_settingsDialog;
DiffReportDialog* m_diffReportDialog;

KRecentFilesAction* m_recentFilesAction = nullptr;
QAction* m_reloadAction = nullptr;
Expand Down
3 changes: 2 additions & 1 deletion src/models/costdelegate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ void CostDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option,
}

const auto totalCost = index.data(m_totalCostRole).toULongLong();
const auto fraction = std::abs(float(cost) / totalCost);
// TODO C++17: std::clamp
const auto fraction = std::max(0.f, std::min(1.f, std::abs(float(cost) / totalCost)));

auto rect = option.rect;
rect.setWidth(rect.width() * fraction);
Expand Down
84 changes: 84 additions & 0 deletions src/models/costproxy.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@

#include <QSortFilterProxyModel>

#include "../util.h"
#include "callercalleeproxy.h"
#include "treemodel.h"

template<typename Model>
class CostProxy : public QSortFilterProxyModel
Expand Down Expand Up @@ -39,3 +41,85 @@ class CostProxy : public QSortFilterProxyModel
return CallerCalleeProxyDetail::match(this, item->symbol);
}
};

namespace CostProxyUtil {
inline int cost(const BottomUpModel* model, int column, int nodeid)
lievenhey marked this conversation as resolved.
Show resolved Hide resolved
{
return model->results().costs.cost(column, nodeid);
}
inline int cost(const TopDownModel* model, int column, int nodeid)
{
const auto inclusiveTypes = model->results().inclusiveCosts.numTypes();
if (column >= inclusiveTypes) {
return model->results().selfCosts.cost(column - inclusiveTypes, nodeid);
}
return model->results().inclusiveCosts.cost(column, nodeid);
}

inline int totalCost(const BottomUpModel* model, int column)
{
return model->results().costs.totalCost(column);
}
inline int totalCost(const TopDownModel* model, int column)
{
const auto inclusiveTypes = model->results().inclusiveCosts.numTypes();
if (column >= inclusiveTypes) {
return model->results().selfCosts.totalCost(column - inclusiveTypes);
}
return model->results().inclusiveCosts.totalCost(column);
}
}

// TODO dedicated cost role
// The DiffCostProxy does all the heavy lifting of diffing
// its gets it data from a Model with baseline cost and the file to diff cost in alternating columns
// this proxy return for every even column the base cost and for every uneven the calculated diff cost
// this simplifies the other models, since we don't need to add this logic there
template<typename Model>
class DiffCostProxy : public CostProxy<Model>
{
public:
explicit DiffCostProxy(QObject* parent = nullptr)
: CostProxy<Model>(parent)
{
}

QVariant data(const QModelIndex& index, int role) const override
{
if (index.column() >= Model::NUM_BASE_COLUMNS) {
const auto model = qobject_cast<Model*>(CostProxy<Model>::sourceModel());
Q_ASSERT(model);

const auto node = model->itemFromIndex(CostProxy<Model>::mapToSource(index));

const auto baseColumn = (index.column() - Model::NUM_BASE_COLUMNS) / 2;
const auto column = baseColumn + (index.column() - Model::NUM_BASE_COLUMNS) % 2;

auto cost = [model, node](int column) { return CostProxyUtil::cost(model, column, node->id); };

auto totalCost = [model](int column) { return CostProxyUtil::totalCost(model, column); };

if (column == baseColumn) {
if (role == Model::TotalCostRole) {
return totalCost(column);
} else if (role == Model::SortRole) {
return cost(column);
} else if (role == Qt::DisplayRole) {
return Util::formatCostRelative(cost(column), totalCost(column), true);
}
} else {
if (role == Model::TotalCostRole) {
return cost(baseColumn);
} else if (role == Model::SortRole) {
if (cost(baseColumn) == 0)
return 0;
return cost(column);
} else if (role == Qt::DisplayRole) {
return Util::formatCostRelative(cost(column), cost(baseColumn), true);
}
}
}

return CostProxy<Model>::data(index, role);
}
};
Loading