File indexing completed on 2025-01-19 03:53:37
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2005-04-21 0007 * Description : Handling access to one item and associated data - Properties 0008 * 0009 * SPDX-FileCopyrightText: 2005 by Renchi Raju <renchi dot raju at gmail dot com> 0010 * SPDX-FileCopyrightText: 2007-2013 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> 0011 * SPDX-FileCopyrightText: 2009-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> 0012 * SPDX-FileCopyrightText: 2013 by Michael G. Hansen <mike at mghansen dot de> 0013 * 0014 * SPDX-License-Identifier: GPL-2.0-or-later 0015 * 0016 * ============================================================ */ 0017 0018 #include "iteminfo_p.h" 0019 0020 namespace Digikam 0021 { 0022 0023 bool ItemInfo::isNull() const 0024 { 0025 return !m_data; 0026 } 0027 0028 qlonglong ItemInfo::id() const 0029 { 0030 return (m_data ? m_data->id : -1); 0031 } 0032 0033 int ItemInfo::albumId() const 0034 { 0035 return (m_data ? m_data->albumId : -1); 0036 } 0037 0038 int ItemInfo::albumRootId() const 0039 { 0040 return (m_data ? m_data->albumRootId : -1); 0041 } 0042 0043 QString ItemInfo::name() const 0044 { 0045 if (!m_data) 0046 { 0047 return QString(); 0048 } 0049 0050 ItemInfoReadLocker lock; 0051 0052 return m_data->name; 0053 } 0054 0055 qlonglong ItemInfo::fileSize() const 0056 { 0057 if (!m_data) 0058 { 0059 return 0; 0060 } 0061 0062 RETURN_IF_CACHED(fileSize) 0063 0064 QVariantList values = CoreDbAccess().db()->getImagesFields(m_data->id, DatabaseFields::FileSize); 0065 0066 STORE_IN_CACHE_AND_RETURN(fileSize, values.first().toLongLong()) 0067 } 0068 0069 QString ItemInfo::title() const 0070 { 0071 if (!m_data) 0072 { 0073 return QString(); 0074 } 0075 0076 RETURN_IF_CACHED(defaultTitle) 0077 0078 QString title; 0079 { 0080 CoreDbAccess access; 0081 ItemComments comments(access, m_data->id); 0082 title = comments.defaultComment(DatabaseComment::Title); 0083 } 0084 0085 ItemInfoWriteLocker lock; 0086 m_data.data()->defaultTitle = title; 0087 m_data.data()->defaultTitleCached = true; 0088 0089 return m_data->defaultTitle; 0090 } 0091 0092 QString ItemInfo::comment() const 0093 { 0094 if (!m_data) 0095 { 0096 return QString(); 0097 } 0098 0099 RETURN_IF_CACHED(defaultComment) 0100 0101 QString comment; 0102 { 0103 CoreDbAccess access; 0104 ItemComments comments(access, m_data->id); 0105 comment = comments.defaultComment(); 0106 } 0107 0108 ItemInfoWriteLocker lock; 0109 m_data.data()->defaultComment = comment; 0110 m_data.data()->defaultCommentCached = true; 0111 0112 return m_data->defaultComment; 0113 } 0114 0115 double ItemInfo::aspectRatio() const 0116 { 0117 if (!m_data) 0118 { 0119 return 0; 0120 } 0121 0122 RETURN_ASPECTRATIO_IF_IMAGESIZE_CACHED() 0123 0124 return (double)m_data->imageSize.width() / m_data->imageSize.height(); 0125 } 0126 0127 qlonglong ItemInfo::manualOrder() const 0128 { 0129 if (!m_data) 0130 { 0131 return 0; 0132 } 0133 0134 RETURN_IF_CACHED(manualOrder) 0135 0136 QVariantList values = CoreDbAccess().db()->getImagesFields(m_data->id, DatabaseFields::ManualOrder); 0137 0138 STORE_IN_CACHE_AND_RETURN(manualOrder, values.first().toLongLong()) 0139 } 0140 0141 QString ItemInfo::format() const 0142 { 0143 if (!m_data) 0144 { 0145 return QString(); 0146 } 0147 0148 RETURN_IF_CACHED(format) 0149 0150 QVariantList values = CoreDbAccess().db()->getItemInformation(m_data->id, DatabaseFields::Format); 0151 0152 STORE_IN_CACHE_AND_RETURN(format, values.first().toString()) 0153 } 0154 0155 DatabaseItem::Category ItemInfo::category() const 0156 { 0157 if (!m_data) 0158 { 0159 return DatabaseItem::UndefinedCategory; 0160 } 0161 0162 RETURN_IF_CACHED(category) 0163 0164 QVariantList values = CoreDbAccess().db()->getImagesFields(m_data->id, DatabaseFields::Category); 0165 0166 STORE_IN_CACHE_AND_RETURN(category, (DatabaseItem::Category)values.first().toInt()) 0167 } 0168 0169 QDateTime ItemInfo::dateTime() const 0170 { 0171 if (!m_data) 0172 { 0173 return QDateTime(); 0174 } 0175 0176 RETURN_IF_CACHED(creationDate) 0177 0178 QVariantList values = CoreDbAccess().db()->getItemInformation(m_data->id, DatabaseFields::CreationDate); 0179 0180 STORE_IN_CACHE_AND_RETURN(creationDate, values.first().toDateTime()) 0181 } 0182 0183 QDateTime ItemInfo::modDateTime() const 0184 { 0185 if (!m_data) 0186 { 0187 return QDateTime(); 0188 } 0189 0190 RETURN_IF_CACHED(modificationDate) 0191 0192 QVariantList values = CoreDbAccess().db()->getImagesFields(m_data->id, DatabaseFields::ModificationDate); 0193 0194 STORE_IN_CACHE_AND_RETURN(modificationDate, values.first().toDateTime()) 0195 } 0196 0197 QSize ItemInfo::dimensions() const 0198 { 0199 if (!m_data) 0200 { 0201 return QSize(); 0202 } 0203 0204 RETURN_IF_CACHED(imageSize) 0205 0206 QVariantList values = CoreDbAccess().db()->getItemInformation(m_data->id, DatabaseFields::Width | DatabaseFields::Height); 0207 0208 ItemInfoWriteLocker lock; 0209 m_data.data()->imageSizeCached = true; 0210 0211 if (values.size() == 2) 0212 { 0213 m_data.data()->imageSize = QSize(values.at(0).toInt(), values.at(1).toInt()); 0214 } 0215 0216 return m_data->imageSize; 0217 } 0218 0219 int ItemInfo::faceCount() const 0220 { 0221 if (!m_data) 0222 { 0223 return 0; 0224 } 0225 0226 RETURN_IF_CACHED(faceCount); 0227 0228 FaceTagsEditor fte; 0229 int count = fte.databaseFaces(m_data->id).count(); 0230 0231 ItemInfoWriteLocker lock; 0232 m_data.data()->faceCountCached = true; 0233 m_data.data()->faceCount = count; 0234 0235 return m_data->faceCount; 0236 } 0237 0238 int ItemInfo::unconfirmedFaceCount() const 0239 { 0240 if (!m_data) 0241 { 0242 return 0; 0243 } 0244 0245 RETURN_IF_CACHED(unconfirmedFaceCount); 0246 0247 FaceTagsEditor fte; 0248 int count = fte.unconfirmedNameFaceTagsIfaces(m_data->id).count(); 0249 0250 ItemInfoWriteLocker lock; 0251 m_data.data()->unconfirmedFaceCountCached = true; 0252 m_data.data()->unconfirmedFaceCount = count; 0253 0254 return m_data->unconfirmedFaceCount; 0255 } 0256 0257 QMap<QString, QString> ItemInfo::getSuggestedNames() const 0258 { 0259 if (!m_data) 0260 { 0261 return QMap<QString, QString>(); 0262 } 0263 0264 RETURN_IF_CACHED(faceSuggestions); 0265 0266 FaceTagsEditor fte; 0267 QMap<QString, QString> faceSuggestions = fte.getSuggestedNames(m_data->id); 0268 0269 ItemInfoWriteLocker lock; 0270 m_data.data()->faceSuggestionsCached = true; 0271 m_data.data()->faceSuggestions = faceSuggestions; 0272 0273 return m_data->faceSuggestions; 0274 } 0275 0276 int ItemInfo::orientation() const 0277 { 0278 if (!m_data) 0279 { 0280 return 0; // ORIENTATION_UNSPECIFIED 0281 } 0282 0283 RETURN_IF_CACHED(orientation) 0284 0285 QVariantList values = CoreDbAccess().db()->getItemInformation(m_data->id, DatabaseFields::Orientation); 0286 0287 STORE_IN_CACHE_AND_RETURN(orientation, values.first().toInt()); 0288 } 0289 0290 QUrl ItemInfo::fileUrl() const 0291 { 0292 return QUrl::fromLocalFile(filePath()); 0293 } 0294 0295 QString ItemInfo::filePath() const 0296 { 0297 if (!m_data) 0298 { 0299 return QString(); 0300 } 0301 0302 QString albumRoot = CollectionManager::instance()->albumRootPath(m_data->albumRootId); 0303 0304 if (albumRoot.isNull()) 0305 { 0306 return QString(); 0307 } 0308 0309 QString album = ItemInfoStatic::cache()->albumRelativePath(m_data->albumId); 0310 ItemInfoReadLocker lock; 0311 0312 if (album == QLatin1String("/")) 0313 { 0314 return (albumRoot + album + m_data->name); 0315 } 0316 else 0317 { 0318 return (albumRoot + album + QLatin1Char('/') + m_data->name); 0319 } 0320 } 0321 0322 QString ItemInfo::relativePath() const 0323 { 0324 if (!m_data) 0325 { 0326 return QString(); 0327 } 0328 0329 return (ItemInfoStatic::cache()->albumRelativePath(m_data->albumId)); 0330 } 0331 0332 bool ItemInfo::isVisible() const 0333 { 0334 if (!m_data) 0335 { 0336 return false; 0337 } 0338 0339 QVariantList value = CoreDbAccess().db()->getImagesFields(m_data->id, DatabaseFields::Status); 0340 0341 if (!value.isEmpty()) 0342 { 0343 return (value.first().toInt() == DatabaseItem::Visible); 0344 } 0345 0346 return false; 0347 } 0348 0349 bool ItemInfo::isRemoved() const 0350 { 0351 if (!m_data) 0352 { 0353 return true; 0354 } 0355 0356 QVariantList value = CoreDbAccess().db()->getImagesFields(m_data->id, DatabaseFields::Status); 0357 0358 if (!value.isEmpty()) 0359 { 0360 return (value.first().toInt() == DatabaseItem::Trashed) || (value.first().toInt() == DatabaseItem::Obsolete); 0361 } 0362 0363 return false; 0364 } 0365 0366 void ItemInfo::setVisible(bool isVisible) 0367 { 0368 if (!m_data) 0369 { 0370 return; 0371 } 0372 0373 if (m_data->albumId == 0) 0374 { 0375 qCWarning(DIGIKAM_DATABASE_LOG) << "Attempt to make a Removed item visible with ItemInfo::setVisible"; 0376 return; 0377 } 0378 0379 CoreDbAccess().db()->setItemStatus(m_data->id, isVisible ? DatabaseItem::Visible : DatabaseItem::Hidden); 0380 } 0381 0382 void ItemInfo::setManualOrder(qlonglong value) 0383 { 0384 if (!m_data) 0385 { 0386 return; 0387 } 0388 0389 { 0390 ItemInfoWriteLocker lock; 0391 m_data->manualOrder = value; 0392 m_data->manualOrderCached = true; 0393 } 0394 0395 CoreDbAccess().db()->setItemManualOrder(m_data->id, value); 0396 } 0397 0398 void ItemInfo::setOrientation(int value) 0399 { 0400 if (!m_data) 0401 { 0402 return; 0403 } 0404 0405 { 0406 ItemInfoWriteLocker lock; 0407 m_data->orientation = value; 0408 m_data->orientationCached = true; 0409 } 0410 0411 CoreDbAccess().db()->changeItemInformation(m_data->id, QVariantList() << value, DatabaseFields::Orientation); 0412 } 0413 0414 void ItemInfo::setName(const QString& newName) 0415 { 0416 if (!m_data || newName.isEmpty()) 0417 { 0418 return; 0419 } 0420 0421 { 0422 ItemInfoWriteLocker lock; 0423 m_data->name = newName; 0424 ItemInfoStatic::cache()->cacheByName(m_data); 0425 } 0426 0427 CoreDbAccess().db()->renameItem(m_data->id, newName); 0428 } 0429 0430 void ItemInfo::setDateTime(const QDateTime& dateTime) 0431 { 0432 if (!m_data || !dateTime.isValid()) 0433 { 0434 return; 0435 } 0436 0437 { 0438 ItemInfoWriteLocker lock; 0439 m_data->creationDate = dateTime; 0440 m_data->creationDateCached = true; 0441 } 0442 0443 CoreDbAccess().db()->changeItemInformation(m_data->id, QVariantList() << dateTime, DatabaseFields::CreationDate); 0444 } 0445 0446 void ItemInfo::setModDateTime(const QDateTime& dateTime) 0447 { 0448 if (!m_data || !dateTime.isValid()) 0449 { 0450 return; 0451 } 0452 0453 { 0454 ItemInfoWriteLocker lock; 0455 m_data->modificationDate = dateTime; 0456 m_data->modificationDateCached = true; 0457 } 0458 0459 CoreDbAccess().db()->setItemModificationDate(m_data->id, dateTime); 0460 } 0461 0462 ItemInfo::DatabaseFieldsHashRaw ItemInfo::getDatabaseFieldsRaw(const DatabaseFields::Set& requestedSet) const 0463 { 0464 if (!m_data || (!m_data->hasVideoMetadata && !m_data->hasImageMetadata)) 0465 { 0466 return DatabaseFieldsHashRaw(); 0467 } 0468 0469 DatabaseFields::VideoMetadataMinSizeType cachedVideoMetadata; 0470 DatabaseFields::ImageMetadataMinSizeType cachedImageMetadata; 0471 ItemInfo::DatabaseFieldsHashRaw cachedHash; 0472 0473 // consolidate to one ReadLocker. In particular, the shallow copy of the QHash must be done under protection 0474 0475 { 0476 ItemInfoReadLocker lock; 0477 cachedVideoMetadata = m_data->videoMetadataCached; 0478 cachedImageMetadata = m_data->imageMetadataCached; 0479 cachedHash = m_data->databaseFieldsHashRaw; 0480 } 0481 0482 if (requestedSet.hasFieldsFromVideoMetadata() && m_data->hasVideoMetadata) 0483 { 0484 const DatabaseFields::VideoMetadata requestedVideoMetadata = requestedSet.getVideoMetadata(); 0485 const DatabaseFields::VideoMetadata missingVideoMetadata = requestedVideoMetadata & ~cachedVideoMetadata; 0486 0487 if (missingVideoMetadata) 0488 { 0489 const QVariantList fieldValues = CoreDbAccess().db()->getVideoMetadata(m_data->id, missingVideoMetadata); 0490 0491 ItemInfoWriteLocker lock; 0492 0493 if (fieldValues.isEmpty()) 0494 { 0495 m_data.data()->hasVideoMetadata = false; 0496 m_data.data()->databaseFieldsHashRaw.removeAllFields(DatabaseFields::VideoMetadataAll); 0497 m_data.data()->videoMetadataCached = DatabaseFields::VideoMetadataNone; 0498 } 0499 else 0500 { 0501 int fieldsIndex = 0; 0502 0503 for (DatabaseFields::VideoMetadataIteratorSetOnly it(missingVideoMetadata) ; !it.atEnd() ; ++it) 0504 { 0505 const QVariant fieldValue = fieldValues.at(fieldsIndex); 0506 ++fieldsIndex; 0507 0508 m_data.data()->databaseFieldsHashRaw.insertField(*it, fieldValue); 0509 } 0510 0511 m_data.data()->videoMetadataCached |= missingVideoMetadata; 0512 } 0513 0514 // update for return value 0515 0516 cachedHash = m_data->databaseFieldsHashRaw; 0517 } 0518 } 0519 0520 if (requestedSet.hasFieldsFromImageMetadata() && m_data->hasImageMetadata) 0521 { 0522 const DatabaseFields::ImageMetadata requestedImageMetadata = requestedSet.getImageMetadata(); 0523 const DatabaseFields::ImageMetadata missingImageMetadata = requestedImageMetadata & ~cachedImageMetadata; 0524 0525 if (missingImageMetadata) 0526 { 0527 const QVariantList fieldValues = CoreDbAccess().db()->getImageMetadata(m_data->id, missingImageMetadata); 0528 0529 ItemInfoWriteLocker lock; 0530 0531 if (fieldValues.isEmpty()) 0532 { 0533 m_data.data()->hasImageMetadata = false; 0534 m_data.data()->databaseFieldsHashRaw.removeAllFields(DatabaseFields::ImageMetadataAll); 0535 m_data.data()->imageMetadataCached = DatabaseFields::ImageMetadataNone; 0536 } 0537 else 0538 { 0539 int fieldsIndex = 0; 0540 0541 for (DatabaseFields::ImageMetadataIteratorSetOnly it(missingImageMetadata) ; !it.atEnd() ; ++it) 0542 { 0543 const QVariant fieldValue = fieldValues.at(fieldsIndex); 0544 ++fieldsIndex; 0545 0546 m_data.data()->databaseFieldsHashRaw.insertField(*it, fieldValue); 0547 } 0548 0549 m_data.data()->imageMetadataCached |= missingImageMetadata; 0550 } 0551 0552 cachedHash = m_data->databaseFieldsHashRaw; 0553 } 0554 } 0555 0556 // We always return all fields, the caller can just retrieve the ones he needs. 0557 0558 return cachedHash; 0559 } 0560 0561 QVariant ItemInfo::getDatabaseFieldRaw(const DatabaseFields::Set& requestedField) const 0562 { 0563 DatabaseFieldsHashRaw rawHash = getDatabaseFieldsRaw(requestedField); 0564 0565 if (requestedField.hasFieldsFromImageMetadata()) 0566 { 0567 const DatabaseFields::ImageMetadata requestedFieldFlag = requestedField; 0568 const QVariant value = rawHash.value(requestedFieldFlag); 0569 0570 return value; 0571 } 0572 0573 if (requestedField.hasFieldsFromVideoMetadata()) 0574 { 0575 const DatabaseFields::VideoMetadata requestedFieldFlag = requestedField; 0576 const QVariant value = rawHash.value(requestedFieldFlag); 0577 0578 return value; 0579 } 0580 0581 return QVariant(); 0582 } 0583 0584 } // namespace Digikam