Perf: Move config widget setup closer to settingspage

Change-Id: Idda753dc07103dc0f6d0c3ff9759d0ff083ac2d9
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
hjk
2023-07-25 13:55:32 +02:00
parent a478b9682e
commit 86e11befca
7 changed files with 363 additions and 433 deletions

View File

@@ -10,7 +10,6 @@ endif()
set(PERFPROFILER_CPP_SOURCES
perfconfigeventsmodel.cpp perfconfigeventsmodel.h
perfconfigwidget.cpp perfconfigwidget.h
perfdatareader.cpp perfdatareader.h
perfevent.h
perfeventtype.h

View File

@@ -1,369 +0,0 @@
// Copyright (C) 2018 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "perfconfigeventsmodel.h"
#include "perfconfigwidget.h"
#include "perfprofilertr.h"
#include <coreplugin/messagebox.h>
#include <projectexplorer/devicesupport/idevice.h>
#include <projectexplorer/kit.h>
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/target.h>
#include <utils/aspects.h>
#include <utils/layoutbuilder.h>
#include <utils/process.h>
#include <utils/qtcassert.h>
#include <QComboBox>
#include <QHeaderView>
#include <QMessageBox>
#include <QMetaEnum>
#include <QPushButton>
#include <QStyledItemDelegate>
#include <QTableView>
using namespace Utils;
namespace PerfProfiler {
namespace Internal {
class SettingsDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
SettingsDelegate(QObject *parent = nullptr) : QStyledItemDelegate(parent) {}
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
const QModelIndex &index) const override;
void setEditorData(QWidget *editor, const QModelIndex &index) const override;
void setModelData(QWidget *editor, QAbstractItemModel *model,
const QModelIndex &index) const override;
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option,
const QModelIndex &index) const override;
};
PerfConfigWidget::PerfConfigWidget(PerfSettings *settings, QWidget *parent)
: m_settings(settings)
{
setParent(parent);
eventsView = new QTableView(this);
eventsView->setMinimumSize(QSize(0, 300));
eventsView->setEditTriggers(QAbstractItemView::AllEditTriggers);
eventsView->setSelectionMode(QAbstractItemView::SingleSelection);
eventsView->setSelectionBehavior(QAbstractItemView::SelectRows);
eventsView->setModel(new PerfConfigEventsModel(m_settings, this));
eventsView->setItemDelegate(new SettingsDelegate(this));
eventsView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
useTracePointsButton = new QPushButton(this);
useTracePointsButton->setText(Tr::tr("Use Trace Points"));
useTracePointsButton->setVisible(false);
connect(useTracePointsButton, &QPushButton::pressed,
this, &PerfConfigWidget::readTracePoints);
addEventButton = new QPushButton(this);
addEventButton->setText(Tr::tr("Add Event"));
connect(addEventButton, &QPushButton::pressed, this, [this]() {
auto model = eventsView->model();
model->insertRow(model->rowCount());
});
removeEventButton = new QPushButton(this);
removeEventButton->setText(Tr::tr("Remove Event"));
connect(removeEventButton, &QPushButton::pressed, this, [this]() {
QModelIndex index = eventsView->currentIndex();
if (index.isValid())
eventsView->model()->removeRow(index.row());
});
resetButton = new QPushButton(this);
resetButton->setText(Tr::tr("Reset"));
connect(resetButton, &QPushButton::pressed, m_settings, &PerfSettings::resetToDefault);
using namespace Layouting;
Column {
Row { st, useTracePointsButton, addEventButton, removeEventButton, resetButton },
eventsView,
Grid {
m_settings->callgraphMode, m_settings->stackSize, br,
m_settings->sampleMode, m_settings->period, br,
m_settings->extraArguments,
},
st
}.attachTo(this);
}
PerfConfigWidget::~PerfConfigWidget() = default;
void PerfConfigWidget::setTarget(ProjectExplorer::Target *target)
{
ProjectExplorer::IDevice::ConstPtr device;
if (target) {
if (ProjectExplorer::Kit *kit = target->kit())
device = ProjectExplorer::DeviceKitAspect::device(kit);
}
if (device.isNull()) {
useTracePointsButton->setEnabled(false);
return;
}
QTC_ASSERT(device, return);
QTC_CHECK(!m_process || m_process->state() == QProcess::NotRunning);
m_process.reset(new Process);
m_process->setCommand({device->filePath("perf"), {"probe", "-l"}});
connect(m_process.get(), &Process::done,
this, &PerfConfigWidget::handleProcessDone);
useTracePointsButton->setEnabled(true);
}
void PerfConfigWidget::setTracePointsButtonVisible(bool visible)
{
useTracePointsButton->setVisible(visible);
}
void PerfConfigWidget::apply()
{
m_settings->writeGlobalSettings();
}
void PerfConfigWidget::readTracePoints()
{
QMessageBox messageBox;
messageBox.setWindowTitle(Tr::tr("Use Trace Points"));
messageBox.setIcon(QMessageBox::Question);
messageBox.setText(Tr::tr("Replace events with trace points read from the device?"));
messageBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
if (messageBox.exec() == QMessageBox::Yes) {
m_process->start();
useTracePointsButton->setEnabled(false);
}
}
void PerfConfigWidget::handleProcessDone()
{
if (m_process->error() == QProcess::FailedToStart) {
Core::AsynchronousMessageBox::warning(
Tr::tr("Cannot List Trace Points"),
Tr::tr("\"perf probe -l\" failed to start. Is perf installed?"));
useTracePointsButton->setEnabled(true);
return;
}
const QList<QByteArray> lines =
m_process->readAllRawStandardOutput().append(m_process->readAllRawStandardError())
.split('\n');
auto model = eventsView->model();
const int previousRows = model->rowCount();
QHash<QByteArray, QByteArray> tracePoints;
for (const QByteArray &line : lines) {
const QByteArray trimmed = line.trimmed();
const int space = trimmed.indexOf(' ');
if (space < 0)
continue;
// If the whole "on ..." string is the same, the trace points are redundant
tracePoints[trimmed.mid(space + 1)] = trimmed.left(space);
}
if (tracePoints.isEmpty()) {
Core::AsynchronousMessageBox::warning(
Tr::tr("No Trace Points Found"),
Tr::tr("Trace points can be defined with \"perf probe -a\"."));
} else {
for (const QByteArray &event : std::as_const(tracePoints)) {
int row = model->rowCount();
model->insertRow(row);
model->setData(model->index(row, PerfConfigEventsModel::ColumnEventType),
PerfConfigEventsModel::EventTypeCustom);
model->setData(model->index(row, PerfConfigEventsModel::ColumnSubType),
QString::fromUtf8(event));
}
model->removeRows(0, previousRows);
m_settings->sampleMode.setVolatileValue(1);
m_settings->period.setVolatileValue(1);
}
useTracePointsButton->setEnabled(true);
}
QWidget *SettingsDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
Q_UNUSED(option)
const int row = index.row();
const int column = index.column();
const PerfConfigEventsModel *model = qobject_cast<const PerfConfigEventsModel *>(index.model());
auto getRowEventType = [&]() {
return qvariant_cast<PerfConfigEventsModel::EventType>(
model->data(model->index(row, PerfConfigEventsModel::ColumnEventType),
Qt::EditRole));
};
switch (column) {
case PerfConfigEventsModel::ColumnEventType: {
QComboBox *editor = new QComboBox(parent);
QMetaEnum meta = QMetaEnum::fromType<PerfConfigEventsModel::EventType>();
for (int i = 0; i < PerfConfigEventsModel::EventTypeInvalid; ++i) {
editor->addItem(QString::fromLatin1(meta.valueToKey(i)).mid(
static_cast<int>(strlen("EventType"))).toLower(), i);
}
return editor;
}
case PerfConfigEventsModel::ColumnSubType: {
PerfConfigEventsModel::EventType eventType = getRowEventType();
switch (eventType) {
case PerfConfigEventsModel::EventTypeHardware: {
QComboBox *editor = new QComboBox(parent);
for (int i = PerfConfigEventsModel::SubTypeEventTypeHardware;
i < PerfConfigEventsModel::SubTypeEventTypeSoftware; ++i) {
editor->addItem(PerfConfigEventsModel::subTypeString(PerfConfigEventsModel::EventTypeHardware,
PerfConfigEventsModel::SubType(i)), i);
}
return editor;
}
case PerfConfigEventsModel::EventTypeSoftware: {
QComboBox *editor = new QComboBox(parent);
for (int i = PerfConfigEventsModel::SubTypeEventTypeSoftware;
i < PerfConfigEventsModel::SubTypeEventTypeCache; ++i) {
editor->addItem(PerfConfigEventsModel::subTypeString(PerfConfigEventsModel::EventTypeSoftware,
PerfConfigEventsModel::SubType(i)), i);
}
return editor;
}
case PerfConfigEventsModel::EventTypeCache: {
QComboBox *editor = new QComboBox(parent);
for (int i = PerfConfigEventsModel::SubTypeEventTypeCache;
i < PerfConfigEventsModel::SubTypeInvalid; ++i) {
editor->addItem(PerfConfigEventsModel::subTypeString(PerfConfigEventsModel::EventTypeCache,
PerfConfigEventsModel::SubType(i)), i);
}
return editor;
}
case PerfConfigEventsModel::EventTypeBreakpoint: {
QLineEdit *editor = new QLineEdit(parent);
editor->setText("0x0000000000000000");
editor->setValidator(new QRegularExpressionValidator(
QRegularExpression("0x[0-9a-f]{16}"), parent));
return editor;
}
case PerfConfigEventsModel::EventTypeCustom: {
QLineEdit *editor = new QLineEdit(parent);
return editor;
}
case PerfConfigEventsModel::EventTypeRaw: {
QLineEdit *editor = new QLineEdit(parent);
editor->setText("r000");
editor->setValidator(new QRegularExpressionValidator(
QRegularExpression("r[0-9a-f]{3}"), parent));
return editor;
}
case PerfConfigEventsModel::EventTypeInvalid:
return nullptr;
}
return nullptr; // Will never be reached, but GCC cannot figure this out.
}
case PerfConfigEventsModel::ColumnOperation: {
QComboBox *editor = new QComboBox(parent);
PerfConfigEventsModel::EventType eventType = getRowEventType();
if (eventType == PerfConfigEventsModel::EventTypeCache) {
editor->addItem("load", PerfConfigEventsModel::OperationLoad);
editor->addItem("store", PerfConfigEventsModel::OperationStore);
editor->addItem("prefetch", PerfConfigEventsModel::OperationPrefetch);
} else if (eventType == PerfConfigEventsModel::EventTypeBreakpoint) {
editor->addItem("r", PerfConfigEventsModel::OperationLoad);
editor->addItem("rw", PerfConfigEventsModel::OperationLoad
| PerfConfigEventsModel::OperationStore);
editor->addItem("rwx", PerfConfigEventsModel::OperationLoad
| PerfConfigEventsModel::OperationStore
| PerfConfigEventsModel::OperationExecute);
editor->addItem("rx", PerfConfigEventsModel::OperationLoad
| PerfConfigEventsModel::OperationExecute);
editor->addItem("w", PerfConfigEventsModel::OperationStore);
editor->addItem("wx", PerfConfigEventsModel::OperationStore
| PerfConfigEventsModel::OperationExecute);
editor->addItem("x", PerfConfigEventsModel::OperationExecute);
} else {
editor->setEnabled(false);
}
return editor;
}
case PerfConfigEventsModel::ColumnResult: {
QComboBox *editor = new QComboBox(parent);
PerfConfigEventsModel::EventType eventType = getRowEventType();
if (eventType != PerfConfigEventsModel::EventTypeCache) {
editor->setEnabled(false);
} else {
editor->addItem("refs", PerfConfigEventsModel::ResultRefs);
editor->addItem("misses", PerfConfigEventsModel::ResultMisses);
}
return editor;
}
default:
return nullptr;
}
}
void SettingsDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
if (QComboBox *combo = qobject_cast<QComboBox *>(editor)) {
QVariant data = index.model()->data(index, Qt::EditRole);
for (int i = 0, end = combo->count(); i != end; ++i) {
if (combo->itemData(i) == data) {
combo->setCurrentIndex(i);
return;
}
}
} else if (QLineEdit *lineedit = qobject_cast<QLineEdit *>(editor)) {
lineedit->setText(index.model()->data(index, Qt::DisplayRole).toString());
}
}
void SettingsDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
const QModelIndex &index) const
{
if (QComboBox *combo = qobject_cast<QComboBox *>(editor)) {
model->setData(index, combo->currentData());
} else if (QLineEdit *lineedit = qobject_cast<QLineEdit *>(editor)) {
QString text = lineedit->text();
QVariant type = model->data(model->index(index.row(),
PerfConfigEventsModel::ColumnEventType),
Qt::EditRole);
switch (qvariant_cast<PerfConfigEventsModel::EventType>(type)) {
case PerfConfigEventsModel::EventTypeRaw:
model->setData(index, text.mid(static_cast<int>(strlen("r"))).toULongLong(nullptr, 16));
break;
case PerfConfigEventsModel::EventTypeBreakpoint:
model->setData(index,
text.mid(static_cast<int>(strlen("0x"))).toULongLong(nullptr, 16));
break;
case PerfConfigEventsModel::EventTypeCustom:
model->setData(index, text);
break;
default:
break;
}
}
}
void SettingsDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
Q_UNUSED(index)
editor->setGeometry(option.rect);
}
} // namespace Internal
} // namespace PerfProfiler
#include "perfconfigwidget.moc"

