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"