forked from qt-creator/qt-creator
ClangTools: Allow multi-selection in diagnostics view
This enables users to suppress or copy several issues at once. Fixes: QTCREATORBUG-24396 Change-Id: Ib9019fd6a495b967627bf1ce53dead4d168e99da Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
@@ -538,6 +538,12 @@ void DiagnosticFilterModel::setProject(ProjectExplorer::Project *project)
|
|||||||
handleSuppressedDiagnosticsChanged();
|
handleSuppressedDiagnosticsChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DiagnosticFilterModel::addSuppressedDiagnostics(const SuppressedDiagnosticsList &diags)
|
||||||
|
{
|
||||||
|
m_suppressedDiagnostics << diags;
|
||||||
|
invalidate();
|
||||||
|
}
|
||||||
|
|
||||||
void DiagnosticFilterModel::addSuppressedDiagnostic(const SuppressedDiagnostic &diag)
|
void DiagnosticFilterModel::addSuppressedDiagnostic(const SuppressedDiagnostic &diag)
|
||||||
{
|
{
|
||||||
QTC_ASSERT(!m_project, return);
|
QTC_ASSERT(!m_project, return);
|
||||||
|
@@ -157,6 +157,7 @@ public:
|
|||||||
DiagnosticFilterModel(QObject *parent = nullptr);
|
DiagnosticFilterModel(QObject *parent = nullptr);
|
||||||
|
|
||||||
void setProject(ProjectExplorer::Project *project);
|
void setProject(ProjectExplorer::Project *project);
|
||||||
|
void addSuppressedDiagnostics(const SuppressedDiagnosticsList &diags);
|
||||||
void addSuppressedDiagnostic(const SuppressedDiagnostic &diag);
|
void addSuppressedDiagnostic(const SuppressedDiagnostic &diag);
|
||||||
ProjectExplorer::Project *project() const { return m_project; }
|
ProjectExplorer::Project *project() const { return m_project; }
|
||||||
|
|
||||||
|
@@ -44,6 +44,7 @@
|
|||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QHeaderView>
|
#include <QHeaderView>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
|
#include <QSet>
|
||||||
|
|
||||||
using namespace Debugger;
|
using namespace Debugger;
|
||||||
|
|
||||||
@@ -127,6 +128,7 @@ DiagnosticView::DiagnosticView(QWidget *parent)
|
|||||||
, m_delegate(new DiagnosticViewDelegate(m_style, this))
|
, m_delegate(new DiagnosticViewDelegate(m_style, this))
|
||||||
{
|
{
|
||||||
header()->hide();
|
header()->hide();
|
||||||
|
setSelectionMode(ExtendedSelection);
|
||||||
|
|
||||||
const QIcon filterIcon = Utils::Icon({{":/utils/images/filtericon.png",
|
const QIcon filterIcon = Utils::Icon({{":/utils/images/filtericon.png",
|
||||||
Utils::Theme::PanelTextColorMid}},
|
Utils::Theme::PanelTextColorMid}},
|
||||||
@@ -160,7 +162,7 @@ DiagnosticView::DiagnosticView(QWidget *parent)
|
|||||||
connect(m_help, &QAction::triggered,
|
connect(m_help, &QAction::triggered,
|
||||||
this, &DiagnosticView::showHelp);
|
this, &DiagnosticView::showHelp);
|
||||||
|
|
||||||
m_suppressAction = new QAction(tr("Suppress This Diagnostic"), this);
|
m_suppressAction = new QAction(this);
|
||||||
connect(m_suppressAction, &QAction::triggered,
|
connect(m_suppressAction, &QAction::triggered,
|
||||||
this, &DiagnosticView::suppressCurrentDiagnostic);
|
this, &DiagnosticView::suppressCurrentDiagnostic);
|
||||||
|
|
||||||
@@ -194,27 +196,36 @@ DiagnosticView::~DiagnosticView()
|
|||||||
void DiagnosticView::suppressCurrentDiagnostic()
|
void DiagnosticView::suppressCurrentDiagnostic()
|
||||||
{
|
{
|
||||||
const QModelIndexList indexes = selectionModel()->selectedRows();
|
const QModelIndexList indexes = selectionModel()->selectedRows();
|
||||||
QTC_ASSERT(indexes.count() == 1, return);
|
|
||||||
const Diagnostic diag = model()->data(indexes.first(),
|
|
||||||
ClangToolsDiagnosticModel::DiagnosticRole)
|
|
||||||
.value<Diagnostic>();
|
|
||||||
QTC_ASSERT(diag.isValid(), return);
|
|
||||||
|
|
||||||
// If the original project was closed, we work directly on the filter model, otherwise
|
// If the original project was closed, we work directly on the filter model, otherwise
|
||||||
// we go via the project settings.
|
// we go via the project settings.
|
||||||
auto * const filterModel = static_cast<DiagnosticFilterModel *>(model());
|
const auto filterModel = static_cast<DiagnosticFilterModel *>(model());
|
||||||
ProjectExplorer::Project * const project = filterModel->project();
|
ProjectExplorer::Project * const project = filterModel->project();
|
||||||
if (project) {
|
|
||||||
|
SuppressedDiagnosticsList diags;
|
||||||
|
for (const QModelIndex &index : indexes) {
|
||||||
|
const Diagnostic diag = model()->data(index, ClangToolsDiagnosticModel::DiagnosticRole)
|
||||||
|
.value<Diagnostic>();
|
||||||
|
if (!diag.isValid())
|
||||||
|
continue;
|
||||||
|
if (!project) {
|
||||||
|
diags << diag;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
Utils::FilePath filePath = Utils::FilePath::fromString(diag.location.filePath);
|
Utils::FilePath filePath = Utils::FilePath::fromString(diag.location.filePath);
|
||||||
const Utils::FilePath relativeFilePath
|
const Utils::FilePath relativeFilePath
|
||||||
= filePath.relativeChildPath(project->projectDirectory());
|
= filePath.relativeChildPath(project->projectDirectory());
|
||||||
if (!relativeFilePath.isEmpty())
|
if (!relativeFilePath.isEmpty())
|
||||||
filePath = relativeFilePath;
|
filePath = relativeFilePath;
|
||||||
const SuppressedDiagnostic supDiag(filePath, diag.description, diag.explainingSteps.count());
|
const SuppressedDiagnostic supDiag(filePath, diag.description,
|
||||||
ClangToolsProjectSettings::getSettings(project)->addSuppressedDiagnostic(supDiag);
|
diag.explainingSteps.count());
|
||||||
} else {
|
diags << SuppressedDiagnostic(filePath, diag.description, diag.explainingSteps.count());
|
||||||
filterModel->addSuppressedDiagnostic(SuppressedDiagnostic(diag));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (project)
|
||||||
|
ClangToolsProjectSettings::getSettings(project)->addSuppressedDiagnostics(diags);
|
||||||
|
else
|
||||||
|
filterModel->addSuppressedDiagnostics(diags);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DiagnosticView::goNext()
|
void DiagnosticView::goNext()
|
||||||
@@ -269,13 +280,16 @@ QList<QAction *> DiagnosticView::customActions() const
|
|||||||
{
|
{
|
||||||
const QModelIndex currentIndex = selectionModel()->currentIndex();
|
const QModelIndex currentIndex = selectionModel()->currentIndex();
|
||||||
|
|
||||||
|
const bool hasMultiSelection = selectionModel()->selectedIndexes().size() > 1;
|
||||||
const bool isDiagnosticItem = currentIndex.parent().isValid();
|
const bool isDiagnosticItem = currentIndex.parent().isValid();
|
||||||
const QString docUrl
|
const QString docUrl
|
||||||
= model()->data(currentIndex, ClangToolsDiagnosticModel::DocumentationUrlRole).toString();
|
= model()->data(currentIndex, ClangToolsDiagnosticModel::DocumentationUrlRole).toString();
|
||||||
m_help->setEnabled(isDiagnosticItem && !docUrl.isEmpty());
|
m_help->setEnabled(isDiagnosticItem && !docUrl.isEmpty() && !hasMultiSelection);
|
||||||
m_filterForCurrentKind->setEnabled(isDiagnosticItem);
|
m_filterForCurrentKind->setEnabled(isDiagnosticItem && !hasMultiSelection);
|
||||||
m_filterOutCurrentKind->setEnabled(isDiagnosticItem);
|
m_filterOutCurrentKind->setEnabled(isDiagnosticItem && !hasMultiSelection);
|
||||||
m_suppressAction->setEnabled(isDiagnosticItem);
|
m_suppressAction->setEnabled(isDiagnosticItem || hasMultiSelection);
|
||||||
|
m_suppressAction->setText(hasMultiSelection ? tr("Suppress Selected Diagnostics")
|
||||||
|
: tr("Suppress This Diagnostic"));
|
||||||
|
|
||||||
return {
|
return {
|
||||||
m_help,
|
m_help,
|
||||||
|
@@ -93,6 +93,12 @@ void ClangToolsProjectSettings::setSelectedFiles(const QSet<Utils::FilePath> &va
|
|||||||
emit changed();
|
emit changed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ClangToolsProjectSettings::addSuppressedDiagnostics(const SuppressedDiagnosticsList &diags)
|
||||||
|
{
|
||||||
|
m_suppressedDiagnostics << diags;
|
||||||
|
emit suppressedDiagnosticsChanged();
|
||||||
|
}
|
||||||
|
|
||||||
void ClangToolsProjectSettings::addSuppressedDiagnostic(const SuppressedDiagnostic &diag)
|
void ClangToolsProjectSettings::addSuppressedDiagnostic(const SuppressedDiagnostic &diag)
|
||||||
{
|
{
|
||||||
QTC_ASSERT(!m_suppressedDiagnostics.contains(diag), return);
|
QTC_ASSERT(!m_suppressedDiagnostics.contains(diag), return);
|
||||||
|
@@ -82,6 +82,7 @@ public:
|
|||||||
void setSelectedFiles(const QSet<Utils::FilePath> &value);
|
void setSelectedFiles(const QSet<Utils::FilePath> &value);
|
||||||
|
|
||||||
SuppressedDiagnosticsList suppressedDiagnostics() const { return m_suppressedDiagnostics; }
|
SuppressedDiagnosticsList suppressedDiagnostics() const { return m_suppressedDiagnostics; }
|
||||||
|
void addSuppressedDiagnostics(const SuppressedDiagnosticsList &diags);
|
||||||
void addSuppressedDiagnostic(const SuppressedDiagnostic &diag);
|
void addSuppressedDiagnostic(const SuppressedDiagnostic &diag);
|
||||||
void removeSuppressedDiagnostic(const SuppressedDiagnostic &diag);
|
void removeSuppressedDiagnostic(const SuppressedDiagnostic &diag);
|
||||||
void removeAllSuppressedDiagnostics();
|
void removeAllSuppressedDiagnostics();
|
||||||
|
@@ -56,9 +56,10 @@ DetailedErrorView::DetailedErrorView(QWidget *parent) :
|
|||||||
m_copyAction->setShortcutContext(Qt::WidgetWithChildrenShortcut);
|
m_copyAction->setShortcutContext(Qt::WidgetWithChildrenShortcut);
|
||||||
connect(m_copyAction, &QAction::triggered, [this] {
|
connect(m_copyAction, &QAction::triggered, [this] {
|
||||||
const QModelIndexList selectedRows = selectionModel()->selectedRows();
|
const QModelIndexList selectedRows = selectionModel()->selectedRows();
|
||||||
QTC_ASSERT(selectedRows.count() == 1, return);
|
QStringList data;
|
||||||
QApplication::clipboard()->setText(model()->data(selectedRows.first(),
|
for (const QModelIndex &index : selectedRows)
|
||||||
FullTextRole).toString());
|
data << model()->data(index, FullTextRole).toString();
|
||||||
|
QApplication::clipboard()->setText(data.join('\n'));
|
||||||
});
|
});
|
||||||
connect(this, &QAbstractItemView::clicked, [](const QModelIndex &index) {
|
connect(this, &QAbstractItemView::clicked, [](const QModelIndex &index) {
|
||||||
if (index.column() == LocationColumn) {
|
if (index.column() == LocationColumn) {
|
||||||
|
Reference in New Issue
Block a user