File indexing completed on 2025-04-27 03:58:28
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2010-01-16 0007 * Description : Qt item view for images - common delegate code 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: 2002-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> 0012 * SPDX-FileCopyrightText: 2006-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> 0013 * 0014 * SPDX-License-Identifier: GPL-2.0-or-later 0015 * 0016 * ============================================================ */ 0017 0018 #include "ditemdelegate.h" 0019 0020 // C++ includes 0021 0022 #include <cmath> 0023 0024 // Qt includes 0025 0026 #include <QApplication> 0027 #include <QCache> 0028 #include <QPainter> 0029 #include <QLocale> 0030 0031 // KDE includes 0032 0033 #include <klocalizedstring.h> 0034 0035 // Local includes 0036 0037 #include "itemviewcategorized.h" 0038 #include "thememanager.h" 0039 #include "thumbbardock.h" 0040 0041 namespace Digikam 0042 { 0043 0044 class Q_DECL_HIDDEN DItemDelegate::Private 0045 { 0046 public: 0047 0048 explicit Private() 0049 { 0050 } 0051 0052 QCache<QString, QPixmap> thumbnailBorderCache; 0053 QCache<QString, QString> squeezedTextCache; 0054 }; 0055 0056 DItemDelegate::DItemDelegate(QObject* const parent) 0057 : QAbstractItemDelegate(parent), 0058 d (new Private) 0059 { 0060 } 0061 0062 DItemDelegate::~DItemDelegate() 0063 { 0064 delete d; 0065 } 0066 0067 void DItemDelegate::clearCaches() 0068 { 0069 d->thumbnailBorderCache.clear(); 0070 d->squeezedTextCache.clear(); 0071 } 0072 0073 QPixmap DItemDelegate::thumbnailBorderPixmap(const QSize& pixSize, bool isGrouped) const 0074 { 0075 const QColor borderColor = QColor(0, 0, 0, 128); 0076 QString cacheKey = QString::number(pixSize.width()) + QLatin1Char('-') 0077 + QString::number(pixSize.height()) + QLatin1Char('-') 0078 + QString::number(isGrouped); 0079 QPixmap* const cachePix = d->thumbnailBorderCache.object(cacheKey); 0080 0081 if (!cachePix) 0082 { 0083 const int radius = 3; 0084 QPixmap pix; 0085 const int width = pixSize.width() + 2*radius; 0086 const int height = pixSize.height() + 2*radius; 0087 0088 if (isGrouped) 0089 { 0090 pix = ThumbBarDock::generateFuzzyRectForGroup(QSize(width, height), 0091 borderColor, 0092 radius); 0093 } 0094 else 0095 { 0096 pix = ThumbBarDock::generateFuzzyRect(QSize(width, height), 0097 borderColor, 0098 radius); 0099 } 0100 0101 d->thumbnailBorderCache.insert(cacheKey, new QPixmap(pix)); 0102 return pix; 0103 } 0104 0105 return *cachePix; 0106 } 0107 0108 QPixmap DItemDelegate::makeDragPixmap(const QStyleOptionViewItem& option, 0109 const QList<QModelIndex>& indexes, 0110 double displayRatio, 0111 const QPixmap& suggestedPixmap) 0112 { 0113 int iconSize = qRound(64.0 * displayRatio); 0114 QPixmap icon = suggestedPixmap; 0115 0116 if (icon.isNull()) 0117 { 0118 icon = QPixmap(QIcon::fromTheme(QLatin1String("image-jpeg")).pixmap(32)); 0119 } 0120 0121 if (qMax(icon.width(), icon.height()) > iconSize) 0122 { 0123 icon = icon.scaled(iconSize, iconSize, Qt::KeepAspectRatio, 0124 Qt::SmoothTransformation); 0125 } 0126 0127 int w = icon.width(); 0128 int h = icon.height(); 0129 const int borderWidth = 6; 0130 0131 QSizeF drawSize = QSizeF(w, h) / displayRatio; 0132 QRect rect(0, 0, w + qRound((double)borderWidth * 2.0 * displayRatio), 0133 h + qRound((double)borderWidth * 2.0 * displayRatio)); 0134 QRect pixmapRect(QPoint(borderWidth, borderWidth), drawSize.toSize()); 0135 0136 QPixmap pix(rect.size()); 0137 pix.setDevicePixelRatio(displayRatio); 0138 QPainter p(&pix); 0139 0140 /* 0141 // border 0142 p.fillRect(0, 0, pix.width()-1, pix.height()-1, QColor(Qt::white)); 0143 p.setPen(QPen(Qt::black, 1)); 0144 p.drawRect(0, 0, pix.width()-1, pix.height()-1); 0145 */ 0146 0147 QStyleOption opt(option); 0148 opt.rect = rect; 0149 qApp->style()->drawPrimitive(QStyle::PE_PanelTipLabel, &opt, &p); 0150 0151 p.drawPixmap(pixmapRect, icon); 0152 0153 QFont f(option.font); 0154 f.setBold(true); 0155 p.setFont(f); 0156 0157 if (indexes.size() > 1) 0158 { 0159 QRect textRect; 0160 QString text; 0161 0162 QString text2(i18np("1 Image", "%1 Images", indexes.count())); 0163 QString text1 = QString::number(indexes.count()); 0164 QRect r1 = p.boundingRect(pixmapRect, Qt::AlignLeft | Qt::AlignTop, text1).adjusted(0, 0, 1, 1); 0165 QRect r2 = p.boundingRect(pixmapRect, Qt::AlignLeft | Qt::AlignTop, text2).adjusted(0, 0, 1, 1); 0166 0167 if ((r2.width() > pixmapRect.width()) || (r2.height() > pixmapRect.height())) 0168 { 0169 // textRect = r1; 0170 text = text1; 0171 int rectSize = qMax(r1.width(), r1.height()); 0172 textRect = QRect(0, 0, rectSize, rectSize); 0173 } 0174 else 0175 { 0176 textRect = QRect(0, 0, r2.width(), r2.height()); 0177 text = text2; 0178 } 0179 0180 textRect.moveLeft((pixmapRect.width() - textRect.width()) / 2 + pixmapRect.x()); 0181 textRect.moveTop((pixmapRect.height() - textRect.height()) * 4 / 5); 0182 p.fillRect(textRect, QColor(0, 0, 0, 128)); 0183 p.setPen(Qt::white); 0184 p.drawText(textRect, Qt::AlignCenter, text); 0185 } 0186 0187 return pix; 0188 } 0189 0190 QString DItemDelegate::dateToString(const QDateTime& datetime) 0191 { 0192 return QLocale().toString(datetime, QLocale::ShortFormat); 0193 } 0194 0195 QString DItemDelegate::squeezedTextCached(QPainter* const p, int width, const QString& text) const 0196 { 0197 QCache<QString, QString>* const cache = &const_cast<DItemDelegate*>(this)->d->squeezedTextCache; 0198 0199 // We do not need to include the font into cache key, the cache is cleared on font change 0200 0201 QString cacheKey = QString::number(width) + QString::number(qHash(text)); 0202 QString* const cachedString = cache->object(cacheKey); 0203 0204 if (cachedString) 0205 { 0206 return *cachedString; 0207 } 0208 0209 QString result = squeezedText(p->fontMetrics(), width, text); 0210 cache->insert(cacheKey, new QString(result)); 0211 0212 return result; 0213 } 0214 0215 QString DItemDelegate::squeezedText(const QFontMetrics& fm, int width, const QString& text) 0216 { 0217 QString fullText(text); 0218 fullText.replace(QLatin1Char('\n'), QLatin1Char(' ')); 0219 0220 return fm.elidedText(text, Qt::ElideRight, width); 0221 } 0222 0223 } // namespace Digikam 0224 0225 #include "moc_ditemdelegate.cpp"