View File

@@ -1,50 +0,0 @@
// Copyright (C) 2018 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#pragma once
#include "perfsettings.h"
#include <coreplugin/dialogs/ioptionspage.h>
#include <QProcess>
QT_BEGIN_NAMESPACE
class QPushButton;
class QTableView;
QT_END_NAMESPACE
namespace Utils { class Process; }
namespace PerfProfiler {
namespace Internal {
class PerfConfigWidget : public Core::IOptionsPageWidget
{
Q_OBJECT
public:
explicit PerfConfigWidget(PerfSettings *settings, QWidget *parent = nullptr);
~PerfConfigWidget();
void updateUi();
void setTarget(ProjectExplorer::Target *target);
void setTracePointsButtonVisible(bool visible);
private:
void apply() final;
void readTracePoints();
void handleProcessDone();
PerfSettings *m_settings;
std::unique_ptr<Utils::Process> m_process;
QTableView *eventsView;
QPushButton *useTracePointsButton;
QPushButton *addEventButton;
QPushButton *removeEventButton;
QPushButton *resetButton;
};
} // namespace Internal
} // namespace PerfProfiler

View File

@@ -18,8 +18,6 @@ QtcPlugin {
files: [
"perfconfigeventsmodel.cpp",
"perfconfigeventsmodel.h",
"perfconfigwidget.cpp",
"perfconfigwidget.h",
"perfdatareader.cpp",
"perfdatareader.h",
"perfevent.h",

View File

@@ -3,7 +3,6 @@
#include "perfprofilertool.h"
#include "perfconfigwidget.h"
#include "perfloaddialog.h"
#include "perfprofilerplugin.h"
#include "perfprofilertr.h"
@@ -236,11 +235,8 @@ void PerfProfilerTool::createViews()
settings = runConfig->currentSettings<PerfSettings>(Constants::PerfSettingsId);
}
PerfConfigWidget *widget = new PerfConfigWidget(
settings ? settings : &globalSettings(),
Core::ICore::dialogParent());
widget->setTracePointsButtonVisible(true);
widget->setTarget(target);
QWidget *widget = settings ? settings->createPerfConfigWidget(target)
: globalSettings().createPerfConfigWidget(target);
widget->setWindowFlags(Qt::Dialog);
widget->setAttribute(Qt::WA_DeleteOnClose);
widget->show();

View File

@@ -1,24 +1,375 @@
// Copyright (C) 2018 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#include "perfconfigwidget.h"
#include "perfsettings.h"
#include "perfconfigeventsmodel.h"
#include "perfprofilerconstants.h"
#include "perfprofilertr.h"
#include "perfsettings.h"
#include <coreplugin/dialogs/ioptionspage.h>
#include <coreplugin/icore.h>
#include <coreplugin/messagebox.h>
#include <debugger/analyzer/analyzericons.h>
#include <debugger/debuggertr.h>
#include <projectexplorer/devicesupport/idevice.h>
#include <projectexplorer/kit.h>
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/target.h>
#include <utils/aspects.h>
#include <utils/layoutbuilder.h>
#include <utils/process.h>
#include <utils/qtcassert.h>
#include <QComboBox>
#include <QHeaderView>
#include <QMessageBox>
#include <QMetaEnum>
#include <QPushButton>
#include <QStyledItemDelegate>
#include <QTableView>
using namespace ProjectExplorer;
using namespace Utils;
using namespace PerfProfiler::Internal;
namespace PerfProfiler {
class PerfConfigWidget : public Core::IOptionsPageWidget
{
public:
PerfConfigWidget(PerfSettings *settings, Target *target);
private:
void apply() final;
void readTracePoints();
void handleProcessDone();
PerfSettings *m_settings;
std::unique_ptr<Utils::Process> m_process;
QTableView *eventsView;
QPushButton *useTracePointsButton;
};
class SettingsDelegate : public QStyledItemDelegate
{
public:
SettingsDelegate(QObject *parent = nullptr) : QStyledItemDelegate(parent) {}
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,
const QModelIndex &index) const override;
void setEditorData(QWidget *editor, const QModelIndex &index) const override;
void setModelData(QWidget *editor, QAbstractItemModel *model,
const QModelIndex &index) const override;
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option,
const QModelIndex &) const override
{
editor->setGeometry(option.rect);
}
};
PerfConfigWidget::PerfConfigWidget(PerfSettings *settings, Target *target)
: m_settings(settings)
{
eventsView = new QTableView(this);
eventsView->setMinimumSize(QSize(0, 300));
eventsView->setEditTriggers(QAbstractItemView::AllEditTriggers);
eventsView->setSelectionMode(QAbstractItemView::SingleSelection);
eventsView->setSelectionBehavior(QAbstractItemView::SelectRows);
eventsView->setModel(new PerfConfigEventsModel(m_settings, this));
eventsView->setItemDelegate(new SettingsDelegate(this));
eventsView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
useTracePointsButton = new QPushButton(this);
useTracePointsButton->setText(Tr::tr("Use Trace Points"));
useTracePointsButton->setVisible(target != nullptr);
connect(useTracePointsButton, &QPushButton::pressed,
this, &PerfConfigWidget::readTracePoints);
auto addEventButton = new QPushButton(Tr::tr("Add Event"), this);
connect(addEventButton, &QPushButton::pressed, this, [this]() {
auto model = eventsView->model();
model->insertRow(model->rowCount());
});
auto removeEventButton = new QPushButton(Tr::tr("Remove Event"), this);
connect(removeEventButton, &QPushButton::pressed, this, [this] {
QModelIndex index = eventsView->currentIndex();
if (index.isValid())
eventsView->model()->removeRow(index.row());
});
auto resetButton = new QPushButton(Tr::tr("Reset"), this);
connect(resetButton, &QPushButton::pressed, m_settings, &PerfSettings::resetToDefault);
using namespace Layouting;
Column {
Row { st, useTracePointsButton, addEventButton, removeEventButton, resetButton },
eventsView,
Grid {
m_settings->callgraphMode, m_settings->stackSize, br,
m_settings->sampleMode, m_settings->period, br,
m_settings->extraArguments,
},
st
}.attachTo(this);
IDevice::ConstPtr device;
if (target)
device = DeviceKitAspect::device(target->kit());
if (device.isNull()) {
useTracePointsButton->setEnabled(false);
return;
}
QTC_ASSERT(device, return);
QTC_CHECK(!m_process || m_process->state() == QProcess::NotRunning);
m_process.reset(new Process);
m_process->setCommand({device->filePath("perf"), {"probe", "-l"}});
connect(m_process.get(), &Process::done,
this, &PerfConfigWidget::handleProcessDone);
useTracePointsButton->setEnabled(true);
}
void PerfConfigWidget::apply()
{
m_settings->writeGlobalSettings();
}
void PerfConfigWidget::readTracePoints()
{
QMessageBox messageBox;
messageBox.setWindowTitle(Tr::tr("Use Trace Points"));
messageBox.setIcon(QMessageBox::Question);
messageBox.setText(Tr::tr("Replace events with trace points read from the device?"));
messageBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
if (messageBox.exec() == QMessageBox::Yes) {
m_process->start();
useTracePointsButton->setEnabled(false);
}
}
void PerfConfigWidget::handleProcessDone()
{
if (m_process->error() == QProcess::FailedToStart) {
Core::AsynchronousMessageBox::warning(
Tr::tr("Cannot List Trace Points"),
Tr::tr("\"perf probe -l\" failed to start. Is perf installed?"));
useTracePointsButton->setEnabled(true);
return;
}
const QList<QByteArray> lines =
m_process->readAllRawStandardOutput().append(m_process->readAllRawStandardError())
.split('\n');
auto model = eventsView->model();
const int previousRows = model->rowCount();
QHash<QByteArray, QByteArray> tracePoints;
for (const QByteArray &line : lines) {
const QByteArray trimmed = line.trimmed();
const int space = trimmed.indexOf(' ');
if (space < 0)
continue;
// If the whole "on ..." string is the same, the trace points are redundant
tracePoints[trimmed.mid(space + 1)] = trimmed.left(space);
}
if (tracePoints.isEmpty()) {
Core::AsynchronousMessageBox::warning(
Tr::tr("No Trace Points Found"),
Tr::tr("Trace points can be defined with \"perf probe -a\"."));
} else {
for (const QByteArray &event : std::as_const(tracePoints)) {
int row = model->rowCount();
model->insertRow(row);
model->setData(model->index(row, PerfConfigEventsModel::ColumnEventType),
PerfConfigEventsModel::EventTypeCustom);
model->setData(model->index(row, PerfConfigEventsModel::ColumnSubType),
QString::fromUtf8(event));
}
model->removeRows(0, previousRows);
m_settings->sampleMode.setVolatileValue(1);
m_settings->period.setVolatileValue(1);
}
useTracePointsButton->setEnabled(true);
}
QWidget *SettingsDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
Q_UNUSED(option)
const int row = index.row();
const int column = index.column();
const PerfConfigEventsModel *model = qobject_cast<const PerfConfigEventsModel *>(index.model());
auto getRowEventType = [&]() {
return qvariant_cast<PerfConfigEventsModel::EventType>(
model->data(model->index(row, PerfConfigEventsModel::ColumnEventType),
Qt::EditRole));
};
switch (column) {
case PerfConfigEventsModel::ColumnEventType: {
QComboBox *editor = new QComboBox(parent);
QMetaEnum meta = QMetaEnum::fromType<PerfConfigEventsModel::EventType>();
for (int i = 0; i < PerfConfigEventsModel::EventTypeInvalid; ++i) {
editor->addItem(QString::fromLatin1(meta.valueToKey(i)).mid(
static_cast<int>(strlen("EventType"))).toLower(), i);
}
return editor;
}
case PerfConfigEventsModel::ColumnSubType: {
PerfConfigEventsModel::EventType eventType = getRowEventType();
switch (eventType) {
case PerfConfigEventsModel::EventTypeHardware: {
QComboBox *editor = new QComboBox(parent);
for (int i = PerfConfigEventsModel::SubTypeEventTypeHardware;
i < PerfConfigEventsModel::SubTypeEventTypeSoftware; ++i) {
editor->addItem(PerfConfigEventsModel::subTypeString(PerfConfigEventsModel::EventTypeHardware,
PerfConfigEventsModel::SubType(i)), i);
}
return editor;
}
case PerfConfigEventsModel::EventTypeSoftware: {
QComboBox *editor = new QComboBox(parent);
for (int i = PerfConfigEventsModel::SubTypeEventTypeSoftware;
i < PerfConfigEventsModel::SubTypeEventTypeCache; ++i) {
editor->addItem(PerfConfigEventsModel::subTypeString(PerfConfigEventsModel::EventTypeSoftware,
PerfConfigEventsModel::SubType(i)), i);
}
return editor;
}
case PerfConfigEventsModel::EventTypeCache: {
QComboBox *editor = new QComboBox(parent);
for (int i = PerfConfigEventsModel::SubTypeEventTypeCache;
i < PerfConfigEventsModel::SubTypeInvalid; ++i) {
editor->addItem(PerfConfigEventsModel::subTypeString(PerfConfigEventsModel::EventTypeCache,
PerfConfigEventsModel::SubType(i)), i);
}
return editor;
}
case PerfConfigEventsModel::EventTypeBreakpoint: {
QLineEdit *editor = new QLineEdit(parent);
editor->setText("0x0000000000000000");
editor->setValidator(new QRegularExpressionValidator(
QRegularExpression("0x[0-9a-f]{16}"), parent));
return editor;
}
case PerfConfigEventsModel::EventTypeCustom: {
QLineEdit *editor = new QLineEdit(parent);
return editor;
}
case PerfConfigEventsModel::EventTypeRaw: {
QLineEdit *editor = new QLineEdit(parent);
editor->setText("r000");
editor->setValidator(new QRegularExpressionValidator(
QRegularExpression("r[0-9a-f]{3}"), parent));
return editor;
}
case PerfConfigEventsModel::EventTypeInvalid:
return nullptr;
}
return nullptr; // Will never be reached, but GCC cannot figure this out.
}
case PerfConfigEventsModel::ColumnOperation: {
QComboBox *editor = new QComboBox(parent);
PerfConfigEventsModel::EventType eventType = getRowEventType();
if (eventType == PerfConfigEventsModel::EventTypeCache) {
editor->addItem("load", PerfConfigEventsModel::OperationLoad);
editor->addItem("store", PerfConfigEventsModel::OperationStore);
editor->addItem("prefetch", PerfConfigEventsModel::OperationPrefetch);
} else if (eventType == PerfConfigEventsModel::EventTypeBreakpoint) {
editor->addItem("r", PerfConfigEventsModel::OperationLoad);
editor->addItem("rw", PerfConfigEventsModel::OperationLoad
| PerfConfigEventsModel::OperationStore);
editor->addItem("rwx", PerfConfigEventsModel::OperationLoad
| PerfConfigEventsModel::OperationStore
| PerfConfigEventsModel::OperationExecute);
editor->addItem("rx", PerfConfigEventsModel::OperationLoad
| PerfConfigEventsModel::OperationExecute);
editor->addItem("w", PerfConfigEventsModel::OperationStore);
editor->addItem("wx", PerfConfigEventsModel::OperationStore
| PerfConfigEventsModel::OperationExecute);
editor->addItem("x", PerfConfigEventsModel::OperationExecute);
} else {
editor->setEnabled(false);
}
return editor;
}
case PerfConfigEventsModel::ColumnResult: {
QComboBox *editor = new QComboBox(parent);
PerfConfigEventsModel::EventType eventType = getRowEventType();
if (eventType != PerfConfigEventsModel::EventTypeCache) {
editor->setEnabled(false);
} else {
editor->addItem("refs", PerfConfigEventsModel::ResultRefs);
editor->addItem("misses", PerfConfigEventsModel::ResultMisses);
}
return editor;
}
default:
return nullptr;
}
}
void SettingsDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
if (QComboBox *combo = qobject_cast<QComboBox *>(editor)) {
QVariant data = index.model()->data(index, Qt::EditRole);
for (int i = 0, end = combo->count(); i != end; ++i) {
if (combo->itemData(i) == data) {
combo->setCurrentIndex(i);
return;
}
}
} else if (QLineEdit *lineedit = qobject_cast<QLineEdit *>(editor)) {
lineedit->setText(index.model()->data(index, Qt::DisplayRole).toString());
}
}
void SettingsDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
const QModelIndex &index) const
{
if (QComboBox *combo = qobject_cast<QComboBox *>(editor)) {
model->setData(index, combo->currentData());
} else if (QLineEdit *lineedit = qobject_cast<QLineEdit *>(editor)) {
QString text = lineedit->text();
QVariant type = model->data(model->index(index.row(),
PerfConfigEventsModel::ColumnEventType),
Qt::EditRole);
switch (qvariant_cast<PerfConfigEventsModel::EventType>(type)) {
case PerfConfigEventsModel::EventTypeRaw:
model->setData(index, text.mid(static_cast<int>(strlen("r"))).toULongLong(nullptr, 16));
break;
case PerfConfigEventsModel::EventTypeBreakpoint:
model->setData(index,
text.mid(static_cast<int>(strlen("0x"))).toULongLong(nullptr, 16));
break;
case PerfConfigEventsModel::EventTypeCustom:
model->setData(index, text);
break;
default:
break;
}
}
}
// PerfSettingsPage
PerfSettings &globalSettings()
{
static PerfSettings theSettings(nullptr);
@@ -67,9 +418,7 @@ PerfSettings::PerfSettings(ProjectExplorer::Target *target)
setLayouter([this, target] {
using namespace Layouting;
auto widget = new Internal::PerfConfigWidget(this);
widget->setTracePointsButtonVisible(target != nullptr);
widget->setTarget(target);
auto widget = new PerfConfigWidget(this, target);
return Column { widget };
});
@@ -137,6 +486,11 @@ void PerfSettings::resetToDefault()
fromMap(map);
}
QWidget *PerfSettings::createPerfConfigWidget(Target *target)
{
return new PerfConfigWidget(this, target);
}
// PerfSettingsPage
class PerfSettingsPage final : public Core::IOptionsPage

View File

@@ -24,6 +24,8 @@ public:
void resetToDefault();
QWidget *createPerfConfigWidget(ProjectExplorer::Target *target);
Utils::IntegerAspect period{this};
Utils::IntegerAspect stackSize{this};
Utils::SelectionAspect sampleMode{this};