From efce9b04fc200fc11114eb9ba2f4c1f8f67327d4 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Thu, 1 Oct 2020 10:27:17 +0200 Subject: [PATCH] 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 --- .../clangtools/clangtoolsdiagnosticmodel.cpp | 6 +++ .../clangtools/clangtoolsdiagnosticmodel.h | 1 + .../clangtools/clangtoolsdiagnosticview.cpp | 46 ++++++++++++------- .../clangtools/clangtoolsprojectsettings.cpp | 6 +++ .../clangtools/clangtoolsprojectsettings.h | 1 + .../debugger/analyzer/detailederrorview.cpp | 7 +-- 6 files changed, 48 insertions(+), 19 deletions(-) diff --git a/src/plugins/clangtools/clangtoolsdiagnosticmodel.cpp b/src/plugins/clangtools/clangtoolsdiagnosticmodel.cpp index 4320b760a00..ef5c6d974d8 100644 --- a/src/plugins/clangtools/clangtoolsdiagnosticmodel.cpp +++ b/src/plugins/clangtools/clangtoolsdiagnosticmodel.cpp @@ -538,6 +538,12 @@ void DiagnosticFilterModel::setProject(ProjectExplorer::Project *project) handleSuppressedDiagnosticsChanged(); } +void DiagnosticFilterModel::addSuppressedDiagnostics(const SuppressedDiagnosticsList &diags) +{ + m_suppressedDiagnostics << diags; + invalidate(); +} + void DiagnosticFilterModel::addSuppressedDiagnostic(const SuppressedDiagnostic &diag) { QTC_ASSERT(!m_project, return); diff --git a/src/plugins/clangtools/clangtoolsdiagnosticmodel.h b/src/plugins/clangtools/clangtoolsdiagnosticmodel.h index 9f4e61ef55f..695cd088e51 100644 --- a/src/plugins/clangtools/clangtoolsdiagnosticmodel.h +++ b/src/plugins/clangtools/clangtoolsdiagnosticmodel.h @@ -157,6 +157,7 @@ public: DiagnosticFilterModel(QObject *parent = nullptr); void setProject(ProjectExplorer::Project *project); + void addSuppressedDiagnostics(const SuppressedDiagnosticsList &diags); void addSuppressedDiagnostic(const SuppressedDiagnostic &diag); ProjectExplorer::Project *project() const { return m_project; } diff --git a/src/plugins/clangtools/clangtoolsdiagnosticview.cpp b/src/plugins/clangtools/clangtoolsdiagnosticview.cpp index dbe6f11564c..ca421e5c825 100644 --- a/src/plugins/clangtools/clangtoolsdiagnosticview.cpp +++ b/src/plugins/clangtools/clangtoolsdiagnosticview.cpp @@ -44,6 +44,7 @@ #include #include #include +#include using namespace Debugger; @@ -127,6 +128,7 @@ DiagnosticView::DiagnosticView(QWidget *parent) , m_delegate(new DiagnosticViewDelegate(m_style, this)) { header()->hide(); + setSelectionMode(ExtendedSelection); const QIcon filterIcon = Utils::Icon({{":/utils/images/filtericon.png", Utils::Theme::PanelTextColorMid}}, @@ -160,7 +162,7 @@ DiagnosticView::DiagnosticView(QWidget *parent) connect(m_help, &QAction::triggered, this, &DiagnosticView::showHelp); - m_suppressAction = new QAction(tr("Suppress This Diagnostic"), this); + m_suppressAction = new QAction(this); connect(m_suppressAction, &QAction::triggered, this, &DiagnosticView::suppressCurrentDiagnostic); @@ -194,27 +196,36 @@ DiagnosticView::~DiagnosticView() void DiagnosticView::suppressCurrentDiagnostic() { const QModelIndexList indexes = selectionModel()->selectedRows(); - QTC_ASSERT(indexes.count() == 1, return); - const Diagnostic diag = model()->data(indexes.first(), - ClangToolsDiagnosticModel::DiagnosticRole) - .value(); - QTC_ASSERT(diag.isValid(), return); // If the original project was closed, we work directly on the filter model, otherwise // we go via the project settings. - auto * const filterModel = static_cast(model()); + const auto filterModel = static_cast(model()); ProjectExplorer::Project * const project = filterModel->project(); - if (project) { + + SuppressedDiagnosticsList diags; + for (const QModelIndex &index : indexes) { + const Diagnostic diag = model()->data(index, ClangToolsDiagnosticModel::DiagnosticRole) + .value(); + if (!diag.isValid()) + continue; + if (!project) { + diags << diag; + continue; + } Utils::FilePath filePath = Utils::FilePath::fromString(diag.location.filePath); const Utils::FilePath relativeFilePath = filePath.relativeChildPath(project->projectDirectory()); if (!relativeFilePath.isEmpty()) filePath = relativeFilePath; - const SuppressedDiagnostic supDiag(filePath, diag.description, diag.explainingSteps.count()); - ClangToolsProjectSettings::getSettings(project)->addSuppressedDiagnostic(supDiag); - } else { - filterModel->addSuppressedDiagnostic(SuppressedDiagnostic(diag)); + const SuppressedDiagnostic supDiag(filePath, diag.description, + diag.explainingSteps.count()); + diags << SuppressedDiagnostic(filePath, diag.description, diag.explainingSteps.count()); } + + if (project) + ClangToolsProjectSettings::getSettings(project)->addSuppressedDiagnostics(diags); + else + filterModel->addSuppressedDiagnostics(diags); } void DiagnosticView::goNext() @@ -269,13 +280,16 @@ QList DiagnosticView::customActions() const { const QModelIndex currentIndex = selectionModel()->currentIndex(); + const bool hasMultiSelection = selectionModel()->selectedIndexes().size() > 1; const bool isDiagnosticItem = currentIndex.parent().isValid(); const QString docUrl = model()->data(currentIndex, ClangToolsDiagnosticModel::DocumentationUrlRole).toString(); - m_help->setEnabled(isDiagnosticItem && !docUrl.isEmpty()); - m_filterForCurrentKind->setEnabled(isDiagnosticItem); - m_filterOutCurrentKind->setEnabled(isDiagnosticItem); - m_suppressAction->setEnabled(isDiagnosticItem); + m_help->setEnabled(isDiagnosticItem && !docUrl.isEmpty() && !hasMultiSelection); + m_filterForCurrentKind->setEnabled(isDiagnosticItem && !hasMultiSelection); + m_filterOutCurrentKind->setEnabled(isDiagnosticItem && !hasMultiSelection); + m_suppressAction->setEnabled(isDiagnosticItem || hasMultiSelection); + m_suppressAction->setText(hasMultiSelection ? tr("Suppress Selected Diagnostics") + : tr("Suppress This Diagnostic")); return { m_help, diff --git a/src/plugins/clangtools/clangtoolsprojectsettings.cpp b/src/plugins/clangtools/clangtoolsprojectsettings.cpp index e92d87771bb..8982be792f8 100644 --- a/src/plugins/clangtools/clangtoolsprojectsettings.cpp +++ b/src/plugins/clangtools/clangtoolsprojectsettings.cpp @@ -93,6 +93,12 @@ void ClangToolsProjectSettings::setSelectedFiles(const QSet &va emit changed(); } +void ClangToolsProjectSettings::addSuppressedDiagnostics(const SuppressedDiagnosticsList &diags) +{ + m_suppressedDiagnostics << diags; + emit suppressedDiagnosticsChanged(); +} + void ClangToolsProjectSettings::addSuppressedDiagnostic(const SuppressedDiagnostic &diag) { QTC_ASSERT(!m_suppressedDiagnostics.contains(diag), return); diff --git a/src/plugins/clangtools/clangtoolsprojectsettings.h b/src/plugins/clangtools/clangtoolsprojectsettings.h index ed3c57fd72d..686aafedfb3 100644 --- a/src/plugins/clangtools/clangtoolsprojectsettings.h +++ b/src/plugins/clangtools/clangtoolsprojectsettings.h @@ -82,6 +82,7 @@ public: void setSelectedFiles(const QSet &value); SuppressedDiagnosticsList suppressedDiagnostics() const { return m_suppressedDiagnostics; } + void addSuppressedDiagnostics(const SuppressedDiagnosticsList &diags); void addSuppressedDiagnostic(const SuppressedDiagnostic &diag); void removeSuppressedDiagnostic(const SuppressedDiagnostic &diag); void removeAllSuppressedDiagnostics(); diff --git a/src/plugins/debugger/analyzer/detailederrorview.cpp b/src/plugins/debugger/analyzer/detailederrorview.cpp index 079bf34ac18..cdb59195357 100644 --- a/src/plugins/debugger/analyzer/detailederrorview.cpp +++ b/src/plugins/debugger/analyzer/detailederrorview.cpp @@ -56,9 +56,10 @@ DetailedErrorView::DetailedErrorView(QWidget *parent) : m_copyAction->setShortcutContext(Qt::WidgetWithChildrenShortcut); connect(m_copyAction, &QAction::triggered, [this] { const QModelIndexList selectedRows = selectionModel()->selectedRows(); - QTC_ASSERT(selectedRows.count() == 1, return); - QApplication::clipboard()->setText(model()->data(selectedRows.first(), - FullTextRole).toString()); + QStringList data; + for (const QModelIndex &index : selectedRows) + data << model()->data(index, FullTextRole).toString(); + QApplication::clipboard()->setText(data.join('\n')); }); connect(this, &QAbstractItemView::clicked, [](const QModelIndex &index) { if (index.column() == LocationColumn) {