From 30b77eb0325669fa39331b1aef261c94c22a4c73 Mon Sep 17 00:00:00 2001 From: Nikolai Kosjar Date: Fri, 14 Nov 2014 13:39:59 +0100 Subject: DiagnosticView: Add copy action to context menu Task-number: QCE-22 Change-Id: I22a71bd99689e4eaece3b2595b28e0d434a52453 Reviewed-by: Riitta-Leena Miettinen Reviewed-by: Nikolai Kosjar --- .../clangstaticanalyzerdiagnosticview.cpp | 99 ++++++++++++++++++---- .../clangstaticanalyzerdiagnosticview.h | 13 +++ .../clangstaticanalyzertool.cpp | 3 +- 3 files changed, 98 insertions(+), 17 deletions(-) diff --git a/plugins/clangstaticanalyzer/clangstaticanalyzerdiagnosticview.cpp b/plugins/clangstaticanalyzer/clangstaticanalyzerdiagnosticview.cpp index 6d00968c86..0c0a872de3 100644 --- a/plugins/clangstaticanalyzer/clangstaticanalyzerdiagnosticview.cpp +++ b/plugins/clangstaticanalyzer/clangstaticanalyzerdiagnosticview.cpp @@ -21,12 +21,19 @@ #include "clangstaticanalyzerlogfilereader.h" #include "clangstaticanalyzerutils.h" +#include + #include +#include +#include +#include +#include #include #include #include #include +#include #include using namespace Analyzer; @@ -90,29 +97,32 @@ QLabel *createExplainingStepLabel(const QFont &font, bool useAlternateRowPalette } QString createLocationString(const ClangStaticAnalyzer::Internal::Location &location, - bool withMarkup) + bool withMarkup, bool withAbsolutePath) { const QString filePath = location.filePath; - const QString fileName = QFileInfo(filePath).fileName(); const QString lineNumber = QString::number(location.line); const QString columnNumber = QString::number(location.column - 1); - const QString fileNameAndLine = fileName + QLatin1Char(':') + lineNumber; + const QString fileAndLine = (withAbsolutePath ? filePath : QFileInfo(filePath).fileName()) + + QLatin1Char(':') + lineNumber; if (withMarkup) { return QLatin1String("in ") - + fileNameAndLine + + fileAndLine + QLatin1String(""); } else { - return QLatin1String("in ") + fileNameAndLine; + return QLatin1String("in ") + fileAndLine; } } -QString createExplainingStepNumberString(int number) +QString createExplainingStepNumberString(int number, bool withMarkup) { const int fieldWidth = 2; - return QString::fromLatin1("%1:").arg(number, fieldWidth); + const QString result = QString::fromLatin1("%1:").arg(number, fieldWidth); + return withMarkup + ? QLatin1String("") + result + QLatin1String("") + : result; } QString createExplainingStepToolTipString(const ClangStaticAnalyzer::Internal::ExplainingStep &step) @@ -154,6 +164,17 @@ QString createExplainingStepToolTipString(const ClangStaticAnalyzer::Internal::E return html; } +QString createExplainingStepString( + const ClangStaticAnalyzer::Internal::ExplainingStep &explainingStep, + int number, bool withMarkup, bool withAbsolutePath) +{ + return createExplainingStepNumberString(number, withMarkup) + + QLatin1Char(' ') + + explainingStep.extendedMessage + + QLatin1Char(' ') + + createLocationString(explainingStep.location, withMarkup, withAbsolutePath); +} + } // anonymous namespace namespace ClangStaticAnalyzer { @@ -172,13 +193,36 @@ DetailedErrorDelegate::SummaryLineInfo ClangStaticAnalyzerDiagnosticDelegate::su DetailedErrorDelegate::SummaryLineInfo info; info.errorText = diagnostic.description; - info.errorLocation = createLocationString(diagnostic.location, /*withMarkup=*/ false); + info.errorLocation = createLocationString(diagnostic.location, + /*withMarkup=*/ false, + /*withAbsolutePath=*/ false); return info; } void ClangStaticAnalyzerDiagnosticDelegate::copy() { - qDebug() << Q_FUNC_INFO; + QTC_ASSERT(m_detailsIndex.isValid(), return); + + const Diagnostic diagnostic = m_detailsIndex.data(Qt::UserRole).value(); + QTC_ASSERT(diagnostic.isValid(), return); + + // Create summary + QString clipboardText = diagnostic.category + QLatin1String(": ") + diagnostic.type; + if (diagnostic.type != diagnostic.description) + clipboardText += QLatin1String(": ") + diagnostic.description; + clipboardText += QLatin1Char('\n'); + + // Create explaining steps + int explainingStepNumber = 1; + foreach (const ExplainingStep &explainingStep, diagnostic.explainingSteps) { + clipboardText += createExplainingStepString(explainingStep, + explainingStepNumber++, + /*withMarkup=*/ false, + /*withAbsolutePath=*/ true) + QLatin1Char('\n'); + } + + clipboardText.chop(1); // Remove \n + QApplication::clipboard()->setText(clipboardText); } QWidget *ClangStaticAnalyzerDiagnosticDelegate::createDetailsWidget(const QFont &font, @@ -201,12 +245,10 @@ QWidget *ClangStaticAnalyzerDiagnosticDelegate::createDetailsWidget(const QFont // Add labels for explaining steps int explainingStepNumber = 1; foreach (const ExplainingStep &explainingStep, diagnostic.explainingSteps) { - const QString text = createExplainingStepNumberString(explainingStepNumber++) - + QLatin1Char(' ') - + explainingStep.extendedMessage - + QLatin1Char(' ') - + createLocationString(explainingStep.location, /*withMarkup=*/ true); - + const QString text = createExplainingStepString(explainingStep, + explainingStepNumber++, + /*withMarkup=*/ true, + /*withAbsolutePath=*/ false); QLabel *label = createExplainingStepLabel(font, explainingStepNumber % 2 == 0); label->setParent(widget); label->setText(text); @@ -222,5 +264,32 @@ QWidget *ClangStaticAnalyzerDiagnosticDelegate::createDetailsWidget(const QFont return widget; } +ClangStaticAnalyzerDiagnosticView::ClangStaticAnalyzerDiagnosticView(QWidget *parent) + : Analyzer::DetailedErrorView(parent) +{ + ClangStaticAnalyzerDiagnosticDelegate *delegate + = new ClangStaticAnalyzerDiagnosticDelegate(this); + setItemDelegate(delegate); + + m_copyAction = new QAction(this); + m_copyAction->setText(tr("Copy")); + m_copyAction->setIcon(QIcon(QLatin1String(Core::Constants::ICON_COPY))); + m_copyAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_C)); + m_copyAction->setShortcutContext(Qt::WidgetWithChildrenShortcut); + connect(m_copyAction, &QAction::triggered, + delegate, &ClangStaticAnalyzerDiagnosticDelegate::copy); + addAction(m_copyAction); +} + +void ClangStaticAnalyzerDiagnosticView::contextMenuEvent(QContextMenuEvent *e) +{ + if (selectionModel()->selectedRows().isEmpty()) + return; + + QMenu menu; + menu.addAction(m_copyAction); + menu.exec(e->globalPos()); +} + } // namespace Internal } // namespace ClangStaticAnalyzer diff --git a/plugins/clangstaticanalyzer/clangstaticanalyzerdiagnosticview.h b/plugins/clangstaticanalyzer/clangstaticanalyzerdiagnosticview.h index 551aff3e72..5830a05a50 100644 --- a/plugins/clangstaticanalyzer/clangstaticanalyzerdiagnosticview.h +++ b/plugins/clangstaticanalyzer/clangstaticanalyzerdiagnosticview.h @@ -24,6 +24,19 @@ namespace ClangStaticAnalyzer { namespace Internal { +class ClangStaticAnalyzerDiagnosticView : public Analyzer::DetailedErrorView +{ + Q_OBJECT + +public: + ClangStaticAnalyzerDiagnosticView(QWidget *parent = 0); + +private: + void contextMenuEvent(QContextMenuEvent *e); + + QAction *m_copyAction; +}; + class ClangStaticAnalyzerDiagnosticDelegate : public Analyzer::DetailedErrorDelegate { public: diff --git a/plugins/clangstaticanalyzer/clangstaticanalyzertool.cpp b/plugins/clangstaticanalyzer/clangstaticanalyzertool.cpp index 4da16b98f3..ffec5af1a7 100644 --- a/plugins/clangstaticanalyzer/clangstaticanalyzertool.cpp +++ b/plugins/clangstaticanalyzer/clangstaticanalyzertool.cpp @@ -70,8 +70,7 @@ QWidget *ClangStaticAnalyzerTool::createWidgets() // // Diagnostic View // - m_diagnosticView = new DetailedErrorView; - m_diagnosticView->setItemDelegate(new ClangStaticAnalyzerDiagnosticDelegate(m_diagnosticView)); + m_diagnosticView = new ClangStaticAnalyzerDiagnosticView; m_diagnosticView->setObjectName(QLatin1String("ClangStaticAnalyzerIssuesView")); m_diagnosticView->setFrameStyle(QFrame::NoFrame); m_diagnosticView->setAttribute(Qt::WA_MacShowFocusRect, false); -- cgit v1.2.3