forked from qt-creator/qt-creator
Valgrind: Create a SuppressionsAspect
This is a fairly complex use case, as the corresponding widget looks the same in global settings and Project settings, but behaves differently (Project only stores a diff, is auto-apply). It also use two(!) settings keys in the project case. So while it works, it takes manual help for the cancel/apply and toMap/fromMap. Looks like there is still some basic infrastructure missing. Change-Id: I25ab7b41616ee09ff9133e93b84f34947fc32988 Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
@@ -128,7 +128,7 @@ public:
|
|||||||
void start() override;
|
void start() override;
|
||||||
void stop() override;
|
void stop() override;
|
||||||
|
|
||||||
QStringList suppressionFiles() const;
|
const QStringList suppressionFiles() const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void internalParserError(const QString &errorString);
|
void internalParserError(const QString &errorString);
|
||||||
@@ -212,7 +212,7 @@ QStringList MemcheckToolRunner::toolArguments() const
|
|||||||
}
|
}
|
||||||
arguments << "--leak-check=" + leakCheckValue;
|
arguments << "--leak-check=" + leakCheckValue;
|
||||||
|
|
||||||
foreach (const QString &file, m_settings.suppressionFiles())
|
for (const QString &file : m_settings.suppressions.value())
|
||||||
arguments << QString("--suppressions=%1").arg(file);
|
arguments << QString("--suppressions=%1").arg(file);
|
||||||
|
|
||||||
arguments << QString("--num-callers=%1").arg(m_settings.numCallers.value());
|
arguments << QString("--num-callers=%1").arg(m_settings.numCallers.value());
|
||||||
@@ -225,9 +225,9 @@ QStringList MemcheckToolRunner::toolArguments() const
|
|||||||
return arguments;
|
return arguments;
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList MemcheckToolRunner::suppressionFiles() const
|
const QStringList MemcheckToolRunner::suppressionFiles() const
|
||||||
{
|
{
|
||||||
return m_settings.suppressionFiles();
|
return m_settings.suppressions.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemcheckToolRunner::startDebugger(qint64 valgrindPid)
|
void MemcheckToolRunner::startDebugger(qint64 valgrindPid)
|
||||||
|
@@ -44,13 +44,12 @@
|
|||||||
#include <utils/fileutils.h>
|
#include <utils/fileutils.h>
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
#include <QFile>
|
|
||||||
|
|
||||||
#include <QDialogButtonBox>
|
#include <QDialogButtonBox>
|
||||||
|
#include <QFile>
|
||||||
#include <QFormLayout>
|
#include <QFormLayout>
|
||||||
#include <QPushButton>
|
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QPlainTextEdit>
|
#include <QPlainTextEdit>
|
||||||
|
#include <QPushButton>
|
||||||
|
|
||||||
using namespace Valgrind::XmlProtocol;
|
using namespace Valgrind::XmlProtocol;
|
||||||
|
|
||||||
@@ -217,7 +216,7 @@ void SuppressionDialog::accept()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_settings->addSuppressionFiles(QStringList(path));
|
m_settings->suppressions.addSuppressionFile(path);
|
||||||
|
|
||||||
QModelIndexList indices = m_view->selectionModel()->selectedRows();
|
QModelIndexList indices = m_view->selectionModel()->selectedRows();
|
||||||
Utils::sort(indices, [](const QModelIndex &l, const QModelIndex &r) {
|
Utils::sort(indices, [](const QModelIndex &l, const QModelIndex &r) {
|
||||||
|
@@ -30,26 +30,17 @@
|
|||||||
|
|
||||||
#include <debugger/analyzer/analyzericons.h>
|
#include <debugger/analyzer/analyzericons.h>
|
||||||
|
|
||||||
|
#include <coreplugin/icore.h>
|
||||||
|
|
||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
#include <utils/hostosinfo.h>
|
|
||||||
#include <utils/layoutbuilder.h>
|
#include <utils/layoutbuilder.h>
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
#include <QDebug>
|
|
||||||
#include <QFileDialog>
|
|
||||||
#include <QListView>
|
|
||||||
#include <QPushButton>
|
|
||||||
#include <QStandardItemModel>
|
|
||||||
|
|
||||||
#include <functional>
|
|
||||||
|
|
||||||
using namespace Utils;
|
using namespace Utils;
|
||||||
|
|
||||||
namespace Valgrind {
|
namespace Valgrind {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
class ValgrindBaseSettings;
|
|
||||||
|
|
||||||
class ValgrindConfigWidget : public Core::IOptionsPageWidget
|
class ValgrindConfigWidget : public Core::IOptionsPageWidget
|
||||||
{
|
{
|
||||||
Q_DECLARE_TR_FUNCTIONS(Valgrind::Internal::ValgrindConfigWidget)
|
Q_DECLARE_TR_FUNCTIONS(Valgrind::Internal::ValgrindConfigWidget)
|
||||||
@@ -63,37 +54,14 @@ public:
|
|||||||
ValgrindGlobalSettings::instance()->writeSettings();
|
ValgrindGlobalSettings::instance()->writeSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setSuppressions(const QStringList &files);
|
void finish() final
|
||||||
QStringList suppressions() const;
|
{
|
||||||
|
ValgrindGlobalSettings::instance()->group.finish();
|
||||||
void slotAddSuppression();
|
}
|
||||||
void slotRemoveSuppression();
|
|
||||||
void slotSuppressionsRemoved(const QStringList &files);
|
|
||||||
void slotSuppressionsAdded(const QStringList &files);
|
|
||||||
void slotSuppressionSelectionChanged();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void updateUi();
|
|
||||||
|
|
||||||
ValgrindBaseSettings *m_settings;
|
|
||||||
|
|
||||||
QPushButton *addSuppression;
|
|
||||||
QPushButton *removeSuppression;
|
|
||||||
QListView *suppressionList;
|
|
||||||
|
|
||||||
QStandardItemModel m_model;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
ValgrindConfigWidget::ValgrindConfigWidget(ValgrindBaseSettings *settings)
|
ValgrindConfigWidget::ValgrindConfigWidget(ValgrindBaseSettings *settings)
|
||||||
: m_settings(settings)
|
|
||||||
{
|
{
|
||||||
addSuppression = new QPushButton(tr("Add..."));
|
|
||||||
removeSuppression = new QPushButton(tr("Remove"));
|
|
||||||
|
|
||||||
suppressionList = new QListView;
|
|
||||||
suppressionList->setModel(&m_model);
|
|
||||||
suppressionList->setSelectionMode(QAbstractItemView::MultiSelection);
|
|
||||||
|
|
||||||
using namespace Layouting;
|
using namespace Layouting;
|
||||||
const Break nl;
|
const Break nl;
|
||||||
ValgrindBaseSettings &s = *settings;
|
ValgrindBaseSettings &s = *settings;
|
||||||
@@ -111,16 +79,7 @@ ValgrindConfigWidget::ValgrindConfigWidget(ValgrindBaseSettings *settings)
|
|||||||
s.leakCheckOnFinish, nl,
|
s.leakCheckOnFinish, nl,
|
||||||
s.numCallers, nl,
|
s.numCallers, nl,
|
||||||
s.filterExternalIssues, nl,
|
s.filterExternalIssues, nl,
|
||||||
Item {
|
s.suppressions
|
||||||
Group {
|
|
||||||
Title(tr("Suppression files:")),
|
|
||||||
Row {
|
|
||||||
suppressionList,
|
|
||||||
Column { addSuppression, removeSuppression, Stretch() }
|
|
||||||
}
|
|
||||||
},
|
|
||||||
2 // Span.
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Grid callgrind {
|
Grid callgrind {
|
||||||
@@ -146,111 +105,6 @@ ValgrindConfigWidget::ValgrindConfigWidget(ValgrindBaseSettings *settings)
|
|||||||
Group { Title(tr("CallGrind Profiling Options")), callgrind },
|
Group { Title(tr("CallGrind Profiling Options")), callgrind },
|
||||||
Stretch(),
|
Stretch(),
|
||||||
}.attachTo(this);
|
}.attachTo(this);
|
||||||
|
|
||||||
|
|
||||||
updateUi();
|
|
||||||
connect(m_settings, &ValgrindBaseSettings::changed, this, &ValgrindConfigWidget::updateUi);
|
|
||||||
|
|
||||||
connect(addSuppression, &QPushButton::clicked,
|
|
||||||
this, &ValgrindConfigWidget::slotAddSuppression);
|
|
||||||
connect(removeSuppression, &QPushButton::clicked,
|
|
||||||
this, &ValgrindConfigWidget::slotRemoveSuppression);
|
|
||||||
|
|
||||||
connect(&s, &ValgrindBaseSettings::suppressionFilesRemoved,
|
|
||||||
this, &ValgrindConfigWidget::slotSuppressionsRemoved);
|
|
||||||
connect(&s, &ValgrindBaseSettings::suppressionFilesAdded,
|
|
||||||
this, &ValgrindConfigWidget::slotSuppressionsAdded);
|
|
||||||
|
|
||||||
connect(suppressionList->selectionModel(), &QItemSelectionModel::selectionChanged,
|
|
||||||
this, &ValgrindConfigWidget::slotSuppressionSelectionChanged);
|
|
||||||
|
|
||||||
slotSuppressionSelectionChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ValgrindConfigWidget::updateUi()
|
|
||||||
{
|
|
||||||
m_model.clear();
|
|
||||||
foreach (const QString &file, m_settings->suppressionFiles())
|
|
||||||
m_model.appendRow(new QStandardItem(file));
|
|
||||||
}
|
|
||||||
|
|
||||||
void ValgrindConfigWidget::slotAddSuppression()
|
|
||||||
{
|
|
||||||
ValgrindGlobalSettings *conf = ValgrindGlobalSettings::instance();
|
|
||||||
QTC_ASSERT(conf, return);
|
|
||||||
QStringList files = QFileDialog::getOpenFileNames(this,
|
|
||||||
tr("Valgrind Suppression Files"),
|
|
||||||
conf->lastSuppressionDirectory.value(),
|
|
||||||
tr("Valgrind Suppression File (*.supp);;All Files (*)"));
|
|
||||||
//dialog.setHistory(conf->lastSuppressionDialogHistory());
|
|
||||||
if (!files.isEmpty()) {
|
|
||||||
foreach (const QString &file, files)
|
|
||||||
m_model.appendRow(new QStandardItem(file));
|
|
||||||
m_settings->addSuppressionFiles(files);
|
|
||||||
conf->lastSuppressionDirectory.setValue(QFileInfo(files.at(0)).absolutePath());
|
|
||||||
//conf->setLastSuppressionDialogHistory(dialog.history());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ValgrindConfigWidget::slotSuppressionsAdded(const QStringList &files)
|
|
||||||
{
|
|
||||||
QStringList filesToAdd = files;
|
|
||||||
for (int i = 0, c = m_model.rowCount(); i < c; ++i)
|
|
||||||
filesToAdd.removeAll(m_model.item(i)->text());
|
|
||||||
|
|
||||||
foreach (const QString &file, filesToAdd)
|
|
||||||
m_model.appendRow(new QStandardItem(file));
|
|
||||||
}
|
|
||||||
|
|
||||||
void ValgrindConfigWidget::slotRemoveSuppression()
|
|
||||||
{
|
|
||||||
// remove from end so no rows get invalidated
|
|
||||||
QList<int> rows;
|
|
||||||
|
|
||||||
QStringList removed;
|
|
||||||
foreach (const QModelIndex &index, suppressionList->selectionModel()->selectedIndexes()) {
|
|
||||||
rows << index.row();
|
|
||||||
removed << index.data().toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
Utils::sort(rows, std::greater<int>());
|
|
||||||
|
|
||||||
foreach (int row, rows)
|
|
||||||
m_model.removeRow(row);
|
|
||||||
|
|
||||||
m_settings->removeSuppressionFiles(removed);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ValgrindConfigWidget::slotSuppressionsRemoved(const QStringList &files)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < m_model.rowCount(); ++i) {
|
|
||||||
if (files.contains(m_model.item(i)->text())) {
|
|
||||||
m_model.removeRow(i);
|
|
||||||
--i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ValgrindConfigWidget::setSuppressions(const QStringList &files)
|
|
||||||
{
|
|
||||||
m_model.clear();
|
|
||||||
foreach (const QString &file, files)
|
|
||||||
m_model.appendRow(new QStandardItem(file));
|
|
||||||
}
|
|
||||||
|
|
||||||
QStringList ValgrindConfigWidget::suppressions() const
|
|
||||||
{
|
|
||||||
QStringList ret;
|
|
||||||
|
|
||||||
for (int i = 0; i < m_model.rowCount(); ++i)
|
|
||||||
ret << m_model.item(i)->text();
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ValgrindConfigWidget::slotSuppressionSelectionChanged()
|
|
||||||
{
|
|
||||||
removeSuppression->setEnabled(suppressionList->selectionModel()->hasSelection());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ValgrindOptionsPage
|
// ValgrindOptionsPage
|
||||||
|
@@ -30,32 +30,277 @@
|
|||||||
|
|
||||||
#include <coreplugin/icore.h>
|
#include <coreplugin/icore.h>
|
||||||
|
|
||||||
|
#include <utils/layoutbuilder.h>
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
#include <utils/treemodel.h>
|
||||||
#include <utils/utilsicons.h>
|
#include <utils/utilsicons.h>
|
||||||
|
|
||||||
#include <valgrind/xmlprotocol/error.h>
|
#include <valgrind/xmlprotocol/error.h>
|
||||||
|
|
||||||
#include <QSettings>
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#include <QFileDialog>
|
||||||
|
#include <QListView>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QSettings>
|
||||||
|
#include <QStandardItemModel>
|
||||||
|
|
||||||
using namespace Utils;
|
using namespace Utils;
|
||||||
|
|
||||||
namespace Valgrind {
|
namespace Valgrind {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
|
//
|
||||||
|
// SuppressionAspect
|
||||||
|
//
|
||||||
|
|
||||||
|
// This is somewhat unusual, as it looks the same in Global Settings and Project
|
||||||
|
// settings, but behaves differently (Project only stores a diff) depending on
|
||||||
|
// context.
|
||||||
|
|
||||||
|
const char globalSuppressionKey[] = "Analyzer.Valgrind.SupressionFiles";
|
||||||
|
const char removedProjectSuppressionKey[] = "Analyzer.Valgrind.RemovedSuppressionFiles";
|
||||||
|
const char addedProjectSuppressionKey[] = "Analyzer.Valgrind.AddedSuppressionFiles";
|
||||||
|
|
||||||
|
class SuppressionAspectPrivate : public QObject
|
||||||
|
{
|
||||||
|
Q_DECLARE_TR_FUNCTIONS(Valgrind::Internal::ValgrindConfigWidget)
|
||||||
|
|
||||||
|
public:
|
||||||
|
SuppressionAspectPrivate(SuppressionAspect *q, bool global) : q(q), isGlobal(global) {}
|
||||||
|
|
||||||
|
void slotAddSuppression();
|
||||||
|
void slotRemoveSuppression();
|
||||||
|
void slotSuppressionSelectionChanged();
|
||||||
|
|
||||||
|
SuppressionAspect *q;
|
||||||
|
const bool isGlobal;
|
||||||
|
|
||||||
|
QPointer<QPushButton> addEntry;
|
||||||
|
QPointer<QPushButton> removeEntry;
|
||||||
|
QPointer<QListView> entryList;
|
||||||
|
|
||||||
|
QStandardItemModel m_model; // The volatile value of this aspect.
|
||||||
|
|
||||||
|
QStringList globalSuppressionFiles; // Real value, only used for global settings
|
||||||
|
|
||||||
|
QStringList removedProjectSuppressionFiles; // Part of real value for project settings
|
||||||
|
QStringList addedProjectSuppressionFiles; // Part of real value for project settings
|
||||||
|
};
|
||||||
|
|
||||||
|
void SuppressionAspect::addSuppressionFile(const QString &suppression)
|
||||||
|
{
|
||||||
|
if (d->isGlobal) {
|
||||||
|
d->globalSuppressionFiles.append(suppression);
|
||||||
|
} else {
|
||||||
|
const QStringList globalSuppressions = ValgrindGlobalSettings::instance()->suppressions.value();
|
||||||
|
if (!d->addedProjectSuppressionFiles.contains(suppression))
|
||||||
|
d->addedProjectSuppressionFiles.append(suppression);
|
||||||
|
d->removedProjectSuppressionFiles.removeAll(suppression);
|
||||||
|
}
|
||||||
|
setVolatileValue(value());
|
||||||
|
}
|
||||||
|
|
||||||
|
void SuppressionAspectPrivate::slotAddSuppression()
|
||||||
|
{
|
||||||
|
ValgrindGlobalSettings *conf = ValgrindGlobalSettings::instance();
|
||||||
|
QTC_ASSERT(conf, return);
|
||||||
|
const QStringList files =
|
||||||
|
QFileDialog::getOpenFileNames(Core::ICore::dialogParent(),
|
||||||
|
tr("Valgrind Suppression Files"),
|
||||||
|
conf->lastSuppressionDirectory.value(),
|
||||||
|
tr("Valgrind Suppression File (*.supp);;All Files (*)"));
|
||||||
|
//dialog.setHistory(conf->lastSuppressionDialogHistory());
|
||||||
|
if (!files.isEmpty()) {
|
||||||
|
for (const QString &file : files)
|
||||||
|
m_model.appendRow(new QStandardItem(file));
|
||||||
|
conf->lastSuppressionDirectory.setValue(QFileInfo(files.at(0)).absolutePath());
|
||||||
|
//conf->setLastSuppressionDialogHistory(dialog.history());
|
||||||
|
if (!isGlobal)
|
||||||
|
q->apply();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SuppressionAspectPrivate::slotRemoveSuppression()
|
||||||
|
{
|
||||||
|
// remove from end so no rows get invalidated
|
||||||
|
QList<int> rows;
|
||||||
|
|
||||||
|
QStringList removed;
|
||||||
|
const QModelIndexList selected = entryList->selectionModel()->selectedIndexes();
|
||||||
|
for (const QModelIndex &index : selected) {
|
||||||
|
rows << index.row();
|
||||||
|
removed << index.data().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
Utils::sort(rows, std::greater<int>());
|
||||||
|
|
||||||
|
for (int row : qAsConst(rows))
|
||||||
|
m_model.removeRow(row);
|
||||||
|
|
||||||
|
if (!isGlobal)
|
||||||
|
q->apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SuppressionAspectPrivate::slotSuppressionSelectionChanged()
|
||||||
|
{
|
||||||
|
removeEntry->setEnabled(entryList->selectionModel()->hasSelection());
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// SuppressionAspect
|
||||||
|
//
|
||||||
|
|
||||||
|
SuppressionAspect::SuppressionAspect(bool global)
|
||||||
|
{
|
||||||
|
d = new SuppressionAspectPrivate(this, global);
|
||||||
|
}
|
||||||
|
|
||||||
|
SuppressionAspect::~SuppressionAspect()
|
||||||
|
{
|
||||||
|
delete d;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList SuppressionAspect::value() const
|
||||||
|
{
|
||||||
|
// Note: BaseAspect::d->value is /not/ used.
|
||||||
|
if (d->isGlobal)
|
||||||
|
return d->globalSuppressionFiles;
|
||||||
|
|
||||||
|
QStringList ret = ValgrindGlobalSettings::instance()->suppressions.value();
|
||||||
|
for (const QString &s : d->removedProjectSuppressionFiles)
|
||||||
|
ret.removeAll(s);
|
||||||
|
ret.append(d->addedProjectSuppressionFiles);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SuppressionAspect::setValue(const QStringList &val)
|
||||||
|
{
|
||||||
|
if (d->isGlobal) {
|
||||||
|
d->globalSuppressionFiles = val;
|
||||||
|
} else {
|
||||||
|
const QStringList globals = ValgrindGlobalSettings::instance()->suppressions.value();
|
||||||
|
d->addedProjectSuppressionFiles.clear();
|
||||||
|
for (const QString &s : val) {
|
||||||
|
if (!globals.contains(s))
|
||||||
|
d->addedProjectSuppressionFiles.append(s);
|
||||||
|
}
|
||||||
|
d->removedProjectSuppressionFiles.clear();
|
||||||
|
for (const QString &s : globals) {
|
||||||
|
if (!val.contains(s))
|
||||||
|
d->removedProjectSuppressionFiles.append(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SuppressionAspect::addToLayout(LayoutBuilder &builder)
|
||||||
|
{
|
||||||
|
QTC_CHECK(!d->addEntry);
|
||||||
|
QTC_CHECK(!d->removeEntry);
|
||||||
|
QTC_CHECK(!d->entryList);
|
||||||
|
|
||||||
|
using namespace Layouting;
|
||||||
|
|
||||||
|
d->addEntry = new QPushButton(tr("Add..."));
|
||||||
|
d->removeEntry = new QPushButton(tr("Remove"));
|
||||||
|
|
||||||
|
d->entryList = new QListView;
|
||||||
|
d->entryList->setModel(&d->m_model);
|
||||||
|
d->entryList->setSelectionMode(QAbstractItemView::MultiSelection);
|
||||||
|
|
||||||
|
connect(d->addEntry, &QPushButton::clicked,
|
||||||
|
d, &SuppressionAspectPrivate::slotAddSuppression);
|
||||||
|
connect(d->removeEntry, &QPushButton::clicked,
|
||||||
|
d, &SuppressionAspectPrivate::slotRemoveSuppression);
|
||||||
|
connect(d->entryList->selectionModel(), &QItemSelectionModel::selectionChanged,
|
||||||
|
d, &SuppressionAspectPrivate::slotSuppressionSelectionChanged);
|
||||||
|
|
||||||
|
Group group {
|
||||||
|
Title(tr("Suppression files:")),
|
||||||
|
Row {
|
||||||
|
d->entryList.data(),
|
||||||
|
Column { d->addEntry.data(), d->removeEntry.data(), Stretch() }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
builder.addItem(Item { group, 2 });
|
||||||
|
}
|
||||||
|
|
||||||
|
void SuppressionAspect::fromMap(const QVariantMap &map)
|
||||||
|
{
|
||||||
|
if (d->isGlobal) {
|
||||||
|
d->globalSuppressionFiles = map.value(globalSuppressionKey).toStringList();
|
||||||
|
} else {
|
||||||
|
d->addedProjectSuppressionFiles = map.value(addedProjectSuppressionKey).toStringList();
|
||||||
|
d->removedProjectSuppressionFiles = map.value(removedProjectSuppressionKey).toStringList();
|
||||||
|
}
|
||||||
|
setVolatileValue(value());
|
||||||
|
}
|
||||||
|
|
||||||
|
void SuppressionAspect::toMap(QVariantMap &map) const
|
||||||
|
{
|
||||||
|
auto save = [&map](const QStringList &data, const QString &key) {
|
||||||
|
if (data.isEmpty())
|
||||||
|
map.remove(key);
|
||||||
|
else
|
||||||
|
map.insert(key, data);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (d->isGlobal) {
|
||||||
|
save(d->globalSuppressionFiles, globalSuppressionKey);
|
||||||
|
} else {
|
||||||
|
save(d->addedProjectSuppressionFiles, addedProjectSuppressionKey);
|
||||||
|
save(d->removedProjectSuppressionFiles, removedProjectSuppressionKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant SuppressionAspect::volatileValue() const
|
||||||
|
{
|
||||||
|
QStringList ret;
|
||||||
|
|
||||||
|
for (int i = 0; i < d->m_model.rowCount(); ++i)
|
||||||
|
ret << d->m_model.item(i)->text();
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SuppressionAspect::setVolatileValue(const QVariant &val)
|
||||||
|
{
|
||||||
|
const QStringList files = val.toStringList();
|
||||||
|
d->m_model.clear();
|
||||||
|
for (const QString &file : files)
|
||||||
|
d->m_model.appendRow(new QStandardItem(file));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SuppressionAspect::cancel()
|
||||||
|
{
|
||||||
|
setVolatileValue(value());
|
||||||
|
}
|
||||||
|
|
||||||
|
void SuppressionAspect::apply()
|
||||||
|
{
|
||||||
|
setValue(volatileValue().toStringList());
|
||||||
|
}
|
||||||
|
|
||||||
|
void SuppressionAspect::finish()
|
||||||
|
{
|
||||||
|
setVolatileValue(value()); // Clean up m_model content
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// ValgrindBaseSettings
|
// ValgrindBaseSettings
|
||||||
//
|
//
|
||||||
//////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
ValgrindBaseSettings::ValgrindBaseSettings()
|
ValgrindBaseSettings::ValgrindBaseSettings(bool global)
|
||||||
|
: suppressions(global)
|
||||||
{
|
{
|
||||||
// Note that this is used twice, once for project settings in the .user files
|
// Note that this is used twice, once for project settings in the .user files
|
||||||
// and once for global settings in QtCreator.ini. This uses intentionally
|
// and once for global settings in QtCreator.ini. This uses intentionally
|
||||||
// the same key to facilitate copying using fromMap/toMap.
|
// the same key to facilitate copying using fromMap/toMap.
|
||||||
QString base = "Analyzer.Valgrind.";
|
QString base = "Analyzer.Valgrind.";
|
||||||
|
|
||||||
|
group.registerAspect(&suppressions);
|
||||||
|
|
||||||
group.registerAspect(&valgrindExecutable);
|
group.registerAspect(&valgrindExecutable);
|
||||||
valgrindExecutable.setSettingsKey(base + "ValgrindExecutable");
|
valgrindExecutable.setSettingsKey(base + "ValgrindExecutable");
|
||||||
valgrindExecutable.setDefaultValue("valgrind");
|
valgrindExecutable.setDefaultValue("valgrind");
|
||||||
@@ -236,14 +481,12 @@ void ValgrindBaseSettings::toMap(QVariantMap &map) const
|
|||||||
static ValgrindGlobalSettings *theGlobalSettings = nullptr;
|
static ValgrindGlobalSettings *theGlobalSettings = nullptr;
|
||||||
|
|
||||||
ValgrindGlobalSettings::ValgrindGlobalSettings()
|
ValgrindGlobalSettings::ValgrindGlobalSettings()
|
||||||
|
: ValgrindBaseSettings(true)
|
||||||
{
|
{
|
||||||
theGlobalSettings = this;
|
theGlobalSettings = this;
|
||||||
|
|
||||||
const QString base = "Analyzer.Valgrind";
|
const QString base = "Analyzer.Valgrind";
|
||||||
|
|
||||||
group.registerAspect(&suppressionFiles_);
|
|
||||||
suppressionFiles_.setSettingsKey(base + "SupressionFiles");
|
|
||||||
|
|
||||||
group.registerAspect(&lastSuppressionDirectory);
|
group.registerAspect(&lastSuppressionDirectory);
|
||||||
lastSuppressionDirectory.setSettingsKey(base + "LastSuppressionDirectory");
|
lastSuppressionDirectory.setSettingsKey(base + "LastSuppressionDirectory");
|
||||||
|
|
||||||
@@ -282,20 +525,6 @@ ValgrindGlobalSettings *ValgrindGlobalSettings::instance()
|
|||||||
//
|
//
|
||||||
// Memcheck
|
// Memcheck
|
||||||
//
|
//
|
||||||
QStringList ValgrindGlobalSettings::suppressionFiles() const
|
|
||||||
{
|
|
||||||
return suppressionFiles_.value();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ValgrindGlobalSettings::addSuppressionFiles(const QStringList &suppressions)
|
|
||||||
{
|
|
||||||
suppressionFiles_.appendValues(suppressions);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ValgrindGlobalSettings::removeSuppressionFiles(const QStringList &suppressions)
|
|
||||||
{
|
|
||||||
suppressionFiles_.removeValues(suppressions);
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariantMap ValgrindBaseSettings::defaultSettings() const
|
QVariantMap ValgrindBaseSettings::defaultSettings() const
|
||||||
{
|
{
|
||||||
@@ -310,14 +539,13 @@ static const char groupC[] = "Analyzer";
|
|||||||
|
|
||||||
void ValgrindGlobalSettings::readSettings()
|
void ValgrindGlobalSettings::readSettings()
|
||||||
{
|
{
|
||||||
QVariantMap defaults = defaultSettings();
|
|
||||||
|
|
||||||
// Read stored values
|
// Read stored values
|
||||||
QSettings *settings = Core::ICore::settings();
|
QSettings *settings = Core::ICore::settings();
|
||||||
settings->beginGroup(groupC);
|
settings->beginGroup(groupC);
|
||||||
QVariantMap map = defaults;
|
QVariantMap map;
|
||||||
for (QVariantMap::ConstIterator it = defaults.constBegin(); it != defaults.constEnd(); ++it)
|
const QStringList childKey = settings->childKeys();
|
||||||
map.insert(it.key(), settings->value(it.key(), it.value()));
|
for (const QString &key : childKey)
|
||||||
|
map.insert(key, settings->value(key));
|
||||||
settings->endGroup();
|
settings->endGroup();
|
||||||
|
|
||||||
fromMap(map);
|
fromMap(map);
|
||||||
@@ -343,49 +571,9 @@ void ValgrindGlobalSettings::writeSettings() const
|
|||||||
//////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
ValgrindProjectSettings::ValgrindProjectSettings()
|
ValgrindProjectSettings::ValgrindProjectSettings()
|
||||||
|
: ValgrindBaseSettings(false)
|
||||||
{
|
{
|
||||||
setConfigWidgetCreator([this] { return ValgrindOptionsPage::createSettingsWidget(this); });
|
setConfigWidgetCreator([this] { return ValgrindOptionsPage::createSettingsWidget(this); });
|
||||||
|
|
||||||
group.registerAspect(&disabledGlobalSuppressionFiles);
|
|
||||||
disabledGlobalSuppressionFiles.setSettingsKey("Analyzer.Valgrind.RemovedSuppressionFiles");
|
|
||||||
|
|
||||||
group.registerAspect(&addedSuppressionFiles);
|
|
||||||
addedSuppressionFiles.setSettingsKey("Analyzer.Valgrind.AddedSuppressionFiles");
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// Memcheck
|
|
||||||
//
|
|
||||||
|
|
||||||
void ValgrindProjectSettings::addSuppressionFiles(const QStringList &suppressions)
|
|
||||||
{
|
|
||||||
const QStringList globalSuppressions = ValgrindGlobalSettings::instance()->suppressionFiles();
|
|
||||||
for (const QString &s : suppressions) {
|
|
||||||
if (addedSuppressionFiles.value().contains(s))
|
|
||||||
continue;
|
|
||||||
disabledGlobalSuppressionFiles.removeValue(s);
|
|
||||||
if (!globalSuppressions.contains(s))
|
|
||||||
addedSuppressionFiles.appendValue(s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ValgrindProjectSettings::removeSuppressionFiles(const QStringList &suppressions)
|
|
||||||
{
|
|
||||||
const QStringList globalSuppressions = ValgrindGlobalSettings::instance()->suppressionFiles();
|
|
||||||
for (const QString &s : suppressions) {
|
|
||||||
addedSuppressionFiles.removeValue(s);
|
|
||||||
if (globalSuppressions.contains(s))
|
|
||||||
disabledGlobalSuppressionFiles.appendValue(s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QStringList ValgrindProjectSettings::suppressionFiles() const
|
|
||||||
{
|
|
||||||
QStringList ret = ValgrindGlobalSettings::instance()->suppressionFiles();
|
|
||||||
for (const QString &s : disabledGlobalSuppressionFiles.value())
|
|
||||||
ret.removeAll(s);
|
|
||||||
ret.append(addedSuppressionFiles.value());
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
@@ -36,6 +36,36 @@ namespace Internal {
|
|||||||
|
|
||||||
const char ANALYZER_VALGRIND_SETTINGS[] = "Analyzer.Valgrind.Settings";
|
const char ANALYZER_VALGRIND_SETTINGS[] = "Analyzer.Valgrind.Settings";
|
||||||
|
|
||||||
|
class SuppressionAspectPrivate;
|
||||||
|
|
||||||
|
class SuppressionAspect final : public Utils::BaseAspect
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit SuppressionAspect(bool global);
|
||||||
|
~SuppressionAspect() final;
|
||||||
|
|
||||||
|
QStringList value() const;
|
||||||
|
void setValue(const QStringList &val);
|
||||||
|
|
||||||
|
void addToLayout(Utils::LayoutBuilder &builder) final;
|
||||||
|
|
||||||
|
void fromMap(const QVariantMap &map) final;
|
||||||
|
void toMap(QVariantMap &map) const final;
|
||||||
|
|
||||||
|
QVariant volatileValue() const final;
|
||||||
|
void setVolatileValue(const QVariant &val) final;
|
||||||
|
|
||||||
|
void cancel() final;
|
||||||
|
void apply() final;
|
||||||
|
void finish() final;
|
||||||
|
|
||||||
|
void addSuppressionFile(const QString &suppressionFile);
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend class ValgrindBaseSettings;
|
||||||
|
SuppressionAspectPrivate *d = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Valgrind settings shared for global and per-project.
|
* Valgrind settings shared for global and per-project.
|
||||||
*/
|
*/
|
||||||
@@ -44,7 +74,7 @@ class ValgrindBaseSettings : public ProjectExplorer::ISettingsAspect
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ValgrindBaseSettings();
|
explicit ValgrindBaseSettings(bool global);
|
||||||
|
|
||||||
enum SelfModifyingCodeDetection {
|
enum SelfModifyingCodeDetection {
|
||||||
DetectSmcNo,
|
DetectSmcNo,
|
||||||
@@ -73,6 +103,8 @@ public:
|
|||||||
Utils::StringAspect valgrindArguments;
|
Utils::StringAspect valgrindArguments;
|
||||||
Utils::SelectionAspect selfModifyingCodeDetection;
|
Utils::SelectionAspect selfModifyingCodeDetection;
|
||||||
|
|
||||||
|
SuppressionAspect suppressions;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base memcheck settings
|
* Base memcheck settings
|
||||||
*/
|
*/
|
||||||
@@ -85,16 +117,8 @@ public:
|
|||||||
Utils::BoolAspect filterExternalIssues;
|
Utils::BoolAspect filterExternalIssues;
|
||||||
Utils::IntegersAspect visibleErrorKinds;
|
Utils::IntegersAspect visibleErrorKinds;
|
||||||
|
|
||||||
virtual QStringList suppressionFiles() const = 0;
|
|
||||||
virtual void addSuppressionFiles(const QStringList &) = 0;
|
|
||||||
virtual void removeSuppressionFiles(const QStringList &) = 0;
|
|
||||||
|
|
||||||
void setVisibleErrorKinds(const QList<int> &);
|
void setVisibleErrorKinds(const QList<int> &);
|
||||||
|
|
||||||
signals:
|
|
||||||
void suppressionFilesRemoved(const QStringList &);
|
|
||||||
void suppressionFilesAdded(const QStringList &);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base callgrind settings
|
* Base callgrind settings
|
||||||
*/
|
*/
|
||||||
@@ -130,15 +154,10 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Global memcheck settings
|
* Global memcheck settings
|
||||||
*/
|
*/
|
||||||
QStringList suppressionFiles() const override;
|
|
||||||
// in the global settings we change the internal list directly
|
|
||||||
void addSuppressionFiles(const QStringList &) override;
|
|
||||||
void removeSuppressionFiles(const QStringList &) override;
|
|
||||||
|
|
||||||
void writeSettings() const;
|
void writeSettings() const;
|
||||||
void readSettings();
|
void readSettings();
|
||||||
|
|
||||||
Utils::StringListAspect suppressionFiles_;
|
|
||||||
Utils::StringAspect lastSuppressionDirectory;
|
Utils::StringAspect lastSuppressionDirectory;
|
||||||
Utils::StringAspect lastSuppressionHistory;
|
Utils::StringAspect lastSuppressionHistory;
|
||||||
|
|
||||||
@@ -161,18 +180,6 @@ class ValgrindProjectSettings : public ValgrindBaseSettings
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
ValgrindProjectSettings();
|
ValgrindProjectSettings();
|
||||||
|
|
||||||
/**
|
|
||||||
* Per-project memcheck settings, saves a diff to the global suppression files list
|
|
||||||
*/
|
|
||||||
QStringList suppressionFiles() const override;
|
|
||||||
// in the project-specific settings we store a diff to the global list
|
|
||||||
void addSuppressionFiles(const QStringList &suppressions) override;
|
|
||||||
void removeSuppressionFiles(const QStringList &suppressions) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
Utils::StringListAspect disabledGlobalSuppressionFiles;
|
|
||||||
Utils::StringListAspect addedSuppressionFiles;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
Reference in New Issue
Block a user