diff --git a/src/plugins/analyzerbase/detailederrorview.cpp b/src/plugins/analyzerbase/detailederrorview.cpp index f6a6f3fbc27..d15c8b2e72c 100644 --- a/src/plugins/analyzerbase/detailederrorview.cpp +++ b/src/plugins/analyzerbase/detailederrorview.cpp @@ -30,10 +30,14 @@ #include "detailederrorview.h" +#include #include #include +#include +#include +#include #include #include #include @@ -216,6 +220,11 @@ void DetailedErrorDelegate::openLinkInEditor(const QString &link) Core::EditorManager::openEditorAt(path, qMax(line, 0), qMax(column, 0)); } +void DetailedErrorDelegate::copyToClipboard() +{ + QApplication::clipboard()->setText(textualRepresentation()); +} + DetailedErrorView::DetailedErrorView(QWidget *parent) : QListView(parent) { @@ -232,6 +241,14 @@ void DetailedErrorView::setItemDelegate(QAbstractItemDelegate *delegate) DetailedErrorDelegate *myDelegate = qobject_cast(itemDelegate()); connect(this, &DetailedErrorView::resized, myDelegate, &DetailedErrorDelegate::onViewResized); + + 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, myDelegate, &DetailedErrorDelegate::copyToClipboard); + addAction(m_copyAction); } void DetailedErrorView::setModel(QAbstractItemModel *model) @@ -253,6 +270,21 @@ void DetailedErrorView::resizeEvent(QResizeEvent *e) QListView::resizeEvent(e); } +void DetailedErrorView::contextMenuEvent(QContextMenuEvent *e) +{ + if (selectionModel()->selectedRows().isEmpty()) + return; + + QMenu menu; + menu.addActions(commonActions()); + const QList custom = customActions(); + if (!custom.isEmpty()) { + menu.addSeparator(); + menu.addActions(custom); + } + menu.exec(e->globalPos()); +} + void DetailedErrorView::updateGeometries() { if (model()) { @@ -284,6 +316,18 @@ int DetailedErrorView::rowCount() const return model() ? model()->rowCount() : 0; } +QList DetailedErrorView::commonActions() const +{ + QList actions; + actions << m_copyAction; + return actions; +} + +QList DetailedErrorView::customActions() const +{ + return QList(); +} + int DetailedErrorView::currentRow() const { const QModelIndex index = selectionModel()->currentIndex(); diff --git a/src/plugins/analyzerbase/detailederrorview.h b/src/plugins/analyzerbase/detailederrorview.h index dd8b23d511b..8631b692f0d 100644 --- a/src/plugins/analyzerbase/detailederrorview.h +++ b/src/plugins/analyzerbase/detailederrorview.h @@ -55,7 +55,7 @@ public: explicit DetailedErrorDelegate(QListView *parent); virtual SummaryLineInfo summaryInfo(const QModelIndex &index) const = 0; - virtual void copy() = 0; + void copyToClipboard(); QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const; void paint(QPainter *painter, const QStyleOptionViewItem &option, @@ -77,6 +77,7 @@ private: // the constness of this function is a necessary lie because it is called from paint() const. virtual QWidget *createDetailsWidget(const QFont &font, const QModelIndex &errorIndex, QWidget *parent) const = 0; + virtual QString textualRepresentation() const = 0; static const int s_itemMargin = 2; mutable QWidget *m_detailsWidget; @@ -109,10 +110,16 @@ protected: void resizeEvent(QResizeEvent *e); private: + void contextMenuEvent(QContextMenuEvent *e) Q_DECL_OVERRIDE; + int currentRow() const; void setCurrentRow(int row); - int rowCount() const; + + QList commonActions() const; + virtual QList customActions() const; + + QAction *m_copyAction; }; } // namespace Analyzer diff --git a/src/plugins/valgrind/memcheckerrorview.cpp b/src/plugins/valgrind/memcheckerrorview.cpp index f64c8e583b5..85c0ece2157 100644 --- a/src/plugins/valgrind/memcheckerrorview.cpp +++ b/src/plugins/valgrind/memcheckerrorview.cpp @@ -41,7 +41,6 @@ #include "xmlprotocol/modelhelpers.h" #include "xmlprotocol/suppression.h" -#include #include #include #include @@ -52,12 +51,7 @@ #include #include -#include -#include -#include #include -#include -#include #include #include #include @@ -77,13 +71,12 @@ class MemcheckErrorDelegate : public Analyzer::DetailedErrorDelegate public: explicit MemcheckErrorDelegate(QListView *parent); - void copy(); - SummaryLineInfo summaryInfo(const QModelIndex &index) const; private: QWidget *createDetailsWidget(const QFont &font, const QModelIndex &errorIndex, QWidget *parent) const; + QString textualRepresentation() const Q_DECL_OVERRIDE; }; static QString makeFrameName(const Frame &frame, const QString &relativeTo, @@ -261,9 +254,9 @@ Analyzer::DetailedErrorDelegate::SummaryLineInfo MemcheckErrorDelegate::summaryI return info; } -void MemcheckErrorDelegate::copy() +QString MemcheckErrorDelegate::textualRepresentation() const { - QTC_ASSERT(m_detailsIndex.isValid(), return); + QTC_ASSERT(m_detailsIndex.isValid(), return QString()); QString content; QTextStream stream(&content); @@ -283,7 +276,7 @@ void MemcheckErrorDelegate::copy() } stream.flush(); - QApplication::clipboard()->setText(content); + return content; } MemcheckErrorView::MemcheckErrorView(QWidget *parent) @@ -293,14 +286,6 @@ MemcheckErrorView::MemcheckErrorView(QWidget *parent) MemcheckErrorDelegate *delegate = new MemcheckErrorDelegate(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, &MemcheckErrorDelegate::copy); - addAction(m_copyAction); - m_suppressAction = new QAction(this); m_suppressAction->setText(tr("Suppress Error")); m_suppressAction->setIcon(QIcon(QLatin1String(":/qmldesigner/images/eye_crossed.png"))); @@ -332,32 +317,30 @@ void MemcheckErrorView::settingsChanged(ValgrindBaseSettings *settings) m_settings = settings; } -void MemcheckErrorView::contextMenuEvent(QContextMenuEvent *e) -{ - const QModelIndexList indizes = selectionModel()->selectedRows(); - if (indizes.isEmpty()) - return; - - QList errors; - foreach (const QModelIndex &index, indizes) { - Error error = model()->data(index, ErrorListModel::ErrorRole).value(); - if (!error.suppression().isNull()) - errors << error; - } - - QMenu menu; - menu.addAction(m_copyAction); - menu.addSeparator(); - menu.addAction(m_suppressAction); - m_suppressAction->setEnabled(!errors.isEmpty()); - menu.exec(e->globalPos()); -} - void MemcheckErrorView::suppressError() { SuppressionDialog::maybeShow(this); } +QList MemcheckErrorView::customActions() const +{ + QList actions; + const QModelIndexList indizes = selectionModel()->selectedRows(); + QTC_ASSERT(!indizes.isEmpty(), return actions); + + bool hasErrors = false; + foreach (const QModelIndex &index, indizes) { + Error error = model()->data(index, ErrorListModel::ErrorRole).value(); + if (!error.suppression().isNull()) { + hasErrors = true; + break; + } + } + m_suppressAction->setEnabled(hasErrors); + actions << m_suppressAction; + return actions; +} + } // namespace Internal } // namespace Valgrind diff --git a/src/plugins/valgrind/memcheckerrorview.h b/src/plugins/valgrind/memcheckerrorview.h index 579fc2434a5..6f086fae55a 100644 --- a/src/plugins/valgrind/memcheckerrorview.h +++ b/src/plugins/valgrind/memcheckerrorview.h @@ -57,11 +57,11 @@ public slots: void settingsChanged(ValgrindBaseSettings *settings); private slots: - void contextMenuEvent(QContextMenuEvent *e); void suppressError(); private: - QAction *m_copyAction; + QList customActions() const Q_DECL_OVERRIDE; + QAction *m_suppressAction; QString m_defaultSuppFile; ValgrindBaseSettings *m_settings;