File indexing completed on 2025-04-27 03:58:23
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2010-04-30 0007 * Description : Graphics View items for DImg 0008 * 0009 * SPDX-FileCopyrightText: 2010-2011 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> 0010 * 0011 * SPDX-License-Identifier: GPL-2.0-or-later 0012 * 0013 * ============================================================ */ 0014 0015 #include "dimgpreviewitem.h" 0016 #include "dimgitems_p.h" 0017 0018 // Qt includes 0019 0020 #include <QApplication> 0021 #include <QScreen> 0022 0023 // KDE includes 0024 0025 #include <klocalizedstring.h> 0026 0027 // Local includes 0028 0029 #include "iccsettings.h" 0030 #include "loadingcacheinterface.h" 0031 #include "loadingdescription.h" 0032 #include "previewloadthread.h" 0033 #include "previewsettings.h" 0034 0035 namespace Digikam 0036 { 0037 0038 DImgPreviewItem::DImgPreviewItem(QGraphicsItem* const parent) 0039 : GraphicsDImgItem(*new DImgPreviewItemPrivate, parent) 0040 { 0041 Q_D(DImgPreviewItem); 0042 0043 d->init(this); 0044 } 0045 0046 DImgPreviewItem::DImgPreviewItem(DImgPreviewItemPrivate& dd, QGraphicsItem* const parent) 0047 : GraphicsDImgItem(dd, parent) 0048 { 0049 Q_D(DImgPreviewItem); 0050 0051 d->init(this); 0052 } 0053 0054 DImgPreviewItem::DImgPreviewItemPrivate::DImgPreviewItemPrivate() 0055 : state (DImgPreviewItem::NoImage), 0056 exifRotate (false), 0057 previewSize (1024), 0058 previewThread (nullptr), 0059 preloadThread (nullptr) 0060 { 0061 } 0062 0063 void DImgPreviewItem::DImgPreviewItemPrivate::init(DImgPreviewItem* const q) 0064 { 0065 previewThread = new PreviewLoadThread; 0066 preloadThread = new PreviewLoadThread; 0067 preloadThread->setPriority(QThread::LowPriority); 0068 0069 QObject::connect(previewThread, SIGNAL(signalImageLoaded(LoadingDescription,DImg)), 0070 q, SLOT(slotGotImagePreview(LoadingDescription,DImg))); 0071 0072 QObject::connect(preloadThread, SIGNAL(signalImageLoaded(LoadingDescription,DImg)), 0073 q, SLOT(preloadNext())); 0074 0075 // get preview size from screen size, but limit from VGA to WQXGA 0076 0077 previewSize = qBound(640, 0078 qMax(qApp->primaryScreen()->availableGeometry().height(), 0079 qApp->primaryScreen()->availableGeometry().width()), 0080 2560); 0081 0082 LoadingCacheInterface::connectToSignalFileChanged(q, SLOT(slotFileChanged(QString))); 0083 0084 QObject::connect(IccSettings::instance(), SIGNAL(signalICCSettingsChanged(ICCSettingsContainer,ICCSettingsContainer)), 0085 q, SLOT(iccSettingsChanged(ICCSettingsContainer,ICCSettingsContainer))); 0086 } 0087 0088 DImgPreviewItem::~DImgPreviewItem() 0089 { 0090 Q_D(DImgPreviewItem); 0091 0092 delete d->previewThread; 0093 delete d->preloadThread; 0094 } 0095 0096 void DImgPreviewItem::setDisplayingWidget(QWidget* const widget) 0097 { 0098 Q_D(DImgPreviewItem); 0099 0100 d->previewThread->setDisplayingWidget(widget); 0101 } 0102 0103 void DImgPreviewItem::setPreviewSettings(const PreviewSettings& settings) 0104 { 0105 Q_D(DImgPreviewItem); 0106 0107 if (settings == d->previewSettings) 0108 { 0109 return; 0110 } 0111 0112 d->previewSettings = settings; 0113 reload(); 0114 } 0115 0116 QString DImgPreviewItem::path() const 0117 { 0118 Q_D(const DImgPreviewItem); 0119 0120 return d->path; 0121 } 0122 0123 void DImgPreviewItem::setPath(const QString& path, bool rePreview) 0124 { 0125 Q_D(DImgPreviewItem); 0126 0127 if ((path == d->path) && !rePreview) 0128 { 0129 return; 0130 } 0131 0132 d->path = path; 0133 0134 if (d->path.isNull()) 0135 { 0136 d->state = NoImage; 0137 Q_EMIT stateChanged(d->state); 0138 } 0139 else 0140 { 0141 d->state = Loading; 0142 d->previewThread->load(d->path, d->previewSettings, d->previewSize); 0143 0144 Q_EMIT stateChanged(d->state); 0145 } 0146 0147 d->preloadThread->stopLoading(); 0148 } 0149 0150 void DImgPreviewItem::setPreloadPaths(const QStringList& pathsToPreload) 0151 { 0152 Q_D(DImgPreviewItem); 0153 0154 d->pathsToPreload = pathsToPreload; 0155 preloadNext(); 0156 } 0157 0158 static bool approximates(const QSizeF& s1, const QSizeF& s2) 0159 { 0160 if (s1 == s2) 0161 { 0162 return true; 0163 } 0164 0165 double widthRatio = s1.width() / s2.width(); 0166 0167 if ((widthRatio < 0.98) || (widthRatio > 1.02)) 0168 { 0169 return false; 0170 } 0171 0172 double heightRatio = s1.height() / s2.height(); 0173 0174 if ((heightRatio < 0.98) || (heightRatio > 1.02)) 0175 { 0176 return false; 0177 } 0178 0179 return true; 0180 } 0181 0182 QString DImgPreviewItem::userLoadingHint() const 0183 { 0184 Q_D(const DImgPreviewItem); 0185 0186 switch (d->state) 0187 { 0188 case NoImage: 0189 { 0190 return QString(); 0191 } 0192 0193 case Loading: 0194 { 0195 return i18n("Loading..."); 0196 } 0197 0198 case ImageLoaded: 0199 { 0200 if (d->image.detectedFormat() == DImg::RAW) 0201 { 0202 if (d->image.attribute(QLatin1String("fromRawEmbeddedPreview")).toBool()) 0203 { 0204 return i18n("Embedded JPEG Preview"); 0205 } 0206 else if (approximates(d->image.originalSize(), d->image.size())) 0207 { 0208 return QString(); 0209 } 0210 else 0211 { 0212 return i18n("Half Size Raw Preview"); 0213 } 0214 } 0215 else 0216 { 0217 if (approximates(d->image.originalSize(), d->image.size())) 0218 { 0219 //return i18n("Full Size Preview"); 0220 return QString(); 0221 } 0222 else 0223 { 0224 return i18n("Reduced Size Preview"); 0225 } 0226 } 0227 0228 return QString(); // To please compiler without warnings. 0229 } 0230 0231 default: // ImageLoadingFailed: 0232 { 0233 break; 0234 } 0235 } 0236 0237 return i18n("Failed to load image"); 0238 } 0239 0240 void DImgPreviewItem::reload() 0241 { 0242 Q_D(DImgPreviewItem); 0243 0244 QString path = d->path; 0245 d->path.clear(); 0246 setPath(path); 0247 } 0248 0249 DImgPreviewItem::State DImgPreviewItem::state() const 0250 { 0251 Q_D(const DImgPreviewItem); 0252 0253 return d->state; 0254 } 0255 0256 bool DImgPreviewItem::isLoaded() const 0257 { 0258 Q_D(const DImgPreviewItem); 0259 0260 return (d->state == ImageLoaded); 0261 } 0262 0263 void DImgPreviewItem::slotGotImagePreview(const LoadingDescription& description, const DImg& image) 0264 { 0265 Q_D(DImgPreviewItem); 0266 0267 if ((description.filePath != d->path) || description.isThumbnail()) 0268 { 0269 return; 0270 } 0271 0272 if (image.isNull()) 0273 { 0274 setImage(DImg()); 0275 0276 d->state = ImageLoadingFailed; 0277 Q_EMIT stateChanged(d->state); 0278 Q_EMIT loadingFailed(); 0279 } 0280 else 0281 { 0282 setImage(image); 0283 0284 d->state = ImageLoaded; 0285 Q_EMIT stateChanged(d->state); 0286 Q_EMIT loaded(); 0287 } 0288 0289 preloadNext(); 0290 } 0291 0292 void DImgPreviewItem::preloadNext() 0293 { 0294 Q_D(DImgPreviewItem); 0295 0296 if (!isLoaded() || d->pathsToPreload.isEmpty()) 0297 { 0298 return; 0299 } 0300 0301 QString preloadPath = d->pathsToPreload.takeFirst(); 0302 d->preloadThread->load(preloadPath, d->previewSettings, d->previewSize); 0303 } 0304 0305 void DImgPreviewItem::slotFileChanged(const QString& path) 0306 { 0307 Q_D(DImgPreviewItem); 0308 0309 if (d->path == path) 0310 { 0311 reload(); 0312 } 0313 } 0314 0315 void DImgPreviewItem::iccSettingsChanged(const ICCSettingsContainer& current, const ICCSettingsContainer& previous) 0316 { 0317 if ((current.enableCM != previous.enableCM) || 0318 (current.useManagedPreviews != previous.useManagedPreviews) || 0319 (current.monitorProfile != previous.monitorProfile)) 0320 { 0321 reload(); 0322 } 0323 } 0324 0325 } // namespace Digikam 0326 0327 #include "moc_dimgpreviewitem.cpp"