Commit 2d509250 authored by Leandro Melo's avatar Leandro Melo

Create a reusable item delegate wich supports "annotations".

Currently used by the QML outline and C++ type hierarchy.

Reviewed-by: kkoehne
Task-number: QTCREATORBUG-2583
parent ed6585c3
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** 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 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#include "annotateditemdelegate.h"
#include <QtCore/QSize>
#include <QtCore/QModelIndex>
#include <QtGui/QStandardItemModel>
#include <QtGui/QPainter>
#include <QtGui/QStyle>
#include <QtGui/QStyleOptionViewItemV4>
#include <QtGui/QApplication>
using namespace Utils;
AnnotatedItemDelegate::AnnotatedItemDelegate(QObject *parent) : QStyledItemDelegate(parent)
{}
AnnotatedItemDelegate::~AnnotatedItemDelegate()
{}
void AnnotatedItemDelegate::setAnnotationRole(int role)
{
m_annotationRole = role;
}
int AnnotatedItemDelegate::annotationRole() const
{
return m_annotationRole;
}
void AnnotatedItemDelegate::setDelimiter(const QString &delimiter)
{
m_delimiter = delimiter;
}
const QString &AnnotatedItemDelegate::delimiter() const
{
return m_delimiter;
}
void AnnotatedItemDelegate::paint(QPainter *painter,
const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
QStyleOptionViewItemV4 opt = option;
initStyleOption(&opt, index);
QStyle *style = QApplication::style();
style->drawPrimitive(QStyle::PE_PanelItemViewItem, &opt, painter, opt.widget);
style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, opt.widget);
const QString &annotation = index.data(m_annotationRole).toString();
if (!annotation.isEmpty()) {
QPalette disabled(opt.palette);
disabled.setCurrentColorGroup(QPalette::Disabled);
painter->save();
painter->setPen(disabled.color(QPalette::WindowText));
static int extra = opt.fontMetrics.width(m_delimiter) + 10;
const QPixmap &pixmap = opt.icon.pixmap(opt.decorationSize);
const QRect &iconRect = style->itemPixmapRect(opt.rect, opt.decorationAlignment, pixmap);
const QRect &displayRect = style->itemTextRect(opt.fontMetrics, opt.rect,
opt.displayAlignment, true, index.data(Qt::DisplayRole).toString());
QRect annotationRect = style->itemTextRect(opt.fontMetrics, opt.rect,
opt.displayAlignment, true, annotation);
annotationRect.adjust(iconRect.width() + displayRect.width() + extra, 0,
iconRect.width() + displayRect.width() + extra, 0);
QApplication::style()->drawItemText(painter, annotationRect,
Qt::AlignLeft | Qt::AlignBottom, disabled, true, annotation);
painter->restore();
}
}
QSize AnnotatedItemDelegate::sizeHint(const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
QStyleOptionViewItemV4 opt = option;
initStyleOption(&opt, index);
const QString &annotation = index.data(m_annotationRole).toString();
if (!annotation.isEmpty())
opt.text += m_delimiter + annotation;
return QApplication::style()->sizeFromContents(QStyle::CT_ItemViewItem, &opt, QSize(), 0);
}
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** 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 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#ifndef ANNOTATEDITEMDELEGATE_H
#define ANNOTATEDITEMDELEGATE_H
#include "utils_global.h"
#include <QtCore/QString>
#include <QtCore/QSize>
#include <QtGui/QStyledItemDelegate>
namespace Utils {
class QTCREATOR_UTILS_EXPORT AnnotatedItemDelegate : public QStyledItemDelegate
{
public:
AnnotatedItemDelegate(QObject *parent = 0);
virtual ~AnnotatedItemDelegate();
void setAnnotationRole(int role);
int annotationRole() const;
void setDelimiter(const QString &delimiter);
const QString &delimiter() const;
protected:
virtual void paint(QPainter *painter,
const QStyleOptionViewItem &option,
const QModelIndex &index) const;
virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;
private:
int m_annotationRole;
QString m_delimiter;
};
} // Utils
#endif // ANNOTATEDITEMDELEGATE_H
......@@ -50,7 +50,8 @@ SOURCES += $$PWD/environment.cpp \
$$PWD/crumblepath.cpp \
$$PWD/debuggerlanguagechooser.cpp \
$$PWD/historycompleter.cpp \
$$PWD/buildablehelperlibrary.cpp
$$PWD/buildablehelperlibrary.cpp \
$$PWD/annotateditemdelegate.cpp
win32 {
SOURCES += $$PWD/abstractprocess_win.cpp \
......@@ -111,7 +112,8 @@ HEADERS += $$PWD/environment.h \
$$PWD/crumblepath.h \
$$PWD/debuggerlanguagechooser.h \
$$PWD/historycompleter.h \
$$PWD/buildablehelperlibrary.h
$$PWD/buildablehelperlibrary.h \
$$PWD/annotateditemdelegate.h
FORMS += $$PWD/filewizardpage.ui \
$$PWD/projectintropage.ui \
......
......@@ -35,97 +35,19 @@
#include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/coreconstants.h>
#include <utils/navigationtreeview.h>
#include <utils/annotateditemdelegate.h>
#include <QtCore/QLatin1Char>
#include <QtCore/QLatin1String>
#include <QtCore/QModelIndex>
#include <QtCore/QSettings>
#include <QtGui/QVBoxLayout>
#include <QtGui/QStandardItemModel>
#include <QtGui/QFontMetrics>
#include <QtGui/QApplication>
#include <QtGui/QPainter>
#include <QtGui/QLabel>
using namespace CppEditor;
using namespace Internal;
// CppTypeHierarchyItem
CppTypeHierarchyItem::CppTypeHierarchyItem(const CppClass &cppClass) :
QStandardItem(), m_cppClass(cppClass)
{}
CppTypeHierarchyItem::~CppTypeHierarchyItem()
{}
int CppTypeHierarchyItem::type() const
{ return UserType; }
const CppClass &CppTypeHierarchyItem::cppClass() const
{ return m_cppClass; }
// CppTypeHierarchyDelegate
CppTypeHierarchyDelegate::CppTypeHierarchyDelegate(QObject *parent) : QStyledItemDelegate(parent)
{}
CppTypeHierarchyDelegate::~CppTypeHierarchyDelegate()
{}
void CppTypeHierarchyDelegate::paint(QPainter *painter,
const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
if (const QStyleOptionViewItemV3 *v3 =
qstyleoption_cast<const QStyleOptionViewItemV3 *>(&option)) {
QApplication::style()->drawPrimitive(QStyle::PE_PanelItemViewItem, v3, painter, v3->widget);
QStyleOptionViewItemV4 opt = option;
initStyleOption(&opt, index);
const QStandardItemModel *model = static_cast<const QStandardItemModel *>(index.model());
CppTypeHierarchyItem *item =
static_cast<CppTypeHierarchyItem *>(model->itemFromIndex(index));
painter->save();
const QIcon &icon = item->cppClass().icon();
const QSize &iconSize = icon.actualSize(opt.decorationSize);
QRect workingRect(opt.rect);
QRect decorationRect(workingRect.topLeft(), iconSize);
icon.paint(painter, decorationRect, opt.decorationAlignment);
workingRect.setX(workingRect.x() + iconSize.width() + 4);
QRect boundingRect;
const QString &name = item->cppClass().name() + QLatin1Char(' ');
painter->drawText(workingRect, Qt::AlignLeft, name, &boundingRect);
if (item->cppClass().name() != item->cppClass().qualifiedName()) {
QFont font(painter->font());
if (font.pointSize() > 2)
font.setPointSize(font.pointSize() - 2);
else if (font.pointSize() > 1)
font.setPointSize(font.pointSize() - 1);
font.setItalic(true);
painter->setFont(font);
QFontMetrics metrics(font);
workingRect.setX(boundingRect.x() + boundingRect.width());
workingRect.setY(boundingRect.y() + boundingRect.height() - metrics.height());
painter->drawText(workingRect, Qt::AlignLeft, item->cppClass().qualifiedName());
}
painter->restore();
} else {
QStyledItemDelegate::paint(painter, option, index);
}
}
QSize CppTypeHierarchyDelegate::sizeHint(const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
QSize size = QStyledItemDelegate::sizeHint(option, index);
size.rwidth() += 5; // Extend a bit because of the font processing.
return size;
}
using namespace Utils;
// CppTypeHierarchyWidget
CppTypeHierarchyWidget::CppTypeHierarchyWidget(Core::IEditor *editor) :
......@@ -144,7 +66,9 @@ CppTypeHierarchyWidget::CppTypeHierarchyWidget(Core::IEditor *editor) :
m_model = new QStandardItemModel;
m_treeView = new Utils::NavigationTreeView;
m_delegate = new CppTypeHierarchyDelegate;
m_delegate = new AnnotatedItemDelegate;
m_delegate->setDelimiter(QLatin1String(" "));
m_delegate->setAnnotationRole(AnnotationRole);
m_treeView->setModel(m_model);
m_treeView->setEditTriggers(QAbstractItemView::NoEditTriggers);
m_treeView->setItemDelegate(m_delegate);
......@@ -200,13 +124,16 @@ void CppTypeHierarchyWidget::perform()
void CppTypeHierarchyWidget::buildModel(const CppClass &cppClass, QStandardItem *parent)
{
CppTypeHierarchyItem *item = new CppTypeHierarchyItem(cppClass);
QStandardItem *item = new QStandardItem;
parent->appendRow(item);
// The delegate retrieves data from the item directly. This is to help size hint.
const QString &display = cppClass.name() + cppClass.qualifiedName();
m_model->setData(m_model->indexFromItem(item), display, Qt::DisplayRole);
m_model->setData(m_model->indexFromItem(item), cppClass.name(), Qt::DisplayRole);
if (cppClass.name() != cppClass.qualifiedName())
m_model->setData(m_model->indexFromItem(item), cppClass.qualifiedName(), AnnotationRole);
m_model->setData(m_model->indexFromItem(item), cppClass.icon(), Qt::DecorationRole);
QVariant link;
link.setValue(CPPEditor::Link(cppClass.link()));
m_model->setData(m_model->indexFromItem(item), link, LinkRole);
foreach (const CppClass &cppBase, cppClass.bases())
buildModel(cppBase, item);
......@@ -216,10 +143,7 @@ void CppTypeHierarchyWidget::buildModel(const CppClass &cppClass, QStandardItem
void CppTypeHierarchyWidget::onItemClicked(const QModelIndex &index)
{
if (QStandardItem *item = m_model->itemFromIndex(index)) {
CppTypeHierarchyItem *cppItem = static_cast<CppTypeHierarchyItem *>(item);
m_cppEditor->openLink(cppItem->cppClass().link());
}
m_cppEditor->openLink(index.data(LinkRole).value<CPPEditor::Link>());
}
// CppTypeHierarchyStackedWidget
......
......@@ -37,13 +37,11 @@
#include <QtCore/QString>
#include <QtGui/QWidget>
#include <QtGui/QStackedWidget>
#include <QtGui/QStandardItem>
#include <QtGui/QStyledItemDelegate>
QT_BEGIN_NAMESPACE
class QStandardItemModel;
class QStandardItem;
class QModelIndex;
class QPainter;
QT_END_NAMESPACE
namespace Core {
......@@ -52,6 +50,7 @@ class IEditor;
namespace Utils {
class NavigationTreeView;
class AnnotatedItemDelegate;
}
namespace CppEditor {
......@@ -59,32 +58,6 @@ namespace Internal {
class CPPEditor;
class CppTypeHierarchyItem : public QStandardItem
{
public:
CppTypeHierarchyItem(const CppClass &cppClass);
virtual ~CppTypeHierarchyItem();
virtual int type() const;
const CppClass &cppClass() const;
private:
CppClass m_cppClass;
};
class CppTypeHierarchyDelegate : public QStyledItemDelegate
{
public:
CppTypeHierarchyDelegate(QObject *parent = 0);
virtual ~CppTypeHierarchyDelegate();
virtual void paint(QPainter *painter,
const QStyleOptionViewItem &option,
const QModelIndex &index) const;
virtual QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;
};
class CppTypeHierarchyWidget : public QWidget
{
Q_OBJECT
......@@ -101,12 +74,17 @@ private slots:
void onItemClicked(const QModelIndex &index);
private:
enum ItemRole {
AnnotationRole = Qt::UserRole + 1,
LinkRole
};
void buildModel(const CppClass &cppClass, QStandardItem *item);
CPPEditor *m_cppEditor;
Utils::NavigationTreeView *m_treeView;
QStandardItemModel *m_model;
CppTypeHierarchyDelegate *m_delegate;
Utils::AnnotatedItemDelegate *m_delegate;
};
// @todo: Pretty much the same design as the OutlineWidgetStack. Maybe we can generalize the
......
#include "qmljsoutlinetreeview.h"
#include "qmloutlinemodel.h"
#include <QtCore/QDebug>
#include <QtGui/QApplication>
#include <QtGui/QPainter>
#include <utils/annotateditemdelegate.h>
namespace QmlJSEditor {
namespace Internal {
QmlJSOutlineItemDelegate::QmlJSOutlineItemDelegate(QObject *parent) :
QStyledItemDelegate(parent)
{
}
QSize QmlJSOutlineItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
QStyleOptionViewItemV4 opt = option;
initStyleOption(&opt, index);
const QString annotation = index.data(QmlOutlineModel::AnnotationRole).toString();
if (!annotation.isEmpty())
opt.text += " " + annotation;
QStyle *style = QApplication::style();
return style->sizeFromContents(QStyle::CT_ItemViewItem, &opt, QSize(), 0);
}
void QmlJSOutlineItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
QStyleOptionViewItemV4 opt = option;
initStyleOption(&opt, index);
if (opt.state & QStyle::State_Selected)
painter->fillRect(opt.rect, option.palette.highlight());
const QString typeString = index.data(Qt::DisplayRole).toString();
const QString annotationString = index.data(QmlOutlineModel::AnnotationRole).toString();
QStyle *style = QApplication::style();
style->drawControl(QStyle::CE_ItemViewItem, &opt, painter, 0);
if (!annotationString.isEmpty()) {
QPalette::ColorRole textColorRole = QPalette::Text;
if (option.state & QStyle::State_Selected) {
textColorRole = QPalette::HighlightedText;
}
// calculate sizes of icon, type.
QPixmap iconPixmap = opt.icon.pixmap(opt.rect.size());
QRect iconRect = style->itemPixmapRect(opt.rect, Qt::AlignLeft, iconPixmap);
QRect typeRect = style->itemTextRect(opt.fontMetrics, opt.rect, Qt::AlignLeft, true, typeString);
QRect annotationRect = style->itemTextRect(opt.fontMetrics, opt.rect, Qt::AlignLeft | Qt::AlignBottom, true,
annotationString);
static int space = opt.fontMetrics.width(" ");
annotationRect.adjust(iconRect.width() + typeRect.width() + space, 0,
iconRect.width() + typeRect.width() + space, 0);
QPalette disabledPalette(opt.palette);
disabledPalette.setCurrentColorGroup(QPalette::Disabled);
style->drawItemText(painter, annotationRect, Qt::AlignLeft, disabledPalette, true,
annotationString, textColorRole);
}
}
QmlJSOutlineTreeView::QmlJSOutlineTreeView(QWidget *parent) :
Utils::NavigationTreeView(parent)
{
......@@ -80,7 +20,9 @@ QmlJSOutlineTreeView::QmlJSOutlineTreeView(QWidget *parent) :
setRootIsDecorated(false);
QmlJSOutlineItemDelegate *itemDelegate = new QmlJSOutlineItemDelegate(this);
Utils::AnnotatedItemDelegate *itemDelegate = new Utils::AnnotatedItemDelegate(this);
itemDelegate->setDelimiter(QLatin1String(" "));
itemDelegate->setAnnotationRole(QmlOutlineModel::AnnotationRole);
setItemDelegateForColumn(0, itemDelegate);
}
......
......@@ -2,21 +2,10 @@
#define QMLJSOUTLINETREEVIEW_H
#include <utils/navigationtreeview.h>
#include <QtGui/QStyledItemDelegate>
namespace QmlJSEditor {
namespace Internal {
class QmlJSOutlineItemDelegate : public QStyledItemDelegate
{
public:
explicit QmlJSOutlineItemDelegate(QObject *parent = 0);
QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;
void paint(QPainter *painter, const QStyleOptionViewItem &option,
const QModelIndex &index) const;
};
class QmlJSOutlineTreeView : public Utils::NavigationTreeView
{
Q_OBJECT
......
......@@ -648,4 +648,6 @@ private:
} // namespace TextEditor
Q_DECLARE_METATYPE(TextEditor::BaseTextEditor::Link);
#endif // BASETEXTEDITOR_H
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment