diff options
author | Eike Ziller <eike.ziller@theqtcompany.com> | 2014-11-26 11:12:29 +0100 |
---|---|---|
committer | Eike Ziller <eike.ziller@theqtcompany.com> | 2014-11-26 11:12:41 +0100 |
commit | 63b705184a3cd1533c002fedfb4922811b20b6db (patch) | |
tree | 82b682e82defa2ce4b8db4eff2d67935c3d30420 | |
parent | 6d4dfed9b0415eb93440f53909ab602b32510b43 (diff) | |
parent | 4bdd4c263ec53b7a2c8773912285ddb8d970da2e (diff) | |
download | qt-creator-63b705184a3cd1533c002fedfb4922811b20b6db.tar.gz |
Merge remote-tracking branch 'origin/3.3'
Change-Id: I182f4971b7ade725fc6d8c94ce194401bce51566
4 files changed, 112 insertions, 27 deletions
diff --git a/plugins/clangstaticanalyzer/clangstaticanalyzerdiagnosticmodel.cpp b/plugins/clangstaticanalyzer/clangstaticanalyzerdiagnosticmodel.cpp index 2318c50c05..2b21765331 100644 --- a/plugins/clangstaticanalyzer/clangstaticanalyzerdiagnosticmodel.cpp +++ b/plugins/clangstaticanalyzer/clangstaticanalyzerdiagnosticmodel.cpp @@ -58,19 +58,20 @@ static QString createDiagnosticToolTipString(const Diagnostic &diagnostic) if (!diagnostic.category.isEmpty()) { lines << qMakePair( QCoreApplication::translate("ClangStaticAnalyzer::Diagnostic", "Category:"), - diagnostic.category); + diagnostic.category.toHtmlEscaped()); } if (!diagnostic.type.isEmpty()) { lines << qMakePair( QCoreApplication::translate("ClangStaticAnalyzer::Diagnostic", "Type:"), - diagnostic.type); + diagnostic.type.toHtmlEscaped()); } if (!diagnostic.issueContext.isEmpty() && !diagnostic.issueContextKind.isEmpty()) { lines << qMakePair( QCoreApplication::translate("ClangStaticAnalyzer::Diagnostic", "Context:"), - diagnostic.issueContextKind + QLatin1Char(' ') + diagnostic.issueContext); + diagnostic.issueContextKind.toHtmlEscaped() + QLatin1Char(' ') + + diagnostic.issueContext.toHtmlEscaped()); } lines << qMakePair( diff --git a/plugins/clangstaticanalyzer/clangstaticanalyzerdiagnosticview.cpp b/plugins/clangstaticanalyzer/clangstaticanalyzerdiagnosticview.cpp index 6d00968c86..616cf9f369 100644 --- a/plugins/clangstaticanalyzer/clangstaticanalyzerdiagnosticview.cpp +++ b/plugins/clangstaticanalyzer/clangstaticanalyzerdiagnosticview.cpp @@ -21,12 +21,19 @@ #include "clangstaticanalyzerlogfilereader.h" #include "clangstaticanalyzerutils.h" +#include <coreplugin/coreconstants.h> + #include <utils/qtcassert.h> +#include <QAction> +#include <QApplication> +#include <QClipboard> +#include <QContextMenuEvent> #include <QCoreApplication> #include <QDebug> #include <QFileInfo> #include <QLabel> +#include <QMenu> #include <QVBoxLayout> using namespace Analyzer; @@ -56,7 +63,9 @@ QString createSummaryText(const ClangStaticAnalyzer::Internal::Diagnostic &diagn const QString location = fileName + QLatin1Char(' ') + QString::number(diagnostic.location.line); return QString::fromLatin1("%1 <span %3>%2</span>") - .arg(diagnostic.description, location, linkStyle); + .arg(diagnostic.description.toHtmlEscaped(), + location, + linkStyle); } QLabel *createSummaryLabel(const ClangStaticAnalyzer::Internal::Diagnostic &diagnostic) @@ -90,29 +99,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 <a href=\"file://") + filePath + QLatin1Char(':') + lineNumber + QLatin1Char(':') + columnNumber + QLatin1String("\">") - + fileNameAndLine + + fileAndLine + QLatin1String("</a>"); } 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("<code style='white-space:pre'>%1:</code>").arg(number, fieldWidth); + const QString result = QString::fromLatin1("%1:").arg(number, fieldWidth); + return withMarkup + ? QLatin1String("<code style='white-space:pre'>") + result + QLatin1String("</code>") + : result; } QString createExplainingStepToolTipString(const ClangStaticAnalyzer::Internal::ExplainingStep &step) @@ -126,12 +138,12 @@ QString createExplainingStepToolTipString(const ClangStaticAnalyzer::Internal::E if (!step.message.isEmpty()) { lines << qMakePair( QCoreApplication::translate("ClangStaticAnalyzer::ExplainingStep", "Message:"), - step.message); + step.message.toHtmlEscaped()); } if (!step.extendedMessage.isEmpty()) { lines << qMakePair( QCoreApplication::translate("ClangStaticAnalyzer::ExplainingStep", "Extended Message:"), - step.extendedMessage); + step.extendedMessage.toHtmlEscaped()); } lines << qMakePair( @@ -154,6 +166,19 @@ 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(' ') + + (withMarkup + ? explainingStep.extendedMessage.toHtmlEscaped() + : explainingStep.extendedMessage) + + QLatin1Char(' ') + + createLocationString(explainingStep.location, withMarkup, withAbsolutePath); +} + } // anonymous namespace namespace ClangStaticAnalyzer { @@ -172,13 +197,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<Diagnostic>(); + 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, @@ -186,12 +234,13 @@ QWidget *ClangStaticAnalyzerDiagnosticDelegate::createDetailsWidget(const QFont QWidget *parent) const { QWidget *widget = new QWidget(parent); - QVBoxLayout *layout = new QVBoxLayout; const Diagnostic diagnostic = index.data(Qt::UserRole).value<Diagnostic>(); if (!diagnostic.isValid()) return widget; + QVBoxLayout *layout = new QVBoxLayout; + // Add summary label QLabel *summaryLineLabel = createSummaryLabel(diagnostic); connect(summaryLineLabel, &QLabel::linkActivated, @@ -201,12 +250,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 +269,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 5042267776..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); @@ -185,9 +184,7 @@ static bool dontStartAfterHintForDebugMode() .arg(toolName).arg(wrongMode); if (Utils::CheckableMessageBox::doNotAskAgainQuestion(Core::ICore::mainWindow(), title, message, Core::ICore::settings(), - QLatin1String("ClangStaticAnalyzerCorrectModeWarning"), - QDialogButtonBox::Yes|QDialogButtonBox::Cancel, - QDialogButtonBox::Cancel, QDialogButtonBox::Yes) != QDialogButtonBox::Yes) + QLatin1String("ClangStaticAnalyzerCorrectModeWarning")) != QDialogButtonBox::Yes) return true; } |