00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "qitemdelegate.h"
00025
00026 #ifndef QT_NO_ITEMVIEWS
00027 #include <qabstractitemmodel.h>
00028 #include <qapplication.h>
00029 #include <qbrush.h>
00030 #include <qlineedit.h>
00031 #include <qpainter.h>
00032 #include <qpalette.h>
00033 #include <qpoint.h>
00034 #include <qrect.h>
00035 #include <qsize.h>
00036 #include <qstyle.h>
00037 #include <qstyleoption.h>
00038 #include <qevent.h>
00039 #include <qpixmap.h>
00040 #include <qbitmap.h>
00041 #include <qpixmapcache.h>
00042 #include <qitemeditorfactory.h>
00043 #include <qmetaobject.h>
00044 #include <qtextlayout.h>
00045 #include <private/qobject_p.h>
00046 #include <private/qdnd_p.h>
00047 #include <qdebug.h>
00048 #include <qlocale.h>
00049
00050 #include <limits.h>
00051
00052 class QItemDelegatePrivate : public QObjectPrivate
00053 {
00054 Q_DECLARE_PUBLIC(QItemDelegate)
00055
00056 public:
00057 QItemDelegatePrivate() : f(0), clipPainting(false) {}
00058
00059 inline const QItemEditorFactory *editorFactory() const
00060 { return f ? f : QItemEditorFactory::defaultFactory(); }
00061
00062 inline QIcon::Mode iconMode(QStyle::State state) const
00063 {
00064 if (!(state & QStyle::State_Enabled)) return QIcon::Disabled;
00065 if (state & QStyle::State_Selected) return QIcon::Selected;
00066 return QIcon::Normal;
00067 }
00068
00069 inline QIcon::State iconState(QStyle::State state) const
00070 { return state & QStyle::State_Open ? QIcon::On : QIcon::Off; }
00071
00072 inline static QString replaceNewLine(QString text)
00073 {
00074 const QChar nl = QLatin1Char('\n');
00075 for (int i = 0; i < text.count(); ++i)
00076 if (text.at(i) == nl)
00077 text[i] = QChar::LineSeparator;
00078 return text;
00079 }
00080
00081 void _q_commitDataAndCloseEditor(QWidget *editor);
00082
00083 QItemEditorFactory *f;
00084 bool clipPainting;
00085
00086 QRect textLayoutBounds(const QStyleOptionViewItemV2 &options) const;
00087 QSizeF doTextLayout(int lineWidth) const;
00088 mutable QTextLayout textLayout;
00089 mutable QTextOption textOption;
00090 };
00091
00092 void QItemDelegatePrivate::_q_commitDataAndCloseEditor(QWidget *editor)
00093 {
00094 Q_Q(QItemDelegate);
00095 emit q->commitData(editor);
00096 emit q->closeEditor(editor, QAbstractItemDelegate::SubmitModelCache);
00097 }
00098
00099 QRect QItemDelegatePrivate::textLayoutBounds(const QStyleOptionViewItemV2 &option) const
00100 {
00101 QRect rect = option.rect;
00102 const bool wrapText = option.features & QStyleOptionViewItemV2::WrapText;
00103 switch (option.decorationPosition) {
00104 case QStyleOptionViewItem::Left:
00105 case QStyleOptionViewItem::Right:
00106 rect.setWidth(INT_MAX >> 6);
00107 break;
00108 case QStyleOptionViewItem::Top:
00109 case QStyleOptionViewItem::Bottom:
00110 rect.setWidth(wrapText ? option.decorationSize.width() : (INT_MAX >> 6));
00111 break;
00112 }
00113
00114 return rect;
00115 }
00116
00117 QSizeF QItemDelegatePrivate::doTextLayout(int lineWidth) const
00118 {
00119 QFontMetrics fontMetrics(textLayout.font());
00120 int leading = fontMetrics.leading();
00121 qreal height = 0;
00122 qreal widthUsed = 0;
00123 textLayout.beginLayout();
00124 while (true) {
00125 QTextLine line = textLayout.createLine();
00126 if (!line.isValid())
00127 break;
00128 line.setLineWidth(lineWidth);
00129 height += leading;
00130 line.setPosition(QPointF(0, height));
00131 height += line.height();
00132 widthUsed = qMax(widthUsed, line.naturalTextWidth());
00133 }
00134 textLayout.endLayout();
00135 return QSizeF(widthUsed, height);
00136 }
00137
00245 QItemDelegate::QItemDelegate(QObject *parent)
00246 : QAbstractItemDelegate(*new QItemDelegatePrivate(), parent)
00247 {
00248
00249 }
00250
00255 QItemDelegate::~QItemDelegate()
00256 {
00257 }
00258
00269 bool QItemDelegate::hasClipping() const
00270 {
00271 Q_D(const QItemDelegate);
00272 return d->clipPainting;
00273 }
00274
00275 void QItemDelegate::setClipping(bool clip)
00276 {
00277 Q_D(QItemDelegate);
00278 d->clipPainting = clip;
00279 }
00280
00306 void QItemDelegate::paint(QPainter *painter,
00307 const QStyleOptionViewItem &option,
00308 const QModelIndex &index) const
00309 {
00310 Q_D(const QItemDelegate);
00311 Q_ASSERT(index.isValid());
00312 QStyleOptionViewItemV2 opt = setOptions(index, option);
00313 const QStyleOptionViewItemV2 *v2 = qstyleoption_cast<const QStyleOptionViewItemV2 *>(&option);
00314 opt.features = v2 ? v2->features : QStyleOptionViewItemV2::ViewItemFeatures(QStyleOptionViewItemV2::None);
00315
00316
00317 painter->save();
00318 if (d->clipPainting)
00319 painter->setClipRect(opt.rect);
00320
00321
00322
00323 QVariant value;
00324
00325 QIcon icon;
00326 QIcon::Mode iconMode = d->iconMode(option.state);
00327 QIcon::State iconState = d->iconState(option.state);
00328
00329 QPixmap pixmap;
00330 QRect decorationRect;
00331 value = index.data(Qt::DecorationRole);
00332 if (value.isValid()) {
00333 if (value.type() == QVariant::Icon) {
00334 icon = qvariant_cast<QIcon>(value);
00335 decorationRect = QRect(QPoint(0, 0),
00336 icon.actualSize(option.decorationSize, iconMode, iconState));
00337 } else {
00338 pixmap = decoration(opt, value);
00339 decorationRect = QRect(QPoint(0, 0), pixmap.size());
00340 }
00341 }
00342
00343 QString text;
00344 QRect displayRect;
00345 value = index.data(Qt::DisplayRole);
00346 if (value.isValid()) {
00347 if (value.type() == QVariant::Double)
00348 text = QLocale().toString(value.toDouble());
00349 else
00350 text = QItemDelegatePrivate::replaceNewLine(value.toString());
00351
00352 displayRect = textRectangle(painter, d->textLayoutBounds(opt), opt.font, text);
00353 }
00354
00355 QRect checkRect;
00356 Qt::CheckState checkState = Qt::Unchecked;
00357 value = index.data(Qt::CheckStateRole);
00358 if (value.isValid()) {
00359 checkState = static_cast<Qt::CheckState>(value.toInt());
00360 checkRect = check(opt, opt.rect, value);
00361 }
00362
00363
00364
00365 doLayout(opt, &checkRect, &decorationRect, &displayRect, false);
00366
00367
00368
00369 drawBackground(painter, opt, index);
00370 drawCheck(painter, opt, checkRect, checkState);
00371 if (!icon.isNull())
00372 icon.paint(painter, decorationRect, option.decorationAlignment, iconMode, iconState);
00373 else
00374 drawDecoration(painter, opt, decorationRect, pixmap);
00375 drawDisplay(painter, opt, displayRect, text);
00376 drawFocus(painter, opt, text.isEmpty() ? QRect() : displayRect);
00377
00378
00379 painter->restore();
00380 }
00381
00392 QSize QItemDelegate::sizeHint(const QStyleOptionViewItem &option,
00393 const QModelIndex &index) const
00394 {
00395 QVariant value = index.data(Qt::SizeHintRole);
00396 if (value.isValid())
00397 return qvariant_cast<QSize>(value);
00398 QRect decorationRect = rect(option, index, Qt::DecorationRole);
00399 QRect displayRect = rect(option, index, Qt::DisplayRole);
00400 QRect checkRect = rect(option, index, Qt::CheckStateRole);
00401
00402 doLayout(option, &checkRect, &decorationRect, &displayRect, true);
00403
00404 return (decorationRect|displayRect|checkRect).size();
00405 }
00406
00415 QWidget *QItemDelegate::createEditor(QWidget *parent,
00416 const QStyleOptionViewItem &,
00417 const QModelIndex &index) const
00418 {
00419 Q_D(const QItemDelegate);
00420 if (!index.isValid())
00421 return 0;
00422 QVariant::Type t = static_cast<QVariant::Type>(index.data(Qt::EditRole).userType());
00423 const QItemEditorFactory *factory = d->f;
00424 if (factory == 0)
00425 factory = QItemEditorFactory::defaultFactory();
00426 return factory->createEditor(t, parent);
00427 }
00428
00438 void QItemDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
00439 {
00440 #ifdef QT_NO_PROPERTIES
00441 Q_UNUSED(editor);
00442 Q_UNUSED(index);
00443 #else
00444 Q_D(const QItemDelegate);
00445 QVariant v = index.data(Qt::EditRole);
00446 QByteArray n = editor->metaObject()->userProperty().name();
00447
00448
00449
00450
00451
00452 if (n == "dateTime") {
00453 if (editor->inherits("QTimeEdit"))
00454 n = "time";
00455 else if (editor->inherits("QDateEdit"))
00456 n = "date";
00457 }
00458
00459 if (n.isEmpty())
00460 n = d->editorFactory()->valuePropertyName(static_cast<QVariant::Type>(v.userType()));
00461 if (!n.isEmpty())
00462 editor->setProperty(n, v);
00463 #endif
00464 }
00465
00475 void QItemDelegate::setModelData(QWidget *editor,
00476 QAbstractItemModel *model,
00477 const QModelIndex &index) const
00478 {
00479 #ifdef QT_NO_PROPERTIES
00480 Q_UNUSED(model);
00481 Q_UNUSED(editor);
00482 Q_UNUSED(index);
00483 #else
00484 Q_D(const QItemDelegate);
00485 Q_ASSERT(model);
00486 Q_ASSERT(editor);
00487 QByteArray n = editor->metaObject()->userProperty().name();
00488 if (n.isEmpty())
00489 n = d->editorFactory()->valuePropertyName(
00490 static_cast<QVariant::Type>(model->data(index, Qt::EditRole).userType()));
00491 if (!n.isEmpty())
00492 model->setData(index, editor->property(n), Qt::EditRole);
00493 #endif
00494 }
00495
00501 void QItemDelegate::updateEditorGeometry(QWidget *editor,
00502 const QStyleOptionViewItem &option,
00503 const QModelIndex &index) const
00504 {
00505 if (!editor)
00506 return;
00507 Q_ASSERT(index.isValid());
00508 QPixmap pixmap = decoration(option, index.data(Qt::DecorationRole));
00509 QString text = QItemDelegatePrivate::replaceNewLine(index.data(Qt::DisplayRole).toString());
00510 QRect pixmapRect = QRect(QPoint(0, 0), option.decorationSize).intersected(pixmap.rect());
00511 QRect textRect = textRectangle(0, option.rect, option.font, text);
00512 QRect checkRect = check(option, textRect, index.data(Qt::CheckStateRole));
00513 QStyleOptionViewItem opt = option;
00514 opt.showDecorationSelected = true;
00515 doLayout(opt, &checkRect, &pixmapRect, &textRect, false);
00516 editor->setGeometry(textRect);
00517 }
00518
00525 QItemEditorFactory *QItemDelegate::itemEditorFactory() const
00526 {
00527 Q_D(const QItemDelegate);
00528 return d->f;
00529 }
00530
00538 void QItemDelegate::setItemEditorFactory(QItemEditorFactory *factory)
00539 {
00540 Q_D(QItemDelegate);
00541 d->f = factory;
00542 }
00543
00549 void QItemDelegate::drawDisplay(QPainter *painter, const QStyleOptionViewItem &option,
00550 const QRect &rect, const QString &text) const
00551 {
00552 Q_D(const QItemDelegate);
00553
00554 if (text.isEmpty())
00555 return;
00556
00557 QPen pen = painter->pen();
00558 QPalette::ColorGroup cg = option.state & QStyle::State_Enabled
00559 ? QPalette::Normal : QPalette::Disabled;
00560 if (cg == QPalette::Normal && !(option.state & QStyle::State_Active))
00561 cg = QPalette::Inactive;
00562 if (option.state & QStyle::State_Selected) {
00563 painter->fillRect(rect, option.palette.brush(cg, QPalette::Highlight));
00564 painter->setPen(option.palette.color(cg, QPalette::HighlightedText));
00565 } else {
00566 painter->setPen(option.palette.color(cg, QPalette::Text));
00567 }
00568
00569 if (option.state & QStyle::State_Editing) {
00570 painter->save();
00571 painter->setPen(option.palette.color(cg, QPalette::Text));
00572 painter->drawRect(rect.adjusted(0, 0, -1, -1));
00573 painter->restore();
00574 }
00575
00576 const QStyleOptionViewItemV2 opt = option;
00577 const int textMargin = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1;
00578 QRect textRect = rect.adjusted(textMargin, 0, -textMargin, 0);
00579 const bool wrapText = opt.features & QStyleOptionViewItemV2::WrapText;
00580 d->textOption.setWrapMode(wrapText ? QTextOption::WordWrap : QTextOption::ManualWrap);
00581 d->textOption.setTextDirection(option.direction);
00582 d->textOption.setAlignment(QStyle::visualAlignment(option.direction, option.displayAlignment));
00583 d->textLayout.setTextOption(d->textOption);
00584 d->textLayout.setFont(option.font);
00585 d->textLayout.setText(QItemDelegatePrivate::replaceNewLine(text));
00586
00587 QSizeF textLayoutSize = d->doTextLayout(textRect.width());
00588
00589 if (textRect.width() < textLayoutSize.width()
00590 || textRect.height() < textLayoutSize.height()) {
00591 QString elided;
00592 int start = 0;
00593 int end = text.indexOf(QChar::LineSeparator, start);
00594 if (end == -1) {
00595 elided += option.fontMetrics.elidedText(text, option.textElideMode, textRect.width());
00596 } else while (end != -1) {
00597 elided += option.fontMetrics.elidedText(text.mid(start, end - start),
00598 option.textElideMode, textRect.width());
00599 start = end + 1;
00600 end = text.indexOf(QChar::LineSeparator, start);
00601 }
00602 d->textLayout.setText(elided);
00603 textLayoutSize = d->doTextLayout(textRect.width());
00604 }
00605
00606 const QSize layoutSize(textRect.width(), int(textLayoutSize.height()));
00607 const QRect layoutRect = QStyle::alignedRect(option.direction, option.displayAlignment,
00608 layoutSize, textRect);
00609 d->textLayout.draw(painter, layoutRect.topLeft(), QVector<QTextLayout::FormatRange>(), layoutRect);
00610 }
00611
00616 void QItemDelegate::drawDecoration(QPainter *painter, const QStyleOptionViewItem &option,
00617 const QRect &rect, const QPixmap &pixmap) const
00618 {
00619 if (pixmap.isNull() || !rect.isValid())
00620 return;
00621 QPoint p = QStyle::alignedRect(option.direction, option.decorationAlignment,
00622 pixmap.size(), rect).topLeft();
00623 if (option.state & QStyle::State_Selected) {
00624 QPixmap *pm = selected(pixmap, option.palette, option.state & QStyle::State_Enabled);
00625 painter->drawPixmap(p, *pm);
00626 } else {
00627 painter->drawPixmap(p, pixmap);
00628 }
00629 }
00630
00636 void QItemDelegate::drawFocus(QPainter *painter,
00637 const QStyleOptionViewItem &option,
00638 const QRect &rect) const
00639 {
00640 if ((option.state & QStyle::State_HasFocus) == 0 || !rect.isValid())
00641 return;
00642 QStyleOptionFocusRect o;
00643 o.QStyleOption::operator=(option);
00644 o.rect = rect;
00645 o.state |= QStyle::State_KeyboardFocusChange;
00646 QPalette::ColorGroup cg = (option.state & QStyle::State_Enabled)
00647 ? QPalette::Normal : QPalette::Disabled;
00648 o.backgroundColor = option.palette.color(cg, (option.state & QStyle::State_Selected)
00649 ? QPalette::Highlight : QPalette::Window);
00650 QApplication::style()->drawPrimitive(QStyle::PE_FrameFocusRect, &o, painter);
00651 }
00652
00659 void QItemDelegate::drawCheck(QPainter *painter,
00660 const QStyleOptionViewItem &option,
00661 const QRect &rect, Qt::CheckState state) const
00662 {
00663 if (!rect.isValid())
00664 return;
00665
00666 QStyleOptionViewItem opt(option);
00667 opt.rect = rect;
00668 opt.state = opt.state & ~QStyle::State_HasFocus;
00669
00670 switch (state) {
00671 case Qt::Unchecked:
00672 opt.state |= QStyle::State_Off;
00673 break;
00674 case Qt::PartiallyChecked:
00675 opt.state |= QStyle::State_NoChange;
00676 break;
00677 case Qt::Checked:
00678 opt.state |= QStyle::State_On;
00679 break;
00680 }
00681
00682 QApplication::style()->drawPrimitive(QStyle::PE_IndicatorViewItemCheck, &opt, painter);
00683 }
00684
00692 void QItemDelegate::drawBackground(QPainter *painter,
00693 const QStyleOptionViewItem &option,
00694 const QModelIndex &index) const
00695 {
00696 if (option.showDecorationSelected && (option.state & QStyle::State_Selected)) {
00697 QPalette::ColorGroup cg = option.state & QStyle::State_Enabled
00698 ? QPalette::Normal : QPalette::Disabled;
00699 if (cg == QPalette::Normal && !(option.state & QStyle::State_Active))
00700 cg = QPalette::Inactive;
00701
00702 painter->fillRect(option.rect, option.palette.brush(cg, QPalette::Highlight));
00703 } else {
00704 QVariant value = index.data(Qt::BackgroundRole);
00705 if (qVariantCanConvert<QBrush>(value)) {
00706 QPointF oldBO = painter->brushOrigin();
00707 painter->setBrushOrigin(option.rect.topLeft());
00708 painter->fillRect(option.rect, qvariant_cast<QBrush>(value));
00709 painter->setBrushOrigin(oldBO);
00710 }
00711 }
00712 }
00713
00714
00719 void QItemDelegate::doLayout(const QStyleOptionViewItem &option,
00720 QRect *checkRect, QRect *pixmapRect, QRect *textRect,
00721 bool hint) const
00722 {
00723 Q_ASSERT(checkRect && pixmapRect && textRect);
00724 const int textMargin = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1;
00725 int x = option.rect.left();
00726 int y = option.rect.top();
00727 int w, h;
00728
00729 textRect->adjust(-textMargin, 0, textMargin, 0);
00730 if (textRect->height() == 0)
00731 textRect->setHeight(option.fontMetrics.lineSpacing());
00732
00733 QSize pm(0, 0);
00734 if (pixmapRect->isValid()) {
00735 pm = pixmapRect->size();
00736 pm.rwidth() += 2 * textMargin;
00737 }
00738 if (hint) {
00739 h = qMax(checkRect->height(), qMax(textRect->height(), pm.height()));
00740 if (option.decorationPosition == QStyleOptionViewItem::Left
00741 || option.decorationPosition == QStyleOptionViewItem::Right) {
00742 w = textRect->width() + pm.width();
00743 } else {
00744 w = qMax(textRect->width(), pm.width());
00745 }
00746 } else {
00747 w = option.rect.width();
00748 h = option.rect.height();
00749 }
00750
00751 int cw = 0;
00752 QRect check;
00753 if (checkRect->isValid()) {
00754 cw = checkRect->width() + 2 * textMargin;
00755 if (hint) w += cw;
00756 if (option.direction == Qt::RightToLeft) {
00757 check.setRect(x + w - cw, y, cw, h);
00758 } else {
00759 check.setRect(x, y, cw, h);
00760 }
00761 }
00762
00763
00764
00765 QRect display;
00766 QRect decoration;
00767 switch (option.decorationPosition) {
00768 case QStyleOptionViewItem::Top: {
00769 if (!pm.isEmpty())
00770 pm.setHeight(pm.height() + textMargin);
00771 h = hint ? textRect->height() : h - pm.height();
00772
00773 if (option.direction == Qt::RightToLeft) {
00774 decoration.setRect(x, y, w - cw, pm.height());
00775 display.setRect(x, y + pm.height(), w - cw, h);
00776 } else {
00777 decoration.setRect(x + cw, y, w - cw, pm.height());
00778 display.setRect(x + cw, y + pm.height(), w - cw, h);
00779 }
00780 break; }
00781 case QStyleOptionViewItem::Bottom: {
00782 if (!textRect->isEmpty())
00783 textRect->setHeight(textRect->height() + textMargin);
00784 h = hint ? textRect->height() + pm.height() : h;
00785
00786 if (option.direction == Qt::RightToLeft) {
00787 display.setRect(x, y, w - cw, textRect->height());
00788 decoration.setRect(x, y + textRect->height(), w - cw, h - textRect->height());
00789 } else {
00790 display.setRect(x + cw, y, w - cw, textRect->height());
00791 decoration.setRect(x + cw, y + textRect->height(), w - cw, h - textRect->height());
00792 }
00793 break; }
00794 case QStyleOptionViewItem::Left: {
00795 if (option.direction == Qt::LeftToRight) {
00796 decoration.setRect(x + cw, y, pm.width(), h);
00797 display.setRect(decoration.right() + 1, y, w - pm.width() - cw, h);
00798 } else {
00799 display.setRect(x, y, w - pm.width() - cw, h);
00800 decoration.setRect(display.right() + 1, y, pm.width(), h);
00801 }
00802 break; }
00803 case QStyleOptionViewItem::Right: {
00804 if (option.direction == Qt::LeftToRight) {
00805 display.setRect(x + cw, y, w - pm.width() - cw, h);
00806 decoration.setRect(display.right() + 1, y, pm.width(), h);
00807 } else {
00808 decoration.setRect(x, y, pm.width(), h);
00809 display.setRect(decoration.right() + 1, y, w - pm.width() - cw, h);
00810 }
00811 break; }
00812 default:
00813 qWarning("doLayout: decoration position is invalid");
00814 decoration = *pixmapRect;
00815 break;
00816 }
00817
00818 if (!hint) {
00819 *checkRect = QStyle::alignedRect(option.direction, Qt::AlignCenter,
00820 checkRect->size(), check);
00821 *pixmapRect = QStyle::alignedRect(option.direction, option.decorationAlignment,
00822 pixmapRect->size(), decoration);
00823
00824 if (option.showDecorationSelected)
00825 *textRect = display;
00826 else
00827 *textRect = QStyle::alignedRect(option.direction, option.displayAlignment,
00828 textRect->size().boundedTo(display.size()), display);
00829 } else {
00830 *checkRect = check;
00831 *pixmapRect = decoration;
00832 *textRect = display;
00833 }
00834 }
00835
00844 QPixmap QItemDelegate::decoration(const QStyleOptionViewItem &option, const QVariant &variant) const
00845 {
00846 Q_D(const QItemDelegate);
00847 switch (variant.type()) {
00848 case QVariant::Icon: {
00849 QIcon::Mode mode = d->iconMode(option.state);
00850 QIcon::State state = d->iconState(option.state);
00851 return qvariant_cast<QIcon>(variant).pixmap(option.decorationSize, mode, state); }
00852 case QVariant::Color: {
00853 static QPixmap pixmap(option.decorationSize);
00854 pixmap.fill(qvariant_cast<QColor>(variant));
00855 return pixmap; }
00856 default:
00857 break;
00858 }
00859
00860 return qvariant_cast<QPixmap>(variant);
00861 }
00862
00863
00864 static QString qPixmapSerial(quint64 i, bool enabled)
00865 {
00866 ushort arr[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '-', '0' + enabled };
00867 ushort *ptr = &arr[16];
00868
00869 while (i > 0) {
00870
00871
00872 *(--ptr) = '0' + i % 16;
00873 i >>= 4;
00874 }
00875
00876 return QString::fromUtf16(ptr, int(&arr[sizeof(arr) / sizeof(ushort)] - ptr));
00877 }
00878
00885 QPixmap *QItemDelegate::selected(const QPixmap &pixmap, const QPalette &palette, bool enabled) const
00886 {
00887 QString key = qPixmapSerial(qt_pixmap_id(pixmap), enabled);
00888 QPixmap *pm = QPixmapCache::find(key);
00889 if (!pm) {
00890 QImage img = pixmap.toImage().convertToFormat(QImage::Format_ARGB32_Premultiplied);
00891
00892 QColor color = palette.color(enabled ? QPalette::Normal : QPalette::Disabled,
00893 QPalette::Highlight);
00894 color.setAlphaF(0.3);
00895
00896 QPainter painter(&img);
00897 painter.setCompositionMode(QPainter::CompositionMode_SourceAtop);
00898 painter.fillRect(0, 0, img.width(), img.height(), color);
00899 painter.end();
00900
00901 QPixmap selected = QPixmap(QPixmap::fromImage(img));
00902 QPixmapCache::insert(key, selected);
00903 pm = QPixmapCache::find(key);
00904 }
00905 return pm;
00906 }
00907
00912 QRect QItemDelegate::rect(const QStyleOptionViewItem &option,
00913 const QModelIndex &index, int role) const
00914 {
00915 Q_D(const QItemDelegate);
00916 QVariant value = index.data(role);
00917 if (role == Qt::CheckStateRole)
00918 return check(option, option.rect, value);
00919 if (value.isValid()) {
00920 switch (value.type()) {
00921 case QVariant::Invalid:
00922 break;
00923 case QVariant::Pixmap:
00924 return QRect(QPoint(0, 0), qvariant_cast<QPixmap>(value).size());
00925 case QVariant::Image:
00926 return QRect(QPoint(0, 0), qvariant_cast<QImage>(value).size());
00927 case QVariant::Icon: {
00928 QIcon::Mode mode = d->iconMode(option.state);
00929 QIcon::State state = d->iconState(option.state);
00930 QIcon icon = qvariant_cast<QIcon>(value);
00931 QSize size = icon.actualSize(option.decorationSize, mode, state);
00932 return QRect(QPoint(0, 0), size); }
00933 case QVariant::Color:
00934 return QRect(QPoint(0, 0), option.decorationSize);
00935 case QVariant::String:
00936 default: {
00937 QString text = QItemDelegatePrivate::replaceNewLine(value.toString());
00938 value = index.data(Qt::FontRole);
00939 QFont fnt = qvariant_cast<QFont>(value).resolve(option.font);
00940 return textRectangle(0, d->textLayoutBounds(option), fnt, text); }
00941 }
00942 }
00943 return QRect();
00944 }
00945
00949 QRect QItemDelegate::check(const QStyleOptionViewItem &option,
00950 const QRect &bounding, const QVariant &value) const
00951 {
00952 if (value.isValid()) {
00953 QStyleOptionButton opt;
00954 opt.QStyleOption::operator=(option);
00955 opt.rect = bounding;
00956 return QApplication::style()->subElementRect(QStyle::SE_ViewItemCheckIndicator, &opt);
00957 }
00958 return QRect();
00959 }
00960
00964 QRect QItemDelegate::textRectangle(QPainter * , const QRect &rect,
00965 const QFont &font, const QString &text) const
00966 {
00967 Q_D(const QItemDelegate);
00968 d->textOption.setWrapMode(QTextOption::WordWrap);
00969 d->textLayout.setTextOption(d->textOption);
00970 d->textLayout.setFont(font);
00971 d->textLayout.setText(QItemDelegatePrivate::replaceNewLine(text));
00972 const QSize size = d->doTextLayout(rect.width()).toSize();
00973 const int textMargin = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1;
00974 return QRect(0, 0, size.width() + 2 * textMargin, size.height());
00975 }
00976
01005 bool QItemDelegate::eventFilter(QObject *object, QEvent *event)
01006 {
01007 QWidget *editor = ::qobject_cast<QWidget*>(object);
01008 if (!editor)
01009 return false;
01010 if (event->type() == QEvent::KeyPress) {
01011 switch (static_cast<QKeyEvent *>(event)->key()) {
01012 case Qt::Key_Tab:
01013 emit commitData(editor);
01014 emit closeEditor(editor, QAbstractItemDelegate::EditNextItem);
01015 return true;
01016 case Qt::Key_Backtab:
01017 emit commitData(editor);
01018 emit closeEditor(editor, QAbstractItemDelegate::EditPreviousItem);
01019 return true;
01020 case Qt::Key_Enter:
01021 case Qt::Key_Return:
01022
01023
01024
01025 QMetaObject::invokeMethod(this, "_q_commitDataAndCloseEditor",
01026 Qt::QueuedConnection, Q_ARG(QWidget*, editor));
01027 return false;
01028 case Qt::Key_Escape:
01029
01030 emit closeEditor(editor, QAbstractItemDelegate::RevertModelCache);
01031 break;
01032 default:
01033 return false;
01034 }
01035 if (editor->parentWidget())
01036 editor->parentWidget()->setFocus();
01037 return true;
01038 } else if (event->type() == QEvent::FocusOut) {
01039 if (!editor->isActiveWindow() || (QApplication::focusWidget() != editor)) {
01040 QWidget *w = QApplication::focusWidget();
01041 while (w) {
01042 if (w == editor)
01043 return false;
01044 w = w->parentWidget();
01045 }
01046 #ifndef QT_NO_DRAGANDDROP
01047
01048
01049 if (QDragManager::self() && QDragManager::self()->object != 0)
01050 return false;
01051 #endif
01052
01053
01054 if (QApplication::activeModalWidget() && !QApplication::activeModalWidget()->isAncestorOf(editor))
01055 return false;
01056 emit commitData(editor);
01057 emit closeEditor(editor, NoHint);
01058 }
01059 }
01060 return false;
01061 }
01062
01067 bool QItemDelegate::editorEvent(QEvent *event,
01068 QAbstractItemModel *model,
01069 const QStyleOptionViewItem &option,
01070 const QModelIndex &index)
01071 {
01072 Q_ASSERT(event);
01073 Q_ASSERT(model);
01074
01075
01076 Qt::ItemFlags flags = model->flags(index);
01077 if (!(flags & Qt::ItemIsUserCheckable) || !((flags & Qt::ItemIsEnabled)))
01078 return false;
01079
01080
01081 QVariant value = index.data(Qt::CheckStateRole);
01082 if (!value.isValid())
01083 return false;
01084
01085
01086 if ((event->type() == QEvent::MouseButtonRelease)
01087 || (event->type() == QEvent::MouseButtonDblClick)) {
01088 const int textMargin = QApplication::style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1;
01089 QRect checkRect = QStyle::alignedRect(option.direction, Qt::AlignLeft | Qt::AlignVCenter,
01090 check(option, option.rect, Qt::Checked).size(),
01091 QRect(option.rect.x() + textMargin, option.rect.y(),
01092 option.rect.width(), option.rect.height()));
01093 if (!checkRect.contains(static_cast<QMouseEvent*>(event)->pos()))
01094 return false;
01095
01096
01097 if (event->type() == QEvent::MouseButtonDblClick)
01098 return true;
01099
01100 } else if (event->type() == QEvent::KeyPress) {
01101 if (static_cast<QKeyEvent*>(event)->key() != Qt::Key_Space
01102 && static_cast<QKeyEvent*>(event)->key() != Qt::Key_Select)
01103 return false;
01104 } else {
01105 return false;
01106 }
01107
01108 Qt::CheckState state = (static_cast<Qt::CheckState>(value.toInt()) == Qt::Checked
01109 ? Qt::Unchecked : Qt::Checked);
01110 return model->setData(index, state, Qt::CheckStateRole);
01111 }
01112
01117 QStyleOptionViewItem QItemDelegate::setOptions(const QModelIndex &index,
01118 const QStyleOptionViewItem &option) const
01119 {
01120 QStyleOptionViewItem opt = option;
01121
01122
01123 QVariant value = index.data(Qt::FontRole);
01124 if (value.isValid()){
01125 opt.font = qvariant_cast<QFont>(value).resolve(opt.font);
01126 opt.fontMetrics = QFontMetrics(opt.font);
01127 }
01128
01129
01130 value = index.data(Qt::TextAlignmentRole);
01131 if (value.isValid())
01132 opt.displayAlignment = (Qt::Alignment)value.toInt();
01133
01134
01135 value = index.data(Qt::ForegroundRole);
01136 if (qVariantCanConvert<QBrush>(value))
01137 opt.palette.setBrush(QPalette::Text, qvariant_cast<QBrush>(value));
01138
01139 return opt;
01140 }
01141
01142 #include "moc_qitemdelegate.cpp"
01143
01144 #endif // QT_NO_ITEMVIEWS