File indexing completed on 2025-04-27 03:58:29

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2009-04-19
0007  * Description : Qt item view for itemss - the delegate
0008  *
0009  * SPDX-FileCopyrightText: 2002-2005 by Renchi Raju <renchi dot raju at gmail dot com>
0010  * SPDX-FileCopyrightText: 2009      by Andi Clemens <andi dot clemens at gmail dot com>
0011  * SPDX-FileCopyrightText: 2006-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
0012  * SPDX-FileCopyrightText: 2002-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0013  *
0014  * SPDX-License-Identifier: GPL-2.0-or-later
0015  *
0016  * ============================================================ */
0017 
0018 #include "itemviewdelegate_p.h"
0019 
0020 // C++ includes
0021 
0022 #include <cmath>
0023 
0024 // Qt includes
0025 
0026 #include <QCache>
0027 #include <QPainter>
0028 #include <QIcon>
0029 #include <QApplication>
0030 
0031 // KDE includes
0032 
0033 #include <klocalizedstring.h>
0034 
0035 // Local includes
0036 
0037 #include "digikam_debug.h"
0038 #include "itempropertiestab.h"
0039 #include "thememanager.h"
0040 #include "colorlabelwidget.h"
0041 #include "ratingwidget.h"
0042 
0043 namespace Digikam
0044 {
0045 
0046 ItemViewDelegatePrivate::ItemViewDelegatePrivate()
0047     : spacing      (0),
0048       ratingPixmaps(QVector<QPixmap>(10)),
0049       thumbSize    (ThumbnailSize(0)),
0050       q            (nullptr),
0051       displayWidget(nullptr),
0052       radius       (3), // painting constants
0053       margin       (5)
0054 {
0055     makeStarPolygon();
0056 }
0057 
0058 void ItemViewDelegatePrivate::init(ItemViewDelegate* const _q, QWidget* const _widget)
0059 {
0060     q             = _q;
0061     displayWidget = _widget;
0062 
0063     q->connect(ThemeManager::instance(), SIGNAL(signalThemeChanged()),
0064                q, SLOT(slotThemeChanged()));
0065 }
0066 
0067 void ItemViewDelegatePrivate::clearRects()
0068 {
0069     gridSize   = QSize(0, 0);
0070     rect       = QRect(0, 0, 0, 0);
0071     ratingRect = QRect(0, 0, 0, 0);
0072 }
0073 
0074 void ItemViewDelegatePrivate::makeStarPolygon()
0075 {
0076     // Pre-computed star polygon for a 15x15 pixmap.
0077 
0078     starPolygon     = RatingWidget::starPolygon();
0079     starPolygonSize = QSize(15, 15);
0080 }
0081 
0082 ItemViewDelegate::ItemViewDelegate(QWidget* const parent)
0083     : DItemDelegate(parent),
0084       d_ptr        (new ItemViewDelegatePrivate)
0085 {
0086     d_ptr->init(this, parent);
0087 }
0088 
0089 ItemViewDelegate::ItemViewDelegate(ItemViewDelegatePrivate& dd, QWidget* const parent)
0090     : DItemDelegate(parent),
0091       d_ptr        (&dd)
0092 {
0093     d_ptr->init(this, parent);
0094 }
0095 
0096 ItemViewDelegate::~ItemViewDelegate()
0097 {
0098     Q_D(ItemViewDelegate);
0099 
0100     removeAllOverlays();
0101     delete d;
0102 }
0103 
0104 ThumbnailSize ItemViewDelegate::thumbnailSize() const
0105 {
0106     Q_D(const ItemViewDelegate);
0107 
0108     return d->thumbSize;
0109 }
0110 
0111 double ItemViewDelegate::displayRatio() const
0112 {
0113     Q_D(const ItemViewDelegate);
0114 
0115     return d->displayWidget->devicePixelRatio();
0116 }
0117 
0118 void ItemViewDelegate::setThumbnailSize(const ThumbnailSize& thumbSize)
0119 {
0120     Q_D(ItemViewDelegate);
0121 
0122     if (d->thumbSize != thumbSize)
0123     {
0124         d->thumbSize = thumbSize;
0125         invalidatePaintingCache();
0126     }
0127 }
0128 
0129 void ItemViewDelegate::setSpacing(int spacing)
0130 {
0131     Q_D(ItemViewDelegate);
0132 
0133     if (d->spacing == spacing)
0134     {
0135         return;
0136     }
0137 
0138     d->spacing = spacing;
0139     invalidatePaintingCache();
0140 }
0141 
0142 int ItemViewDelegate::spacing() const
0143 {
0144     Q_D(const ItemViewDelegate);
0145 
0146     return d->spacing;
0147 }
0148 
0149 QRect ItemViewDelegate::rect() const
0150 {
0151     Q_D(const ItemViewDelegate);
0152 
0153     return d->rect;
0154 }
0155 
0156 QRect ItemViewDelegate::pixmapRect() const
0157 {
0158     return QRect();
0159 }
0160 
0161 QRect ItemViewDelegate::imageInformationRect() const
0162 {
0163     return QRect();
0164 }
0165 
0166 QRect ItemViewDelegate::ratingRect() const
0167 {
0168     Q_D(const ItemViewDelegate);
0169 
0170     return d->ratingRect;
0171 }
0172 
0173 void ItemViewDelegate::setRatingEdited(const QModelIndex& index)
0174 {
0175     Q_D(ItemViewDelegate);
0176 
0177     d->editingRating = index;
0178 }
0179 
0180 QSize ItemViewDelegate::sizeHint(const QStyleOptionViewItem& /*option*/, const QModelIndex& /*index*/) const
0181 {
0182     Q_D(const ItemViewDelegate);
0183 
0184     return d->rect.size();
0185 }
0186 
0187 QSize ItemViewDelegate::gridSize() const
0188 {
0189     Q_D(const ItemViewDelegate);
0190 
0191     return d->gridSize;
0192 }
0193 
0194 bool ItemViewDelegate::acceptsToolTip(const QPoint&, const QRect& visualRect, const QModelIndex&, QRect* retRect) const
0195 {
0196     if (retRect)
0197     {
0198         *retRect = visualRect;
0199     }
0200 
0201     return true;
0202 }
0203 
0204 bool ItemViewDelegate::acceptsActivation(const QPoint& , const QRect& visualRect, const QModelIndex&, QRect* retRect) const
0205 {
0206     if (retRect)
0207     {
0208         *retRect = visualRect;
0209     }
0210 
0211     return true;
0212 }
0213 
0214 QAbstractItemDelegate* ItemViewDelegate::asDelegate()
0215 {
0216     return this;
0217 }
0218 
0219 void ItemViewDelegate::overlayDestroyed(QObject* o)
0220 {
0221     ItemDelegateOverlayContainer::overlayDestroyed(o);
0222 }
0223 
0224 void ItemViewDelegate::mouseMoved(QMouseEvent* e, const QRect& visualRect, const QModelIndex& index)
0225 {
0226     // 3-way indirection DItemDelegate -> ItemViewDelegate -> ItemDelegateOverlayContainer
0227 
0228     ItemDelegateOverlayContainer::mouseMoved(e, visualRect, index);
0229 }
0230 
0231 void ItemViewDelegate::setDefaultViewOptions(const QStyleOptionViewItem& option)
0232 {
0233     Q_D(ItemViewDelegate);
0234 
0235     d->font = option.font;
0236     invalidatePaintingCache();
0237 }
0238 
0239 void ItemViewDelegate::slotThemeChanged()
0240 {
0241     invalidatePaintingCache();
0242 }
0243 
0244 void ItemViewDelegate::slotSetupChanged()
0245 {
0246     invalidatePaintingCache();
0247 }
0248 
0249 void ItemViewDelegate::invalidatePaintingCache()
0250 {
0251     Q_D(ItemViewDelegate);
0252 
0253     QSize oldGridSize = d->gridSize;
0254     updateSizeRectsAndPixmaps();
0255 
0256     if (oldGridSize != d->gridSize)
0257     {
0258         Q_EMIT gridSizeChanged(d->gridSize);
0259 /*
0260         Q_EMIT sizeHintChanged(QModelIndex());
0261 */
0262     }
0263 
0264     Q_EMIT visualChange();
0265 }
0266 
0267 QRect ItemViewDelegate::drawThumbnail(QPainter* p, const QRect& thumbRect, const QPixmap& background,
0268                                       const QPixmap& thumbnail, bool isGrouped) const
0269 {
0270     Q_D(const ItemViewDelegate);
0271 
0272     p->drawPixmap(0, 0, background);
0273 
0274     if (thumbnail.isNull())
0275     {
0276         return QRect();
0277     }
0278 
0279     QRect r    = thumbRect;
0280     double dpr = displayRatio();
0281     int thumbW = qRound((double)thumbnail.width()  / dpr);
0282     int thumbH = qRound((double)thumbnail.height() / dpr);
0283 
0284     QRect actualPixmapRect(r.x() + (r.width()  - thumbW) / 2,
0285                            r.y() + (r.height() - thumbH) / 2,
0286                            thumbW, thumbH);
0287 
0288     QPixmap borderPix = thumbnailBorderPixmap(actualPixmapRect.size(),
0289                                               isGrouped);
0290 
0291     if (isGrouped)
0292     {
0293         const int xPadding = (borderPix.width()  - actualPixmapRect.width())  / 2;
0294         const int yPadding = (borderPix.height() - actualPixmapRect.height()) / 2;
0295 
0296         p->drawPixmap(actualPixmapRect.x() - xPadding,
0297                       actualPixmapRect.y() - yPadding, borderPix);
0298 
0299         QPixmap groupThumbnail = thumbnail.scaled(thumbnail.width()  - 10,
0300                                                   thumbnail.height() - 10,
0301                                                   Qt::KeepAspectRatio,
0302                                                   Qt::SmoothTransformation);
0303 
0304         p->drawPixmap(r.x() + (r.width()  - (thumbW - 10)) / 2,
0305                       r.y() + (r.height() - (thumbH - 10)) / 2,
0306                       thumbW - 10, thumbH - 10, groupThumbnail);
0307     }
0308     else
0309     {
0310         p->drawPixmap(actualPixmapRect.x() - d->radius,
0311                       actualPixmapRect.y() - d->radius, borderPix);
0312 
0313         p->drawPixmap(r.x() + (r.width()  - thumbW) / 2,
0314                       r.y() + (r.height() - thumbH) / 2,
0315                       thumbW, thumbH, thumbnail);
0316     }
0317 
0318     return actualPixmapRect;
0319 }
0320 
0321 void ItemViewDelegate::drawRating(QPainter* p, const QModelIndex& index, const QRect& ratingRect,
0322                                   int rating, bool isSelected) const
0323 {
0324     Q_D(const ItemViewDelegate);
0325 
0326     if (d->editingRating != index)
0327     {
0328         p->drawPixmap(ratingRect, ratingPixmap(rating, isSelected));
0329     }
0330 }
0331 
0332 void ItemViewDelegate::drawSpecialInfo(QPainter* p,const QRect& r, const QString& text) const
0333 {
0334     Q_D(const ItemViewDelegate);
0335 
0336     if (!text.isEmpty() && !r.isNull())
0337     {
0338         p->save();
0339 
0340         QFont fnt(d->fontReg);
0341         fnt.setWeight(QFont::Black);
0342         fnt.setItalic(false);
0343         p->setFont(fnt);
0344         p->setPen(QPen(Qt::gray));
0345         p->setOpacity(0.50);
0346 
0347         int flags   = Qt::AlignCenter | Qt::TextWordWrap;
0348         QRect bRect = p->boundingRect(r, flags, text);
0349 
0350         if (bRect.width() > r.width())
0351         {
0352             flags = Qt::AlignCenter | Qt::TextWrapAnywhere;
0353             bRect = p->boundingRect(r, flags, text);
0354         }
0355 
0356         p->fillRect(bRect, Qt::SolidPattern);
0357         p->setPen(QPen(Qt::white));
0358         p->setOpacity(1.0);
0359         p->drawText(bRect, flags, text);
0360 
0361         p->restore();
0362     }
0363 }
0364 
0365 void ItemViewDelegate::drawName(QPainter* p,const QRect& nameRect, const QString& name) const
0366 {
0367     Q_D(const ItemViewDelegate);
0368 
0369     p->setFont(d->fontReg);
0370 
0371     // NOTE: in case of file name are long, use squeezedTextCached to adjust string elide mode.
0372     // See bug #278664 for details
0373 
0374     p->drawText(nameRect, Qt::AlignCenter, squeezedTextCached(p, nameRect.width(), name));
0375 }
0376 
0377 void ItemViewDelegate::drawTitle(QPainter* p, const QRect& titleRect, const QString& title) const
0378 {
0379     Q_D(const ItemViewDelegate);
0380 
0381     p->setFont(d->fontReg);
0382     p->drawText(titleRect, Qt::AlignCenter, squeezedTextCached(p, titleRect.width(), title));
0383 }
0384 
0385 void ItemViewDelegate::drawComments(QPainter* p, const QRect& commentsRect, const QString& comments) const
0386 {
0387     Q_D(const ItemViewDelegate);
0388 
0389     p->setFont(d->fontCom);
0390     p->drawText(commentsRect, Qt::AlignCenter, squeezedTextCached(p, commentsRect.width(), comments));
0391 }
0392 
0393 void ItemViewDelegate::drawCreationDate(QPainter* p, const QRect& dateRect, const QDateTime& date) const
0394 {
0395     Q_D(const ItemViewDelegate);
0396 
0397     p->setFont(d->fontXtra);
0398     QString str = dateToString(date);
0399 /*
0400     str         = i18nc("date of image creation", "created: %1", str);
0401 */
0402     p->drawText(dateRect, Qt::AlignCenter, str); //squeezedTextCached(p, dateRect.width(), str));
0403 }
0404 
0405 void ItemViewDelegate::drawModificationDate(QPainter* p, const QRect& dateRect, const QDateTime& date) const
0406 {
0407     Q_D(const ItemViewDelegate);
0408 
0409     p->setFont(d->fontXtra);
0410     QString str = dateToString(date);
0411     str         = i18nc("date of last image modification", "Mod.: %1",str);
0412     p->drawText(dateRect, Qt::AlignCenter, str); //squeezedTextCached(p, dateRect.width(), str));
0413 }
0414 
0415 void ItemViewDelegate::drawImageSize(QPainter* p, const QRect& dimsRect, const QSize& dims) const
0416 {
0417     Q_D(const ItemViewDelegate);
0418 
0419     if (dims.isValid())
0420     {
0421         p->setFont(d->fontXtra);
0422         QString mpixels, resolution;
0423         mpixels = QLocale().toString(dims.width()*dims.height()/1000000.0, 'f', 1);
0424 
0425         if (dims.isValid())
0426         {
0427             resolution = i18nc("%1 width, %2 height, %3 mpixels", "%1x%2 (%3Mpx)",
0428                                dims.width(), dims.height(), mpixels);
0429         }
0430         else
0431         {
0432             resolution = i18nc("unknown image resolution", "Unknown");
0433         }
0434 
0435         p->drawText(dimsRect, Qt::AlignCenter, resolution); //squeezedTextCached(p, dimsRect.width(), resolution));
0436     }
0437 }
0438 
0439 void ItemViewDelegate::drawAspectRatio(QPainter* p, const QRect& dimsRect, const QSize& dims) const
0440 {
0441     Q_D(const ItemViewDelegate);
0442 
0443     p->setFont(d->fontXtra);
0444     QString resolution;
0445 
0446     if (dims.isValid())
0447     {
0448         ItemPropertiesTab::aspectRatioToString(dims.width(), dims.height(), resolution);
0449     }
0450     else
0451     {
0452         resolution = i18nc("unknown image resolution", "Unknown");
0453     }
0454 
0455     p->drawText(dimsRect, Qt::AlignCenter, resolution); //squeezedTextCached(p, dimsRect.width(), resolution));
0456 }
0457 
0458 void ItemViewDelegate::drawFileSize(QPainter* p, const QRect& r, qlonglong bytes) const
0459 {
0460     Q_D(const ItemViewDelegate);
0461 
0462     p->setFont(d->fontXtra);
0463     p->drawText(r, Qt::AlignCenter, ItemPropertiesTab::humanReadableBytesCount(bytes));
0464 }
0465 
0466 void ItemViewDelegate::drawTags(QPainter* p, const QRect& r, const QString& tagsString,
0467                                      bool isSelected) const
0468 {
0469     Q_D(const ItemViewDelegate);
0470 
0471     p->setFont(d->fontCom);
0472     p->setPen(isSelected ? qApp->palette().color(QPalette::HighlightedText)
0473                          : qApp->palette().color(QPalette::Link));
0474 
0475     p->drawText(r, Qt::AlignCenter, squeezedTextCached(p, r.width(), tagsString));
0476 }
0477 
0478 void ItemViewDelegate::drawFocusRect(QPainter* p, const QStyleOptionViewItem& option,
0479                                           bool isSelected) const
0480 {
0481     Q_D(const ItemViewDelegate);
0482 
0483     if (option.state & QStyle::State_HasFocus) //?? is current item
0484     {
0485         p->setPen(QPen(isSelected ? qApp->palette().color(QPalette::HighlightedText)
0486                                   : qApp->palette().color(QPalette::Text),
0487                        1, Qt::DotLine));
0488         p->drawRect(1, 1, d->rect.width()-3, d->rect.height()-3);
0489     }
0490 }
0491 
0492 void ItemViewDelegate::drawImageFormat(QPainter* p, const QRect& r, const QString& f, bool drawTop) const
0493 {
0494     Q_D(const ItemViewDelegate);
0495 
0496     if (!f.isEmpty() && !r.isNull())
0497     {
0498         Qt::Alignment alignment = Qt::AlignBottom;
0499 
0500         if (drawTop)
0501         {
0502             alignment = Qt::AlignTop;
0503         }
0504 
0505         p->save();
0506 
0507         QFont fnt(d->fontReg);
0508         fnt.setWeight(QFont::Black);
0509         fnt.setItalic(false);
0510         p->setFont(fnt);
0511         p->setPen(QPen(Qt::gray));
0512         p->setOpacity(0.50);
0513 
0514         QRect bRect = p->boundingRect(r, alignment | Qt::AlignHCenter, f.toUpper());
0515         bRect.adjust(0, 0, 0, -2);
0516 
0517         if (!drawTop)
0518         {
0519             bRect.translate(0, 1);
0520         }
0521 
0522         p->fillRect(bRect, Qt::SolidPattern);
0523         p->setPen(QPen(Qt::white));
0524         p->setOpacity(1.0);
0525         p->drawText(bRect, Qt::AlignBottom | Qt::AlignHCenter, f.toUpper());
0526 
0527         p->restore();
0528     }
0529 }
0530 
0531 void ItemViewDelegate::drawPickLabelIcon(QPainter* p, const QRect& r, int pickId) const
0532 {
0533     // Draw Pick Label icon
0534 
0535     if (pickId != NoPickLabel)
0536     {
0537         QIcon icon;
0538 
0539         if      (pickId == RejectedLabel)
0540         {
0541             icon = QIcon::fromTheme(QLatin1String("flag-red"));
0542         }
0543         else if (pickId == PendingLabel)
0544         {
0545             icon = QIcon::fromTheme(QLatin1String("flag-yellow"));
0546         }
0547         else if (pickId == AcceptedLabel)
0548         {
0549             icon = QIcon::fromTheme(QLatin1String("flag-green"));
0550         }
0551 
0552         icon.paint(p, r);
0553     }
0554 }
0555 
0556 void ItemViewDelegate::drawPanelSideIcon(QPainter* p, bool left, bool right) const
0557 {
0558     Q_D(const ItemViewDelegate);
0559 
0560     const int iconSize = qBound(16, d->rect.width() / 8 - 2, 48);
0561 
0562     if (left)
0563     {
0564         QRect r(3, d->rect.height()/2 - iconSize/2, iconSize, iconSize);
0565         p->setPen(QPen(Qt::gray));
0566         p->setOpacity(0.50);
0567         p->fillRect(r, Qt::SolidPattern);
0568         QIcon icon = QIcon::fromTheme(QLatin1String("arrow-left"));
0569         p->setOpacity(1.0);
0570         icon.paint(p, r, Qt::AlignCenter, QIcon::Active, QIcon::On);
0571     }
0572 
0573     if (right)
0574     {
0575         QRect r(d->rect.width() - 3 - iconSize, d->rect.height()/2 - iconSize/2, iconSize, iconSize);
0576         p->setPen(QPen(Qt::gray));
0577         p->setOpacity(0.50);
0578         p->fillRect(r, Qt::SolidPattern);
0579         QIcon icon = QIcon::fromTheme(QLatin1String("arrow-right"));
0580         p->setOpacity(1.0);
0581         icon.paint(p, r, Qt::AlignCenter, QIcon::Active, QIcon::On);
0582     }
0583 }
0584 
0585 void ItemViewDelegate::drawGeolocationIndicator(QPainter* p, const QRect& r) const
0586 {
0587     if (!r.isNull())
0588     {
0589         QIcon icon(QIcon::fromTheme(QLatin1String("globe")).pixmap(r.size()));
0590         QBrush brush = p->brush();
0591         p->setOpacity(0.50);
0592         p->setPen(QPen(p->background().color()));
0593         p->setBrush(QBrush(p->background().color()));
0594         p->drawEllipse(r);
0595         p->setBrush(brush);
0596         p->setOpacity(1.0);
0597         icon.paint(p, r);
0598     }
0599 }
0600 
0601 void ItemViewDelegate::drawGroupIndicator(QPainter* p, const QRect& r,
0602                                           int numberOfGroupedImages, bool open) const
0603 {
0604     if (numberOfGroupedImages)
0605     {
0606         QIcon icon;
0607 
0608         if (open)
0609         {
0610             icon = QIcon::fromTheme(QLatin1String("folder-open")); //image-stack-open
0611         }
0612         else
0613         {
0614             icon = QIcon::fromTheme(QLatin1String("folder")); //image-stack
0615         }
0616 
0617         icon.paint(p, r);
0618 
0619         QString text = QString::number(numberOfGroupedImages + 1);
0620         p->drawText(r, Qt::AlignCenter, text);
0621     }
0622 }
0623 
0624 void ItemViewDelegate::drawColorLabelRect(QPainter* p, const QStyleOptionViewItem& option,
0625                                           bool isSelected, int colorId) const
0626 {
0627     Q_D(const ItemViewDelegate);
0628     Q_UNUSED(option);
0629     Q_UNUSED(isSelected);
0630 
0631     if (colorId > NoColorLabel)
0632     {
0633         // This draw a simple rectangle around item.
0634 
0635         p->setPen(QPen(ColorLabelWidget::labelColor((ColorLabel)colorId), 5, Qt::SolidLine));
0636         p->drawRect(3, 3, d->rect.width()-7, d->rect.height()-7);
0637     }
0638 }
0639 
0640 void ItemViewDelegate::drawMouseOverRect(QPainter* p, const QStyleOptionViewItem& option) const
0641 {
0642     Q_D(const ItemViewDelegate);
0643 
0644     if (option.state & QStyle::State_MouseOver)
0645     {
0646         p->setPen(QPen(option.palette.color(QPalette::Highlight), 3, Qt::SolidLine));
0647         p->drawRect(1, 1, d->rect.width()-3, d->rect.height()-3);
0648     }
0649 }
0650 
0651 void ItemViewDelegate::prepareFonts()
0652 {
0653     Q_D(ItemViewDelegate);
0654 
0655     d->fontReg  = d->font;
0656     d->fontCom  = d->font;
0657     d->fontXtra = d->font;
0658     d->fontCom.setItalic(true);
0659 
0660     int fnSz    = d->fontReg.pointSize();
0661 
0662     if (fnSz > 0)
0663     {
0664         d->fontCom.setPointSize(fnSz-1);
0665         d->fontXtra.setPointSize(fnSz-2);
0666     }
0667     else
0668     {
0669         fnSz = d->fontReg.pixelSize();
0670         d->fontCom.setPixelSize(fnSz-1);
0671         d->fontXtra.setPixelSize(fnSz-2);
0672     }
0673 }
0674 
0675 void ItemViewDelegate::prepareMetrics(int maxWidth)
0676 {
0677     Q_D(ItemViewDelegate);
0678 
0679     QFontMetrics fm(d->fontReg);
0680     d->oneRowRegRect = fm.boundingRect(0, 0, maxWidth, 0xFFFFFFFF,
0681                                        Qt::AlignTop | Qt::AlignHCenter,
0682                                        QLatin1String("XXXXXXXXX"));
0683     fm = QFontMetrics(d->fontCom);
0684     d->oneRowComRect = fm.boundingRect(0, 0, maxWidth, 0xFFFFFFFF,
0685                                        Qt::AlignTop | Qt::AlignHCenter,
0686                                        QLatin1String("XXXXXXXXX"));
0687     fm = QFontMetrics(d->fontXtra);
0688     d->oneRowXtraRect = fm.boundingRect(0, 0, maxWidth, 0xFFFFFFFF,
0689                                         Qt::AlignTop | Qt::AlignHCenter,
0690                                         QLatin1String("XXXXXXXXX"));
0691 }
0692 
0693 void ItemViewDelegate::prepareBackground()
0694 {
0695     Q_D(ItemViewDelegate);
0696 
0697     if (!d->rect.isValid())
0698     {
0699         d->regPixmap = QPixmap();
0700         d->selPixmap = QPixmap();
0701     }
0702     else
0703     {
0704         d->regPixmap = QPixmap(d->rect.width(), d->rect.height());
0705         d->regPixmap.fill(qApp->palette().color(QPalette::Base));
0706         QPainter p1(&d->regPixmap);
0707         p1.setPen(qApp->palette().color(QPalette::Midlight));
0708         p1.drawRect(0, 0, d->rect.width()-1, d->rect.height()-1);
0709 
0710         d->selPixmap = QPixmap(d->rect.width(), d->rect.height());
0711         d->selPixmap.fill(qApp->palette().color(QPalette::Highlight));
0712         QPainter p2(&d->selPixmap);
0713         p2.setPen(qApp->palette().color(QPalette::Midlight));
0714         p2.drawRect(0, 0, d->rect.width()-1, d->rect.height()-1);
0715     }
0716 }
0717 
0718 void ItemViewDelegate::prepareRatingPixmaps(bool composeOverBackground)
0719 {
0720     // Please call this method after prepareBackground() and when d->ratingPixmap is set
0721 
0722     Q_D(ItemViewDelegate);
0723 
0724     if (!d->ratingRect.isValid())
0725     {
0726         return;
0727     }
0728 
0729     // We use antialiasing and want to pre-render the pixmaps.
0730     // So we need the background at the time of painting,
0731     // and the background may be a gradient, and will be different for selected items.
0732     // This makes 5*2 (small) pixmaps.
0733 
0734     for (int sel = 0 ; sel < 2 ; ++sel)
0735     {
0736         QPixmap basePix;
0737 
0738         if (composeOverBackground)
0739         {
0740             // do this once for regular, once for selected backgrounds
0741 
0742             if (sel)
0743             {
0744                 basePix = d->selPixmap.copy(d->ratingRect);
0745             }
0746             else
0747             {
0748                 basePix = d->regPixmap.copy(d->ratingRect);
0749             }
0750         }
0751         else
0752         {
0753             basePix = QPixmap(d->ratingRect.size());
0754             basePix.fill(Qt::transparent);
0755         }
0756 
0757         double dpr = displayRatio();
0758         basePix    = basePix.scaled(d->ratingRect.size() * dpr);
0759         basePix.setDevicePixelRatio(dpr);
0760 
0761         for (int rating = 1 ; rating <= 5 ; ++rating)
0762         {
0763             // we store first the 5 regular, then the 5 selected pixmaps, for simplicity
0764 
0765             int index = (sel * 5 + rating) - 1;
0766 
0767             // copy background
0768 
0769             d->ratingPixmaps[index] = basePix;
0770 
0771             // open a painter
0772 
0773             QPainter painter(&d->ratingPixmaps[index]);
0774 
0775             // use antialiasing
0776 
0777             painter.setRenderHint(QPainter::Antialiasing, true);
0778             painter.setBrush(qApp->palette().color(QPalette::Link));
0779             QPen pen(qApp->palette().color(QPalette::Text));
0780 
0781             // set a pen which joins the lines at a filled angle
0782 
0783             pen.setJoinStyle(Qt::MiterJoin);
0784             painter.setPen(pen);
0785 
0786             // move painter while drawing polygons
0787 
0788             painter.translate(lround((d->ratingRect.width() - d->margin - rating*(d->starPolygonSize.width()+1))/2.0) + 2, 0);
0789 
0790             for (int s = 0 ; s < rating ; ++s)
0791             {
0792                 painter.drawPolygon(d->starPolygon, Qt::WindingFill);
0793                 painter.translate(d->starPolygonSize.width() + 1, 0);
0794             }
0795         }
0796     }
0797 }
0798 
0799 QPixmap ItemViewDelegate::ratingPixmap(int rating, bool selected) const
0800 {
0801     Q_D(const ItemViewDelegate);
0802 
0803     if ((rating < 1) || (rating > 5))
0804     {
0805         return QPixmap();
0806     }
0807 
0808     --rating;
0809 
0810     if (selected)
0811     {
0812         return d->ratingPixmaps.at(5 + rating);
0813     }
0814     else
0815     {
0816         return d->ratingPixmaps.at(rating);
0817     }
0818 }
0819 
0820 } // namespace Digikam
0821 
0822 #include "moc_itemviewdelegate.cpp"