1 /****************************************************************************
3 ** Copyright (C) Qxt Foundation. Some rights reserved.
5 ** This file is part of the QxtGui module of the Qt eXTension library
7 ** This library is free software; you can redistribute it and/or modify it
8 ** under the terms of th Common Public License, version 1.0, as published by
11 ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY
12 ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
13 ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
14 ** FITNESS FOR A PARTICULAR PURPOSE.
16 ** You should have received a copy of the CPL along with this file.
17 ** See the LICENSE file and the cpl1.0.txt file included with the source
18 ** distribution for more information. If you did not receive a copy of the
19 ** license, contact the Qxt Foundation.
21 ** <http://libqxt.sourceforge.net> <foundation@libqxt.org>
23 ****************************************************************************/
24 #include "qxtitemdelegate.h"
25 #include "qxtitemdelegate_p.h"
26 #include <QApplication>
30 static const int TOP_LEVEL_EXTENT = 2;
32 QxtItemDelegatePrivate::QxtItemDelegatePrivate() :
34 progressFormat("%1%"),
35 elide(Qt::ElideMiddle),
36 style(Qxt::NoDecoration)
39 void QxtItemDelegatePrivate::paintButton(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index, const QTreeView* view) const
42 QStyleOptionButton buttonOption;
43 buttonOption.state = option.state;
45 buttonOption.state |= QStyle::State_Raised;
47 buttonOption.state &= ~QStyle::State_HasFocus;
48 if (view->isExpanded(index))
49 buttonOption.state |= QStyle::State_Sunken;
50 buttonOption.rect = option.rect;
51 buttonOption.palette = option.palette;
52 buttonOption.features = QStyleOptionButton::None;
53 view->style()->drawControl(QStyle::CE_PushButton, &buttonOption, painter, view);
55 // draw the branch indicator
56 static const int i = 9;
57 const QRect& r = option.rect;
58 if (index.model()->hasChildren(index))
60 QStyleOption branchOption;
61 branchOption.initFrom(view);
62 if (branchOption.direction == Qt::LeftToRight)
63 branchOption.rect = QRect(r.left() + i/2, r.top() + (r.height() - i)/2, i, i);
65 branchOption.rect = QRect(r.right() - i/2 - i, r.top() + (r.height() - i)/2, i, i);
66 branchOption.palette = option.palette;
67 branchOption.state = QStyle::State_Children;
68 if (view->isExpanded(index))
69 branchOption.state |= QStyle::State_Open;
70 view->style()->drawPrimitive(QStyle::PE_IndicatorBranch, &branchOption, painter, view);
74 QRect textrect = QRect(r.left() + i*2, r.top(), r.width() - ((5*i)/2), r.height());
75 #if QT_VERSION < 0x040200
76 QString text = QItemDelegate::elidedText(option.fontMetrics, textrect.width(), elide, index.data().toString());
77 #else // QT_VERSION >= 0x040200
78 QString text = option.fontMetrics.elidedText(index.data().toString(), elide, textrect.width());
80 view->style()->drawItemText(painter, textrect, Qt::AlignCenter, option.palette, view->isEnabled(), text);
83 void QxtItemDelegatePrivate::paintMenu(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index, const QTreeView* view) const
85 // draw the menu bar item
86 QStyleOptionMenuItem menuOption;
87 menuOption.palette = view->palette();
88 menuOption.fontMetrics = view->fontMetrics();
89 menuOption.state = QStyle::State_None;
90 // QModelIndex::flags() was introduced in 4.2
91 // => therefore "index.model()->flags(index)"
92 if (view->isEnabled() && index.model()->flags(index) & Qt::ItemIsEnabled)
93 menuOption.state |= QStyle::State_Enabled;
95 menuOption.palette.setCurrentColorGroup(QPalette::Disabled);
96 menuOption.state |= QStyle::State_Selected;
97 menuOption.state |= QStyle::State_Sunken;
98 menuOption.state |= QStyle::State_HasFocus;
99 menuOption.rect = option.rect;
100 menuOption.text = index.data().toString();
101 menuOption.icon = QIcon(index.data(Qt::DecorationRole).value<QPixmap>());
102 view->style()->drawControl(QStyle::CE_MenuBarItem, &menuOption, painter, view);
104 // draw the an arrow as a branch indicator
105 if (index.model()->hasChildren(index))
107 QStyle::PrimitiveElement arrow;
108 if (view->isExpanded(index))
109 arrow = QStyle::PE_IndicatorArrowUp;
111 arrow = QStyle::PE_IndicatorArrowDown;
112 static const int i = 9;
113 const QRect& r = option.rect;
114 menuOption.rect = QRect(r.left() + i/2, r.top() + (r.height() - i)/2, i, i);
115 view->style()->drawPrimitive(arrow, &menuOption, painter, view);
119 void QxtItemDelegatePrivate::paintProgress(QPainter* painter, const QStyleOptionViewItem& option, int progress) const
121 QStyleOptionProgressBar opt;
124 opt.rect = option.rect;
125 opt.progress = progress;
126 opt.textVisible = textVisible;
127 opt.text = progressFormat.arg(progress);
128 QApplication::style()->drawControl(QStyle::CE_ProgressBar, &opt, painter, 0);
131 void QxtItemDelegatePrivate::setCurrentEditor(QWidget* editor, const QModelIndex& index) const
133 currentEditor = editor;
134 currentEdited = index;
137 void QxtItemDelegatePrivate::closeEditor(QWidget* editor)
139 if (currentEdited.isValid() && editor == currentEditor)
141 setCurrentEditor(0, QModelIndex());
142 emit qxt_p().editingFinished(currentEdited);
147 \class QxtItemDelegate QxtItemDelegate
149 \brief An extended QItemDelegate with additional signals and optional decoration.
151 QxtItemDelegate provides signals for starting and finishing of editing
152 and an optional decoration for top level indices in a QTreeView.
153 QxtItemDelegate can also draw a progress bar for indices providing
154 appropriate progress data.
158 \fn QxtItemDelegate::editingStarted(const QModelIndex& index)
160 This signal is emitted after the editing of \a index has been started.
162 \sa editingFinished()
166 \fn QxtItemDelegate::editingFinished(const QModelIndex& index)
168 This signal is emitted after the editing of \a index has been finished.
174 Constructs a new QxtItemDelegate with \a parent.
176 QxtItemDelegate::QxtItemDelegate(QObject* parent) : QItemDelegate(parent)
178 QXT_INIT_PRIVATE(QxtItemDelegate);
179 connect(this, SIGNAL(closeEditor(QWidget*)), &qxt_d(), SLOT(closeEditor(QWidget*)));
183 Destructs the item delegate.
185 QxtItemDelegate::~QxtItemDelegate()
189 \property QxtItemDelegate::decorationStyle
190 \brief This property holds the top level index decoration style
192 Top level indices are decorated according to this property.
193 The default value is \b Qxt::NoDecoration.
195 \note The property has effect only in case the delegate is installed
196 on a QTreeView. The view must be the parent of the delegate.
198 \note Set \b QTreeView::rootIsDecorated to \b false to avoid
199 multiple branch indicators.
201 \sa Qxt::DecorationStyle, QTreeView::rootIsDecorated
203 Qxt::DecorationStyle QxtItemDelegate::decorationStyle() const
205 return qxt_d().style;
208 void QxtItemDelegate::setDecorationStyle(Qxt::DecorationStyle style)
210 qxt_d().style = style;
214 \property QxtItemDelegate::elideMode
215 \brief This property holds the text elide mode
217 The text of a decorated top level index is elided according to this property.
218 The default value is \b Qt::ElideMiddle.
220 \note The property has effect only for decorated top level indices.
222 \sa decorationStyle, Qt::TextElideMode
224 Qt::TextElideMode QxtItemDelegate::elideMode() const
226 return qxt_d().elide;
229 void QxtItemDelegate::setElideMode(Qt::TextElideMode mode)
231 qxt_d().elide = mode;
235 \property QxtItemDelegate::progressTextFormat
236 \brief This property holds the format of optional progress text
238 The progress text is formatted according to this property.
239 The default value is \b "%1%".
241 \note Progress bar is rendered for indices providing valid
242 numerical data for \b ProgressRole.
244 \note \b \%1 is replaced by the progress percent.
246 \sa progressTextVisible, ProgressRole
248 QString QxtItemDelegate::progressTextFormat() const
250 return qxt_d().progressFormat;
253 void QxtItemDelegate::setProgressTextFormat(const QString& format)
255 qxt_d().progressFormat = format;
259 \property QxtItemDelegate::progressTextVisible
260 \brief This property holds whether progress text is visible
262 The default value is \b true.
264 \note Progress bar is rendered for indices providing valid
265 numerical data for \b ProgressRole.
267 \sa progressTextFormat, ProgressRole
269 bool QxtItemDelegate::isProgressTextVisible() const
271 return qxt_d().textVisible;
274 void QxtItemDelegate::setProgressTextVisible(bool visible)
276 qxt_d().textVisible = visible;
279 QWidget* QxtItemDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const
281 QWidget* editor = QItemDelegate::createEditor(parent, option, index);
282 qxt_d().setCurrentEditor(editor, index);
283 emit const_cast<QxtItemDelegate*>(this)->editingStarted(index);
287 void QxtItemDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const
289 QItemDelegate::setModelData(editor, model, index);
290 qxt_d().setCurrentEditor(0, QModelIndex());
291 emit const_cast<QxtItemDelegate*>(this)->editingFinished(index);
294 void QxtItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
296 const QAbstractItemModel* model = index.model();
297 const QTreeView* tree = dynamic_cast<QTreeView*>(parent());
298 const bool topLevel = !index.parent().isValid();
300 if (tree && model && topLevel && qxt_d().style != Qxt::NoDecoration)
302 QStyleOptionViewItem opt;
303 opt.QStyleOption::operator=(option);
304 opt.showDecorationSelected = false;
306 QModelIndex valid = model->index(index.row(), 0);
307 QModelIndex sibling = valid;
308 while (sibling.isValid())
310 opt.rect |= tree->visualRect(sibling);
311 sibling = sibling.sibling(sibling.row(), sibling.column() + 1);
314 switch (qxt_d().style)
316 case Qxt::Buttonlike:
317 qxt_d().paintButton(painter, opt, valid, tree);
320 qxt_d().paintMenu(painter, opt, valid, tree);
323 qWarning("QxtItemDelegate::paint() unknown decoration style");
324 QItemDelegate::paint(painter, opt, valid);
330 QItemDelegate::paint(painter, option, index);
333 const QVariant data = index.data(ProgressRole);
334 const int progress = data.toInt(&ok);
335 if (data.isValid() && ok)
336 qxt_d().paintProgress(painter, option, progress);
340 QSize QxtItemDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const
342 // something slightly bigger for top level indices
343 QSize size = QItemDelegate::sizeHint(option, index);
344 if (!index.parent().isValid())
345 size += QSize(TOP_LEVEL_EXTENT, TOP_LEVEL_EXTENT);