diff --git a/src/plugins/analyzerbase/analyzerbase.pro b/src/plugins/analyzerbase/analyzerbase.pro index e734ffcb1cd..a7013745789 100644 --- a/src/plugins/analyzerbase/analyzerbase.pro +++ b/src/plugins/analyzerbase/analyzerbase.pro @@ -13,6 +13,7 @@ SOURCES += \ analyzermanager.cpp \ analyzerrunconfigwidget.cpp \ analyzerutils.cpp \ + detailederrorview.cpp \ startremotedialog.cpp HEADERS += \ @@ -25,6 +26,7 @@ HEADERS += \ analyzerstartparameters.h \ analyzerrunconfigwidget.h \ analyzerutils.h \ + detailederrorview.h \ startremotedialog.h RESOURCES += \ diff --git a/src/plugins/analyzerbase/analyzerbase.qbs b/src/plugins/analyzerbase/analyzerbase.qbs index 6506ed43cd3..14c1ce79a50 100644 --- a/src/plugins/analyzerbase/analyzerbase.qbs +++ b/src/plugins/analyzerbase/analyzerbase.qbs @@ -29,6 +29,8 @@ QtcPlugin { "analyzerstartparameters.h", "analyzerutils.cpp", "analyzerutils.h", + "detailederrorview.cpp", + "detailederrorview.h", "ianalyzertool.cpp", "ianalyzertool.h", "startremotedialog.cpp", diff --git a/src/plugins/analyzerbase/detailederrorview.cpp b/src/plugins/analyzerbase/detailederrorview.cpp new file mode 100644 index 00000000000..c1671cc997c --- /dev/null +++ b/src/plugins/analyzerbase/detailederrorview.cpp @@ -0,0 +1,294 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://www.qt.io/licensing. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#include "detailederrorview.h" + +#include + +#include + +#include +#include +#include + +namespace Analyzer { + +DetailedErrorDelegate::DetailedErrorDelegate(QListView *parent) + : QStyledItemDelegate(parent), + m_detailsWidget(0) +{ + connect(parent->verticalScrollBar(), &QScrollBar::valueChanged, + this, &DetailedErrorDelegate::onVerticalScroll); +} + +QSize DetailedErrorDelegate::sizeHint(const QStyleOptionViewItem &opt, + const QModelIndex &index) const +{ + const QListView *view = qobject_cast(parent()); + const int viewportWidth = view->viewport()->width(); + const bool isSelected = view->selectionModel()->currentIndex() == index; + const int dy = 2 * s_itemMargin; + + if (!isSelected) { + QFontMetrics fm(opt.font); + return QSize(viewportWidth, fm.height() + dy); + } + + if (m_detailsWidget && m_detailsIndex != index) { + m_detailsWidget->deleteLater(); + m_detailsWidget = 0; + } + + if (!m_detailsWidget) { + m_detailsWidget = createDetailsWidget(opt.font, index, view->viewport()); + QTC_ASSERT(m_detailsWidget->parent() == view->viewport(), + m_detailsWidget->setParent(view->viewport())); + m_detailsIndex = index; + } else { + QTC_ASSERT(m_detailsIndex == index, /**/); + } + const int widthExcludingMargins = viewportWidth - 2 * s_itemMargin; + m_detailsWidget->setFixedWidth(widthExcludingMargins); + + m_detailsWidgetHeight = m_detailsWidget->heightForWidth(widthExcludingMargins); + // HACK: it's a bug in QLabel(?) that we have to force the widget to have the size it said + // it would have. + m_detailsWidget->setFixedHeight(m_detailsWidgetHeight); + return QSize(viewportWidth, dy + m_detailsWidget->heightForWidth(widthExcludingMargins)); +} + +void DetailedErrorDelegate::paint(QPainter *painter, const QStyleOptionViewItem &basicOption, + const QModelIndex &index) const +{ + QStyleOptionViewItemV4 opt(basicOption); + initStyleOption(&opt, index); + + const QListView *const view = qobject_cast(parent()); + const bool isSelected = view->selectionModel()->currentIndex() == index; + + QFontMetrics fm(opt.font); + QPoint pos = opt.rect.topLeft(); + + painter->save(); + + const QColor bgColor = isSelected + ? opt.palette.highlight().color() + : opt.palette.background().color(); + painter->setBrush(bgColor); + + // clear background + painter->setPen(Qt::NoPen); + painter->drawRect(opt.rect); + + pos.rx() += s_itemMargin; + pos.ry() += s_itemMargin; + + if (isSelected) { + // only show detailed widget and let it handle everything + QTC_ASSERT(m_detailsIndex == index, /**/); + QTC_ASSERT(m_detailsWidget, return); // should have been set in sizeHint() + m_detailsWidget->move(pos); + // when scrolling quickly, the widget can get stuck in a visible part of the scroll area + // even though it should not be visible. therefore we hide it every time the scroll value + // changes and un-hide it when the item with details widget is paint()ed, i.e. visible. + m_detailsWidget->show(); + + const int viewportWidth = view->viewport()->width(); + const int widthExcludingMargins = viewportWidth - 2 * s_itemMargin; + QTC_ASSERT(m_detailsWidget->width() == widthExcludingMargins, /**/); + QTC_ASSERT(m_detailsWidgetHeight == m_detailsWidget->height(), /**/); + } else { + // the reference coordinate for text drawing is the text baseline; move it inside the view rect. + pos.ry() += fm.ascent(); + + const QColor textColor = opt.palette.text().color(); + painter->setPen(textColor); + // draw only text + location + + const SummaryLineInfo info = summaryInfo(index); + const QString errorText = info.errorText; + painter->drawText(pos, errorText); + + const int whatWidth = QFontMetrics(opt.font).width(errorText); + const int space = 10; + const int widthLeft = opt.rect.width() - (pos.x() + whatWidth + space + s_itemMargin); + if (widthLeft > 0) { + QFont monospace = opt.font; + monospace.setFamily(QLatin1String("monospace")); + QFontMetrics metrics(monospace); + QColor nameColor = textColor; + nameColor.setAlphaF(0.7); + + painter->setFont(monospace); + painter->setPen(nameColor); + + QPoint namePos = pos; + namePos.rx() += whatWidth + space; + painter->drawText(namePos, metrics.elidedText(info.errorLocation, Qt::ElideLeft, + widthLeft)); + } + } + + // Separator lines (like Issues pane) + painter->setPen(QColor::fromRgb(150,150,150)); + painter->drawLine(0, opt.rect.bottom(), opt.rect.right(), opt.rect.bottom()); + + painter->restore(); +} + +void DetailedErrorDelegate::onCurrentSelectionChanged(const QModelIndex &now, + const QModelIndex &previous) +{ + if (m_detailsWidget) { + m_detailsWidget->deleteLater(); + m_detailsWidget = 0; + } + + m_detailsIndex = QModelIndex(); + if (now.isValid()) + emit sizeHintChanged(now); + if (previous.isValid()) + emit sizeHintChanged(previous); +} + +void DetailedErrorDelegate::onLayoutChanged() +{ + if (m_detailsWidget) { + m_detailsWidget->deleteLater(); + m_detailsWidget = 0; + m_detailsIndex = QModelIndex(); + } +} + +void DetailedErrorDelegate::onViewResized() +{ + const QListView *view = qobject_cast(parent()); + if (m_detailsWidget) + emit sizeHintChanged(view->selectionModel()->currentIndex()); +} + +void DetailedErrorDelegate::onVerticalScroll() +{ + if (m_detailsWidget) + m_detailsWidget->hide(); +} + +void DetailedErrorDelegate::openLinkInEditor(const QString &link) +{ + const int pathStart = int(sizeof("file://")) - 1; + const int pathEnd = link.lastIndexOf(QLatin1Char(':')); + const QString path = link.mid(pathStart, pathEnd - pathStart); + const int line = link.mid(pathEnd + 1).toInt(0); + Core::EditorManager::openEditorAt(path, qMax(line, 0)); +} + +DetailedErrorView::DetailedErrorView(QWidget *parent) + : QListView(parent) +{ +} + +DetailedErrorView::~DetailedErrorView() +{ + itemDelegate()->deleteLater(); +} + +void DetailedErrorView::setItemDelegate(QAbstractItemDelegate *delegate) +{ + QListView::setItemDelegate(delegate); + + DetailedErrorDelegate *myDelegate = qobject_cast(itemDelegate()); + connect(this, &DetailedErrorView::resized, myDelegate, &DetailedErrorDelegate::onViewResized); +} + +void DetailedErrorView::setModel(QAbstractItemModel *model) +{ + QListView::setModel(model); + + DetailedErrorDelegate *delegate = qobject_cast(itemDelegate()); + QTC_ASSERT(delegate, return); + + connect(selectionModel(), &QItemSelectionModel::currentChanged, + delegate, &DetailedErrorDelegate::onCurrentSelectionChanged); + connect(model, &QAbstractItemModel::layoutChanged, + delegate, &DetailedErrorDelegate::onLayoutChanged); +} + +void DetailedErrorView::resizeEvent(QResizeEvent *e) +{ + emit resized(); + QListView::resizeEvent(e); +} + +void DetailedErrorView::updateGeometries() +{ + if (model()) { + QModelIndex index = model()->index(0, modelColumn(), rootIndex()); + QStyleOptionViewItem option = viewOptions(); + // delegate for row / column + QSize step = itemDelegate()->sizeHint(option, index); + horizontalScrollBar()->setSingleStep(step.width() + spacing()); + verticalScrollBar()->setSingleStep(step.height() + spacing()); + } + QListView::updateGeometries(); +} + +void DetailedErrorView::goNext() +{ + QTC_ASSERT(rowCount(), return); + setCurrentRow((currentRow() + 1) % rowCount()); +} + +void DetailedErrorView::goBack() +{ + QTC_ASSERT(rowCount(), return); + const int prevRow = currentRow() - 1; + setCurrentRow(prevRow >= 0 ? prevRow : rowCount() - 1); +} + +int DetailedErrorView::rowCount() const +{ + return model() ? model()->rowCount() : 0; +} + +int DetailedErrorView::currentRow() const +{ + const QModelIndex index = selectionModel()->currentIndex(); + return index.row(); +} + +void DetailedErrorView::setCurrentRow(int row) +{ + const QModelIndex index = model()->index(row, 0); + selectionModel()->setCurrentIndex(index, + QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); + scrollTo(index); +} + +} // namespace Analyzer diff --git a/src/plugins/analyzerbase/detailederrorview.h b/src/plugins/analyzerbase/detailederrorview.h new file mode 100644 index 00000000000..dd8b23d511b --- /dev/null +++ b/src/plugins/analyzerbase/detailederrorview.h @@ -0,0 +1,120 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://www.qt.io/licensing. For further information +** use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +****************************************************************************/ + +#ifndef DETAILEDERRORVIEW_H +#define DETAILEDERRORVIEW_H + +#include "analyzerbase_global.h" + +#include +#include + +namespace Analyzer { + +// Provides the details widget for the DetailedErrorView +class ANALYZER_EXPORT DetailedErrorDelegate : public QStyledItemDelegate +{ + Q_OBJECT + +public: + struct SummaryLineInfo { + QString errorText; + QString errorLocation; + }; + +public: + /// This delegate can only work on one view at a time, parent. parent will also be the parent + /// in the QObject parent-child system. + explicit DetailedErrorDelegate(QListView *parent); + + virtual SummaryLineInfo summaryInfo(const QModelIndex &index) const = 0; + virtual void copy() = 0; + + QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const; + void paint(QPainter *painter, const QStyleOptionViewItem &option, + const QModelIndex &index) const; + +public slots: + void onCurrentSelectionChanged(const QModelIndex &now, const QModelIndex &previous); + void onViewResized(); + void onLayoutChanged(); + +private slots: + void onVerticalScroll(); + +protected: + void openLinkInEditor(const QString &link); + mutable QPersistentModelIndex m_detailsIndex; + +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; + + static const int s_itemMargin = 2; + mutable QWidget *m_detailsWidget; + mutable int m_detailsWidgetHeight; +}; + +// A QListView that displays additional details for the currently selected item +class ANALYZER_EXPORT DetailedErrorView : public QListView +{ + Q_OBJECT + +public: + DetailedErrorView(QWidget *parent = 0); + ~DetailedErrorView(); + + // Reimplemented to connect delegate to connection model after it has + // been set by superclass implementation. + void setModel(QAbstractItemModel *model); + + void setItemDelegate(QAbstractItemDelegate *delegate); // Takes ownership + + void goNext(); + void goBack(); + +signals: + void resized(); + +protected: + void updateGeometries(); + void resizeEvent(QResizeEvent *e); + +private: + int currentRow() const; + void setCurrentRow(int row); + + int rowCount() const; +}; + +} // namespace Analyzer + +#endif // DETAILEDERRORVIEW_H diff --git a/src/plugins/valgrind/memcheckerrorview.cpp b/src/plugins/valgrind/memcheckerrorview.cpp index 199946fd20a..9862133ea36 100644 --- a/src/plugins/valgrind/memcheckerrorview.cpp +++ b/src/plugins/valgrind/memcheckerrorview.cpp @@ -70,82 +70,22 @@ using namespace Valgrind::XmlProtocol; namespace Valgrind { namespace Internal { -class MemcheckErrorDelegate : public QStyledItemDelegate +class MemcheckErrorDelegate : public Analyzer::DetailedErrorDelegate { Q_OBJECT public: - /// This delegate can only work on one view at a time, parent. parent will also be the parent - /// in the QObject parent-child system. explicit MemcheckErrorDelegate(QListView *parent); - QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const; - void paint(QPainter *painter, const QStyleOptionViewItem &option, - const QModelIndex &index) const; - -public slots: - void currentChanged(const QModelIndex &now, const QModelIndex &previous); - void viewResized(); - void layoutChanged(); void copy(); -private slots: - void verticalScrolled(); - void openLinkInEditor(const QString &link); + SummaryLineInfo summaryInfo(const QModelIndex &index) const; private: - // the constness of this function is a necessary lie because it is called from paint() const. - QWidget *createDetailsWidget(const QFont &font, const QModelIndex &errorIndex, QWidget *parent) const; - - static const int s_itemMargin = 2; - mutable QPersistentModelIndex m_detailsIndex; - mutable QWidget *m_detailsWidget; - mutable int m_detailsWidgetHeight; + QWidget *createDetailsWidget(const QFont &font, const QModelIndex &errorIndex, + QWidget *parent) const; }; -MemcheckErrorDelegate::MemcheckErrorDelegate(QListView *parent) - : QStyledItemDelegate(parent), - m_detailsWidget(0) -{ - connect(parent->verticalScrollBar(), SIGNAL(valueChanged(int)), - SLOT(verticalScrolled())); -} - -QSize MemcheckErrorDelegate::sizeHint(const QStyleOptionViewItem &opt, const QModelIndex &index) const -{ - const QListView *view = qobject_cast(parent()); - const int viewportWidth = view->viewport()->width(); - const bool isSelected = view->selectionModel()->currentIndex() == index; - const int dy = 2 * s_itemMargin; - - if (!isSelected) { - QFontMetrics fm(opt.font); - return QSize(viewportWidth, fm.height() + dy); - } - - if (m_detailsWidget && m_detailsIndex != index) { - m_detailsWidget->deleteLater(); - m_detailsWidget = 0; - } - - if (!m_detailsWidget) { - m_detailsWidget = createDetailsWidget(opt.font, index, view->viewport()); - QTC_ASSERT(m_detailsWidget->parent() == view->viewport(), - m_detailsWidget->setParent(view->viewport())); - m_detailsIndex = index; - } else { - QTC_ASSERT(m_detailsIndex == index, /**/); - } - const int widthExcludingMargins = viewportWidth - 2 * s_itemMargin; - m_detailsWidget->setFixedWidth(widthExcludingMargins); - - m_detailsWidgetHeight = m_detailsWidget->heightForWidth(widthExcludingMargins); - // HACK: it's a bug in QLabel(?) that we have to force the widget to have the size it said - // it would have. - m_detailsWidget->setFixedHeight(m_detailsWidgetHeight); - return QSize(viewportWidth, dy + m_detailsWidget->heightForWidth(widthExcludingMargins)); -} - static QString makeFrameName(const Frame &frame, const QString &relativeTo, bool link = true, const QString &linkAttr = QString()) { @@ -239,7 +179,8 @@ QWidget *MemcheckErrorDelegate::createDetailsWidget(const QFont & font, const QM errorLabel->setText(QString::fromLatin1("%1  %2") .arg(error.what(), errorLocation(errorIndex, error, true, linkStyle), linkStyle)); - connect(errorLabel, SIGNAL(linkActivated(QString)), SLOT(openLinkInEditor(QString))); + connect(errorLabel, &QLabel::linkActivated, + this, &MemcheckErrorDelegate::openLinkInEditor); layout->addWidget(errorLabel); const QVector stacks = error.stacks(); @@ -274,7 +215,8 @@ QWidget *MemcheckErrorDelegate::createDetailsWidget(const QFont & font, const QM QFont fixedPitchFont = font; fixedPitchFont.setFixedPitch(true); frameLabel->setFont(fixedPitchFont); - connect(frameLabel, SIGNAL(linkActivated(QString)), SLOT(openLinkInEditor(QString))); + connect(frameLabel, &QLabel::linkActivated, + this, &MemcheckErrorDelegate::openLinkInEditor); // pad frameNr to 2 chars since only 50 frames max are supported by valgrind const QString displayText = displayTextTemplate .arg(frameNr++, 2).arg(frameName); @@ -295,117 +237,19 @@ QWidget *MemcheckErrorDelegate::createDetailsWidget(const QFont & font, const QM return widget; } -void MemcheckErrorDelegate::paint(QPainter *painter, const QStyleOptionViewItem &basicOption, - const QModelIndex &index) const +MemcheckErrorDelegate::MemcheckErrorDelegate(QListView *parent) + : Analyzer::DetailedErrorDelegate(parent) { - QStyleOptionViewItemV4 opt(basicOption); - initStyleOption(&opt, index); - - const QListView *const view = qobject_cast(parent()); - const bool isSelected = view->selectionModel()->currentIndex() == index; - - QFontMetrics fm(opt.font); - QPoint pos = opt.rect.topLeft(); - - painter->save(); - - const QColor bgColor = isSelected ? opt.palette.highlight().color() : opt.palette.background().color(); - painter->setBrush(bgColor); - - // clear background - painter->setPen(Qt::NoPen); - painter->drawRect(opt.rect); - - pos.rx() += s_itemMargin; - pos.ry() += s_itemMargin; +} +Analyzer::DetailedErrorDelegate::SummaryLineInfo MemcheckErrorDelegate::summaryInfo( + const QModelIndex &index) const +{ const Error error = index.data(ErrorListModel::ErrorRole).value(); - - if (isSelected) { - // only show detailed widget and let it handle everything - QTC_ASSERT(m_detailsIndex == index, /**/); - QTC_ASSERT(m_detailsWidget, return); // should have been set in sizeHint() - m_detailsWidget->move(pos); - // when scrolling quickly, the widget can get stuck in a visible part of the scroll area - // even though it should not be visible. therefore we hide it every time the scroll value - // changes and un-hide it when the item with details widget is paint()ed, i.e. visible. - m_detailsWidget->show(); - - const int viewportWidth = view->viewport()->width(); - const int widthExcludingMargins = viewportWidth - 2 * s_itemMargin; - QTC_ASSERT(m_detailsWidget->width() == widthExcludingMargins, /**/); - QTC_ASSERT(m_detailsWidgetHeight == m_detailsWidget->height(), /**/); - } else { - // the reference coordinate for text drawing is the text baseline; move it inside the view rect. - pos.ry() += fm.ascent(); - - const QColor textColor = opt.palette.text().color(); - painter->setPen(textColor); - // draw only text + location - const QString what = error.what(); - painter->drawText(pos, what); - - const QString name = errorLocation(index, error); - const int whatWidth = QFontMetrics(opt.font).width(what); - const int space = 10; - const int widthLeft = opt.rect.width() - (pos.x() + whatWidth + space + s_itemMargin); - if (widthLeft > 0) { - QFont monospace = opt.font; - monospace.setFamily(QLatin1String("monospace")); - QFontMetrics metrics(monospace); - QColor nameColor = textColor; - nameColor.setAlphaF(0.7); - - painter->setFont(monospace); - painter->setPen(nameColor); - - QPoint namePos = pos; - namePos.rx() += whatWidth + space; - painter->drawText(namePos, metrics.elidedText(name, Qt::ElideLeft, widthLeft)); - } - } - - // Separator lines (like Issues pane) - painter->setPen(QColor::fromRgb(150,150,150)); - painter->drawLine(0, opt.rect.bottom(), opt.rect.right(), opt.rect.bottom()); - - painter->restore(); -} - -void MemcheckErrorDelegate::currentChanged(const QModelIndex &now, const QModelIndex &previous) -{ - if (m_detailsWidget) { - m_detailsWidget->deleteLater(); - m_detailsWidget = 0; - } - - m_detailsIndex = QModelIndex(); - if (now.isValid()) - emit sizeHintChanged(now); - if (previous.isValid()) - emit sizeHintChanged(previous); -} - -void MemcheckErrorDelegate::layoutChanged() -{ - if (m_detailsWidget) { - m_detailsWidget->deleteLater(); - m_detailsWidget = 0; - m_detailsIndex = QModelIndex(); - } -} - -void MemcheckErrorDelegate::viewResized() -{ - const QListView *view = qobject_cast(parent()); - if (m_detailsWidget) - emit sizeHintChanged(view->selectionModel()->currentIndex()); -} - -void MemcheckErrorDelegate::verticalScrolled() -{ - if (m_detailsWidget) - m_detailsWidget->hide(); + SummaryLineInfo info; + info.errorText = error.what(); + info.errorLocation = errorLocation(index, error); + return info; } void MemcheckErrorDelegate::copy() @@ -434,28 +278,19 @@ void MemcheckErrorDelegate::copy() QApplication::clipboard()->setText(content); } -void MemcheckErrorDelegate::openLinkInEditor(const QString &link) -{ - const int pathStart = int(sizeof("file://")) - 1; - const int pathEnd = link.lastIndexOf(QLatin1Char(':')); - const QString path = link.mid(pathStart, pathEnd - pathStart); - const int line = link.mid(pathEnd + 1).toInt(0); - Core::EditorManager::openEditorAt(path, qMax(line, 0)); -} - MemcheckErrorView::MemcheckErrorView(QWidget *parent) - : QListView(parent), + : Analyzer::DetailedErrorView(parent), m_settings(0) { - setItemDelegate(new MemcheckErrorDelegate(this)); - connect(this, SIGNAL(resized()), itemDelegate(), SLOT(viewResized())); + MemcheckErrorDelegate *delegate = new MemcheckErrorDelegate(this); + setItemDelegate(delegate); m_copyAction = new QAction(this); m_copyAction->setText(tr("Copy Selection")); 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, SIGNAL(triggered()), itemDelegate(), SLOT(copy())); + connect(m_copyAction, &QAction::triggered, delegate, &MemcheckErrorDelegate::copy); addAction(m_copyAction); m_suppressAction = new QAction(this); @@ -463,29 +298,12 @@ MemcheckErrorView::MemcheckErrorView(QWidget *parent) m_suppressAction->setIcon(QIcon(QLatin1String(":/qmldesigner/images/eye_crossed.png"))); m_suppressAction->setShortcut(QKeySequence(Qt::Key_Delete)); m_suppressAction->setShortcutContext(Qt::WidgetWithChildrenShortcut); - connect(m_suppressAction, SIGNAL(triggered()), this, SLOT(suppressError())); + connect(m_suppressAction, &QAction::triggered, this, &MemcheckErrorView::suppressError); addAction(m_suppressAction); } MemcheckErrorView::~MemcheckErrorView() { - itemDelegate()->deleteLater(); -} - -void MemcheckErrorView::setModel(QAbstractItemModel *model) -{ - QListView::setModel(model); - connect(selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)), - itemDelegate(), SLOT(currentChanged(QModelIndex,QModelIndex))); - - connect(model, SIGNAL(layoutChanged()), - itemDelegate(), SLOT(layoutChanged())); -} - -void MemcheckErrorView::resizeEvent(QResizeEvent *e) -{ - emit resized(); - QListView::resizeEvent(e); } void MemcheckErrorView::setDefaultSuppressionFile(const QString &suppFile) @@ -498,19 +316,6 @@ QString MemcheckErrorView::defaultSuppressionFile() const return m_defaultSuppFile; } -void MemcheckErrorView::updateGeometries() -{ - if (model()) { - QModelIndex index = model()->index(0, modelColumn(), rootIndex()); - QStyleOptionViewItem option = viewOptions(); - // delegate for row / column - QSize step = itemDelegate()->sizeHint(option, index); - horizontalScrollBar()->setSingleStep(step.width() + spacing()); - verticalScrollBar()->setSingleStep(step.height() + spacing()); - } - QListView::updateGeometries(); -} - // slot, can (for now) be invoked either when the settings were modified *or* when the active // settings object has changed. void MemcheckErrorView::settingsChanged(ValgrindBaseSettings *settings) @@ -545,38 +350,6 @@ void MemcheckErrorView::suppressError() SuppressionDialog::maybeShow(this); } -void MemcheckErrorView::goNext() -{ - QTC_ASSERT(rowCount(), return); - setCurrentRow((currentRow() + 1) % rowCount()); -} - -void MemcheckErrorView::goBack() -{ - QTC_ASSERT(rowCount(), return); - const int prevRow = currentRow() - 1; - setCurrentRow(prevRow >= 0 ? prevRow : rowCount() - 1); -} - -int MemcheckErrorView::rowCount() const -{ - return model() ? model()->rowCount() : 0; -} - -int MemcheckErrorView::currentRow() const -{ - const QModelIndex index = selectionModel()->currentIndex(); - return index.row(); -} - -void MemcheckErrorView::setCurrentRow(int row) -{ - const QModelIndex index = model()->index(row, 0); - selectionModel()->setCurrentIndex(index, - QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); - scrollTo(index); -} - } // namespace Internal } // namespace Valgrind diff --git a/src/plugins/valgrind/memcheckerrorview.h b/src/plugins/valgrind/memcheckerrorview.h index 7e915dcea92..579fc2434a5 100644 --- a/src/plugins/valgrind/memcheckerrorview.h +++ b/src/plugins/valgrind/memcheckerrorview.h @@ -32,6 +32,8 @@ #ifndef MEMCHECKERRORVIEW_H #define MEMCHECKERRORVIEW_H +#include + #include namespace Valgrind { @@ -39,7 +41,7 @@ namespace Internal { class ValgrindBaseSettings; -class MemcheckErrorView : public QListView +class MemcheckErrorView : public Analyzer::DetailedErrorView { Q_OBJECT @@ -47,34 +49,18 @@ public: MemcheckErrorView(QWidget *parent = 0); ~MemcheckErrorView(); - // Reimplemented to connect delegate to connection model after it has - // been set by superclass implementation. - void setModel(QAbstractItemModel *model); - void setDefaultSuppressionFile(const QString &suppFile); QString defaultSuppressionFile() const; ValgrindBaseSettings *settings() const { return m_settings; } - void updateGeometries(); - public slots: void settingsChanged(ValgrindBaseSettings *settings); - void goNext(); - void goBack(); - -signals: - void resized(); private slots: - void resizeEvent(QResizeEvent *e); void contextMenuEvent(QContextMenuEvent *e); void suppressError(); - void setCurrentRow(int row); private: - int rowCount() const; - int currentRow() const; - QAction *m_copyAction; QAction *m_suppressAction; QString m_defaultSuppFile; diff --git a/src/plugins/valgrind/memchecktool.cpp b/src/plugins/valgrind/memchecktool.cpp index dbc94f5df48..ad56823bfa3 100644 --- a/src/plugins/valgrind/memchecktool.cpp +++ b/src/plugins/valgrind/memchecktool.cpp @@ -392,7 +392,7 @@ QWidget *MemcheckTool::createWidgets() action->setDisabled(true); action->setIcon(QIcon(QLatin1String(Core::Constants::ICON_PREV))); action->setToolTip(tr("Go to previous leak.")); - connect(action, SIGNAL(triggered(bool)), m_errorView, SLOT(goBack())); + connect(action, &QAction::triggered, m_errorView, &MemcheckErrorView::goBack); button = new QToolButton; button->setDefaultAction(action); layout->addWidget(button); @@ -403,7 +403,7 @@ QWidget *MemcheckTool::createWidgets() action->setDisabled(true); action->setIcon(QIcon(QLatin1String(Core::Constants::ICON_NEXT))); action->setToolTip(tr("Go to next leak.")); - connect(action, SIGNAL(triggered(bool)), m_errorView, SLOT(goNext())); + connect(action, &QAction::triggered, m_errorView, &MemcheckErrorView::goNext); button = new QToolButton; button->setDefaultAction(action); layout->addWidget(button);