File indexing completed on 2025-01-05 03:59:46

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2011-08-03
0007  * Description : digital camera thumbnails controller
0008  *
0009  * SPDX-FileCopyrightText: 2011-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0010  * SPDX-FileCopyrightText: 2015      by Mohamed_Anwer <m_dot_anwer at gmx dot com>
0011  *
0012  * SPDX-License-Identifier: GPL-2.0-or-later
0013  *
0014  * ============================================================ */
0015 
0016 #include "camerathumbsctrl.h"
0017 
0018 // Qt includes
0019 
0020 #include <QCache>
0021 #include <QPair>
0022 
0023 // Local includes
0024 
0025 #include "digikam_debug.h"
0026 #include "cameracontroller.h"
0027 #include "thumbnailsize.h"
0028 #include "iccsettings.h"
0029 #include "iccmanager.h"
0030 #include "iccprofile.h"
0031 
0032 namespace Digikam
0033 {
0034 
0035 class Q_DECL_HIDDEN CameraThumbsCtrlStaticPriv
0036 {
0037 public:
0038 
0039     CameraThumbsCtrlStaticPriv()
0040       : profile(IccProfile::sRGB())
0041     {
0042     }
0043 
0044 public:
0045 
0046     IccProfile profile;
0047 };
0048 
0049 Q_GLOBAL_STATIC(CameraThumbsCtrlStaticPriv, static_d)
0050 
0051 // ------------------------------------------------------------------------------------------
0052 
0053 class Q_DECL_HIDDEN CameraThumbsCtrl::Private
0054 {
0055 
0056 public:
0057 
0058     explicit Private()
0059         : controller(nullptr)
0060     {
0061     }
0062 
0063     QCache<QUrl, CachedItem>   cache;  // Camera info/thumb cache based on item url keys.
0064 
0065     QMap<QUrl, CameraCommand*> pendingItems;
0066 
0067     CameraController*          controller;
0068 };
0069 
0070 // --------------------------------------------------------
0071 
0072 CameraThumbsCtrl::CameraThumbsCtrl(CameraController* const ctrl, QWidget* const parent)
0073     : QObject(parent),
0074       d      (new Private)
0075 {
0076     d->controller     = ctrl;
0077     static_d->profile = IccManager::displayProfile(parent);
0078 
0079     connect(d->controller, SIGNAL(signalThumbInfo(QString,QString,CamItemInfo,QImage)),
0080             this, SLOT(slotThumbInfo(QString,QString,CamItemInfo,QImage)));
0081 
0082     connect(d->controller, SIGNAL(signalThumbInfoFailed(QString,QString,CamItemInfo)),
0083             this, SLOT(slotThumbInfoFailed(QString,QString,CamItemInfo)));
0084 
0085     setCacheSize(200);
0086 }
0087 
0088 CameraThumbsCtrl::~CameraThumbsCtrl()
0089 {
0090     clearCache();
0091 }
0092 
0093 CameraController* CameraThumbsCtrl::cameraController() const
0094 {
0095     return d->controller;
0096 }
0097 
0098 bool CameraThumbsCtrl::getThumbInfo(const CamItemInfo& info, CachedItem& item) const
0099 {
0100     if      (hasItemFromCache(info.url()))
0101     {
0102         // We look if items are not in cache.
0103 
0104         item = *retrieveItemFromCache(info.url());
0105 
0106         return true;
0107     }
0108     else if (d->pendingItems.contains(info.url()))
0109     {
0110         d->controller->moveThumbsInfo(d->pendingItems.value(info.url()));
0111     }
0112     else
0113     {
0114         // We look if items are not in pending list.
0115 
0116         CameraCommand* const cmd = d->controller->getThumbsInfo(CamItemInfoList() << info,
0117                                                                 ThumbnailSize::maxThumbsSize());
0118         d->pendingItems.insert(info.url(), cmd);
0119     }
0120 
0121     item = CachedItem(info, d->controller->mimeTypeThumbnail(info.name).pixmap(ThumbnailSize::maxThumbsSize()));
0122 
0123     return false;
0124 }
0125 
0126 void CameraThumbsCtrl::updateThumbInfoFromCache(const CamItemInfo& info)
0127 {
0128     removeItemFromCache(info.url());
0129     CachedItem item;
0130     getThumbInfo(info, item);
0131 }
0132 
0133 void CameraThumbsCtrl::slotThumbInfo(const QString&, const QString& file, const CamItemInfo& info, const QImage& thumb)
0134 {
0135     QImage thumbnail = thumb;
0136 
0137     if (thumb.isNull())
0138     {
0139         thumbnail = d->controller->mimeTypeThumbnail(file).pixmap(ThumbnailSize::maxThumbsSize()).toImage();
0140     }
0141 
0142     // Color Managed view rules.
0143 
0144     if (IccSettings::instance()->useManagedPreviews())
0145     {
0146         IccManager::transformForDisplay(thumbnail, static_d->profile);
0147     }
0148 
0149     putItemToCache(info.url(), info, QPixmap::fromImage(thumbnail));
0150     d->pendingItems.remove(info.url());
0151     Q_EMIT signalThumbInfoReady(info);
0152 }
0153 
0154 void CameraThumbsCtrl::slotThumbInfoFailed(const QString& /*folder*/, const QString& file, const CamItemInfo& info)
0155 {
0156     QPixmap pix = d->controller->mimeTypeThumbnail(file).pixmap(ThumbnailSize::maxThumbsSize());
0157     putItemToCache(info.url(), info, pix);
0158     d->pendingItems.remove(info.url());
0159     Q_EMIT signalThumbInfoReady(info);
0160 }
0161 
0162 // -- Cache management methods ------------------------------------------------------------
0163 
0164 const CachedItem* CameraThumbsCtrl::retrieveItemFromCache(const QUrl& url) const
0165 {
0166     return d->cache[url];
0167 }
0168 
0169 bool CameraThumbsCtrl::hasItemFromCache(const QUrl& url) const
0170 {
0171     return d->cache.contains(url);
0172 }
0173 
0174 void CameraThumbsCtrl::putItemToCache(const QUrl& url, const CamItemInfo& info, const QPixmap& thumb)
0175 {
0176     int infoCost  = sizeof(info);
0177     int thumbCost = thumb.width() * thumb.height() * thumb.depth() / 8;
0178     d->cache.insert(url, new CachedItem(info, thumb), infoCost + thumbCost);
0179 }
0180 
0181 void CameraThumbsCtrl::removeItemFromCache(const QUrl& url)
0182 {
0183     d->cache.remove(url);
0184 }
0185 
0186 void CameraThumbsCtrl::clearCache()
0187 {
0188     d->cache.clear();
0189 }
0190 
0191 void CameraThumbsCtrl::setCacheSize(int numberOfItems)
0192 {
0193     d->cache.setMaxCost(numberOfItems * (ThumbnailSize::maxThumbsSize() * ThumbnailSize::maxThumbsSize() *
0194                                          QPixmap(1, 1).depth() / 8) + (numberOfItems * sizeof(CamItemInfo)));
0195 }
0196 
0197 } // namespace Digikam
0198 
0199 #include "moc_camerathumbsctrl.cpp"