File indexing completed on 2025-03-09 03:52:55

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2007-09-19
0007  * Description : Scanning a single item.
0008  *
0009  * SPDX-FileCopyrightText: 2007-2013 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
0010  * SPDX-FileCopyrightText: 2013-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0011  *
0012  * SPDX-License-Identifier: GPL-2.0-or-later
0013  *
0014  * ============================================================ */
0015 
0016 #include "itemscanner_p.h"
0017 
0018 namespace Digikam
0019 {
0020 
0021 ItemScanner::ItemScanner(const QFileInfo& info, const ItemScanInfo& scanInfo)
0022     : d(new Private)
0023 {
0024     d->fileInfo = info;
0025     d->scanInfo = scanInfo;
0026 }
0027 
0028 ItemScanner::ItemScanner(const QFileInfo& info)
0029     : d(new Private)
0030 {
0031     d->fileInfo = info;
0032 }
0033 
0034 ItemScanner::ItemScanner(qlonglong imageid)
0035     : d(new Private)
0036 {
0037     ItemShortInfo shortInfo;
0038     {
0039         CoreDbAccess access;
0040         shortInfo   = access.db()->getItemShortInfo(imageid);
0041         d->scanInfo = access.db()->getItemScanInfo(imageid);
0042     }
0043 
0044     QString albumRootPath = CollectionManager::instance()->albumRootPath(shortInfo.albumRootID);
0045     d->fileInfo           = QFileInfo(CoreDbUrl::fromAlbumAndName(shortInfo.itemName,
0046                                       shortInfo.album, QUrl::fromLocalFile(albumRootPath), shortInfo.albumRootID).fileUrl().toLocalFile());
0047 }
0048 
0049 ItemScanner::~ItemScanner()
0050 {
0051     qCDebug(DIGIKAM_DATABASE_LOG) << "Finishing took" << d->timer.elapsed() << "ms";
0052     delete d;
0053 }
0054 
0055 void ItemScanner::setCategory(DatabaseItem::Category category)
0056 {
0057     // we don't have the necessary information in this class, but in CollectionScanner
0058 
0059     d->scanInfo.category = category;
0060 }
0061 
0062 const ItemScanInfo& ItemScanner::itemScanInfo() const
0063 {
0064     return d->scanInfo;
0065 }
0066 
0067 bool ItemScanner::lessThanForIdentity(const ItemScanInfo& a, const ItemScanInfo& b)
0068 {
0069     if (a.status != b.status)
0070     {
0071         // First: sort by status
0072 
0073         // put UndefinedStatus to back
0074 
0075         if (a.status == DatabaseItem::UndefinedStatus)
0076         {
0077             return false;
0078         }
0079 
0080         // enum values are in the order we want it
0081 
0082         return a.status < b.status;
0083     }
0084     else
0085     {
0086         // Second: sort by modification date, descending
0087         return a.modificationDate > b.modificationDate;
0088     }
0089 }
0090 
0091 bool ItemScanner::hasValidField(const QVariantList& list)
0092 {
0093     for (QVariantList::const_iterator it = list.constBegin() ;
0094          it != list.constEnd() ; ++it)
0095     {
0096         if (!(*it).isNull())
0097         {
0098             return true;
0099         }
0100     }
0101 
0102     return false;
0103 }
0104 
0105 void ItemScanner::sortByProximity(QList<ItemInfo>& list, const ItemInfo& subject)
0106 {
0107     if (!list.isEmpty() && !subject.isNull())
0108     {
0109         std::stable_sort(list.begin(), list.end(), LessThanByProximityToSubject(subject));
0110     }
0111 }
0112 
0113 void ItemScanner::loadFromDisk()
0114 {
0115     if (d->loadedFromDisk)
0116     {
0117         return;
0118     }
0119 
0120     d->loadedFromDisk = true;
0121     d->metadata->registerMetadataSettings();
0122     d->hasMetadata    = d->metadata->load(d->fileInfo.filePath());
0123 
0124     if (d->scanInfo.category == DatabaseItem::Image)
0125     {
0126         d->hasImage = d->img.loadItemInfo(d->fileInfo.filePath(), false, false, false, false);
0127     }
0128     else
0129     {
0130         d->hasImage = false;
0131     }
0132 
0133     MetaEngineSettingsContainer settings = MetaEngineSettings::instance()->settings();
0134     QDateTime modificationDate           = d->fileInfo.lastModified();
0135     modificationDate.setTimeSpec(Qt::UTC);
0136 
0137     if (settings.useXMPSidecar4Reading              &&
0138         DMetadata::hasSidecar(d->fileInfo.filePath()))
0139     {
0140         QString filePath      = DMetadata::sidecarPath(d->fileInfo.filePath());
0141         QDateTime sidecarDate = QFileInfo(filePath).lastModified();
0142         sidecarDate.setTimeSpec(Qt::UTC);
0143 
0144         if (sidecarDate > modificationDate)
0145         {
0146             modificationDate = sidecarDate;
0147         }
0148     }
0149 
0150     d->scanInfo.itemName         = d->fileInfo.fileName();
0151     d->scanInfo.fileSize         = d->fileInfo.size();
0152     d->scanInfo.modificationDate = modificationDate;
0153 
0154     // category is set by setCategory
0155     // NOTE: call uniqueHash after loading the image above, else it will fail
0156 
0157     d->scanInfo.uniqueHash       = uniqueHash();
0158 
0159     // faster than loading twice from disk
0160 
0161     if (d->hasMetadata)
0162     {
0163         d->img.setMetadata(d->metadata->data());
0164     }
0165 }
0166 
0167 QString ItemScanner::formatToString(const QString& format)
0168 {
0169     // image -------------------------------------------------------------------
0170 
0171     if      (format == QLatin1String("JPG"))
0172     {
0173         return QLatin1String("JPEG");
0174     }
0175     else if (format == QLatin1String("PNG"))
0176     {
0177         return format;
0178     }
0179     else if (format == QLatin1String("TIFF"))
0180     {
0181         return format;
0182     }
0183     else if (format == QLatin1String("PPM"))
0184     {
0185         return format;
0186     }
0187     else if ((format == QLatin1String("JP2")) || (format == QLatin1String("JP2k")) || (format == QLatin1String("JP2K")))
0188     {
0189         return QLatin1String("JPEG 2000");
0190     }
0191     else if (format.startsWith(QLatin1String("RAW-")))
0192     {
0193         return i18nc("RAW image file (), the parentheses contain the file suffix, like MRW",
0194                      "RAW image file (%1)",
0195                      format.mid(4));
0196     }
0197 
0198     // video -------------------------------------------------------------------
0199 
0200     else if (format == QLatin1String("MPEG"))
0201     {
0202         return format;
0203     }
0204     else if (format == QLatin1String("AVI"))
0205     {
0206         return format;
0207     }
0208     else if (format == QLatin1String("MOV"))
0209     {
0210         return QLatin1String("Quicktime");
0211     }
0212     else if (format == QLatin1String("WMF"))
0213     {
0214         return QLatin1String("Windows MetaFile");
0215     }
0216     else if (format == QLatin1String("WMV"))
0217     {
0218         return QLatin1String("Windows Media Video");
0219     }
0220     else if (format == QLatin1String("MP4"))
0221     {
0222         return QLatin1String("MPEG-4");
0223     }
0224     else if (format == QLatin1String("3GP"))
0225     {
0226         return QLatin1String("3GPP");
0227     }
0228 
0229     // audio -------------------------------------------------------------------
0230 
0231     else if (format == QLatin1String("OGG"))
0232     {
0233         return QLatin1String("Ogg");
0234     }
0235     else if (format == QLatin1String("MP3"))
0236     {
0237         return format;
0238     }
0239     else if (format == QLatin1String("WMA"))
0240     {
0241         return QLatin1String("Windows Media Audio");
0242     }
0243     else if (format == QLatin1String("WAV"))
0244     {
0245         return QLatin1String("WAVE");
0246     }
0247     else
0248     {
0249         return format;
0250     }
0251 }
0252 
0253 } // namespace Digikam