File indexing completed on 2025-01-05 03:56:24
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2006-02-23 0007 * Description : item metadata interface - labels helpers. 0008 * 0009 * SPDX-FileCopyrightText: 2006-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> 0010 * SPDX-FileCopyrightText: 2006-2013 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> 0011 * SPDX-FileCopyrightText: 2011 by Leif Huhn <leif at dkstat dot com> 0012 * 0013 * SPDX-License-Identifier: GPL-2.0-or-later 0014 * 0015 * ============================================================ */ 0016 0017 #include "dmetadata.h" 0018 0019 // Qt includes 0020 0021 #include <QLocale> 0022 0023 // Local includes 0024 0025 #include "metaenginesettings.h" 0026 #include "digikam_version.h" 0027 #include "digikam_globals.h" 0028 #include "digikam_debug.h" 0029 0030 namespace Digikam 0031 { 0032 0033 int DMetadata::getItemPickLabel() const 0034 { 0035 if (hasXmp()) 0036 { 0037 QString value = getXmpTagString("Xmp.digiKam.PickLabel", false); 0038 0039 if (!value.isEmpty()) 0040 { 0041 bool ok = false; 0042 long pickId = value.toLong(&ok); 0043 0044 if (ok && (pickId >= NoPickLabel) && (pickId <= AcceptedLabel)) 0045 { 0046 return pickId; 0047 } 0048 } 0049 } 0050 0051 return -1; 0052 } 0053 0054 int DMetadata::getItemColorLabel(const DMetadataSettingsContainer& settings) const 0055 { 0056 bool xmpSupported = hasXmp(); 0057 bool exivSupported = hasExif(); 0058 0059 Q_FOREACH (const NamespaceEntry& entry, settings.getReadMapping(NamespaceEntry::DM_COLORLABEL_CONTAINER())) 0060 { 0061 if (entry.isDisabled) 0062 { 0063 continue; 0064 } 0065 0066 const std::string myStr = entry.namespaceName.toStdString(); 0067 const char* nameSpace = myStr.data(); 0068 QString value; 0069 0070 switch (entry.subspace) 0071 { 0072 case NamespaceEntry::XMP: 0073 { 0074 if (xmpSupported) 0075 { 0076 value = getXmpTagString(nameSpace, false); 0077 } 0078 0079 break; 0080 } 0081 0082 case NamespaceEntry::IPTC: 0083 { 0084 break; 0085 } 0086 0087 case NamespaceEntry::EXIF: 0088 { 0089 if (exivSupported) 0090 { 0091 value = getExifTagString(nameSpace, false); 0092 } 0093 0094 break; 0095 } 0096 0097 default: 0098 { 0099 break; 0100 } 0101 } 0102 0103 if (value.isEmpty()) 0104 { 0105 continue; 0106 } 0107 0108 bool ok = false; 0109 long colorId = value.toLong(&ok); 0110 0111 if (ok && (colorId >= NoColorLabel) && (colorId <= WhiteLabel)) 0112 { 0113 return colorId; 0114 } 0115 0116 // LightRoom use this tag to store color name as string. 0117 // Values are limited : see bug #358193. 0118 0119 if (value == QLatin1String("Blue")) 0120 { 0121 return BlueLabel; 0122 } 0123 else if (value == QLatin1String("Green")) 0124 { 0125 return GreenLabel; 0126 } 0127 else if (value == QLatin1String("Red")) 0128 { 0129 return RedLabel; 0130 } 0131 else if (value == QLatin1String("Yellow")) 0132 { 0133 return YellowLabel; 0134 } 0135 else if (value == QLatin1String("Purple")) 0136 { 0137 return MagentaLabel; 0138 } 0139 } 0140 0141 return -1; 0142 } 0143 0144 int DMetadata::getItemRating(const DMetadataSettingsContainer& settings) const 0145 { 0146 long rating = -1; 0147 bool xmpSupported = hasXmp(); 0148 bool iptcSupported = hasIptc(); 0149 bool exivSupported = hasExif(); 0150 0151 Q_FOREACH (const NamespaceEntry& entry, settings.getReadMapping(NamespaceEntry::DM_RATING_CONTAINER())) 0152 { 0153 if (entry.isDisabled) 0154 { 0155 continue; 0156 } 0157 0158 const std::string myStr = entry.namespaceName.toStdString(); 0159 const char* nameSpace = myStr.data(); 0160 QString value; 0161 0162 switch (entry.subspace) 0163 { 0164 case NamespaceEntry::XMP: 0165 { 0166 if (xmpSupported) 0167 { 0168 value = getXmpTagString(nameSpace, false); 0169 } 0170 0171 break; 0172 } 0173 0174 case NamespaceEntry::IPTC: 0175 { 0176 if (iptcSupported) 0177 { 0178 value = QString::fromUtf8(getIptcTagData(nameSpace)); 0179 } 0180 0181 break; 0182 } 0183 0184 case NamespaceEntry::EXIF: 0185 { 0186 if (exivSupported) 0187 { 0188 if (!getExifTagLong(nameSpace, rating)) 0189 { 0190 continue; 0191 } 0192 } 0193 0194 break; 0195 } 0196 0197 default: 0198 { 0199 break; 0200 } 0201 } 0202 0203 if (!value.isEmpty()) 0204 { 0205 bool ok = false; 0206 rating = value.toLong(&ok); 0207 0208 if (!ok) 0209 { 0210 return -1; 0211 } 0212 } 0213 0214 int index = entry.convertRatio.indexOf(rating); 0215 0216 // Exact value was not found,but rating is in range, 0217 // so we try to approximate it 0218 0219 if ((index == -1) && 0220 (rating > entry.convertRatio.first()) && 0221 (rating < entry.convertRatio.last())) 0222 { 0223 for (int i = 0 ; i < entry.convertRatio.size() ; ++i) 0224 { 0225 if (rating > entry.convertRatio.at(i)) 0226 { 0227 index = i; 0228 } 0229 } 0230 } 0231 0232 if (index != -1) 0233 { 0234 return index; 0235 } 0236 } 0237 0238 return -1; 0239 } 0240 0241 bool DMetadata::setItemPickLabel(int pickId) const 0242 { 0243 if ((pickId < NoPickLabel) || (pickId > AcceptedLabel)) 0244 { 0245 qCDebug(DIGIKAM_METAENGINE_LOG) << "Pick Label value to write is out of range!"; 0246 return false; 0247 } 0248 /* 0249 qCDebug(DIGIKAM_METAENGINE_LOG) << getFilePath() << " ==> Pick Label: " << pickId; 0250 */ 0251 if (supportXmp()) 0252 { 0253 if (!setXmpTagString("Xmp.digiKam.PickLabel", QString::number(pickId))) 0254 { 0255 return false; 0256 } 0257 } 0258 0259 return true; 0260 } 0261 0262 bool DMetadata::setItemColorLabel(int colorId, const DMetadataSettingsContainer& settings) const 0263 { 0264 if ((colorId < NoColorLabel) || (colorId > WhiteLabel)) 0265 { 0266 qCDebug(DIGIKAM_METAENGINE_LOG) << "Color Label value to write is out of range!"; 0267 0268 return false; 0269 } 0270 /* 0271 qCDebug(DIGIKAM_METAENGINE_LOG) << getFilePath() << " ==> Color Label: " << colorId; 0272 */ 0273 QList<NamespaceEntry> toWrite = settings.getReadMapping(NamespaceEntry::DM_COLORLABEL_CONTAINER()); 0274 0275 if (!settings.unifyReadWrite()) 0276 { 0277 toWrite = settings.getWriteMapping(NamespaceEntry::DM_COLORLABEL_CONTAINER()); 0278 } 0279 0280 for (const NamespaceEntry& entry : qAsConst(toWrite)) 0281 { 0282 if (entry.isDisabled) 0283 { 0284 continue; 0285 } 0286 0287 const std::string myStr = entry.namespaceName.toStdString(); 0288 const char* nameSpace = myStr.data(); 0289 0290 switch (entry.subspace) 0291 { 0292 case NamespaceEntry::XMP: 0293 { 0294 if (!supportXmp()) 0295 { 0296 continue; 0297 } 0298 0299 if (QLatin1String(nameSpace) == QLatin1String("Xmp.xmp.Label")) 0300 { 0301 // LightRoom use this XMP tags to store Color Labels name 0302 // Values are limited : see bug #358193. 0303 0304 QString LRLabel; 0305 0306 switch (colorId) 0307 { 0308 case BlueLabel: 0309 { 0310 LRLabel = QLatin1String("Blue"); 0311 break; 0312 } 0313 0314 case GreenLabel: 0315 { 0316 LRLabel = QLatin1String("Green"); 0317 break; 0318 } 0319 0320 case RedLabel: 0321 { 0322 LRLabel = QLatin1String("Red"); 0323 break; 0324 } 0325 0326 case YellowLabel: 0327 { 0328 LRLabel = QLatin1String("Yellow"); 0329 break; 0330 } 0331 0332 case MagentaLabel: 0333 { 0334 LRLabel = QLatin1String("Purple"); 0335 break; 0336 } 0337 } 0338 0339 if (!LRLabel.isEmpty()) 0340 { 0341 if (!setXmpTagString(nameSpace, LRLabel)) 0342 { 0343 return false; 0344 } 0345 } 0346 else 0347 { 0348 removeXmpTag(nameSpace); 0349 } 0350 } 0351 else 0352 { 0353 if (!setXmpTagString(nameSpace, QString::number(colorId))) 0354 { 0355 return false; 0356 } 0357 } 0358 0359 break; 0360 } 0361 0362 case NamespaceEntry::IPTC: 0363 { 0364 break; 0365 } 0366 0367 case NamespaceEntry::EXIF: 0368 { 0369 if (!setExifTagString(nameSpace, QString::number(colorId))) 0370 { 0371 return false; 0372 } 0373 0374 break; 0375 } 0376 0377 default: 0378 { 0379 break; 0380 } 0381 } 0382 } 0383 0384 return true; 0385 } 0386 0387 bool DMetadata::setItemRating(int rating, const DMetadataSettingsContainer& settings) const 0388 { 0389 if ((rating < RatingMin) || (rating > RatingMax)) 0390 { 0391 qCDebug(DIGIKAM_METAENGINE_LOG) << "Rating value to write is out of range!"; 0392 return false; 0393 } 0394 /* 0395 qCDebug(DIGIKAM_METAENGINE_LOG) << getFilePath() << " ==> Rating:" << rating; 0396 */ 0397 QList<NamespaceEntry> toWrite = settings.getReadMapping(NamespaceEntry::DM_RATING_CONTAINER()); 0398 0399 if (!settings.unifyReadWrite()) 0400 { 0401 toWrite = settings.getWriteMapping(NamespaceEntry::DM_RATING_CONTAINER()); 0402 } 0403 0404 for (const NamespaceEntry& entry : qAsConst(toWrite)) 0405 { 0406 if (entry.isDisabled) 0407 { 0408 continue; 0409 } 0410 0411 const std::string myStr = entry.namespaceName.toStdString(); 0412 const char* nameSpace = myStr.data(); 0413 0414 switch (entry.subspace) 0415 { 0416 case NamespaceEntry::XMP: 0417 { 0418 if (!supportXmp()) 0419 { 0420 continue; 0421 } 0422 0423 if (!setXmpTagString(nameSpace, QString::number(entry.convertRatio.at(rating)))) 0424 { 0425 qCDebug(DIGIKAM_METAENGINE_LOG) << "Setting rating failed" << nameSpace; 0426 return false; 0427 } 0428 0429 break; 0430 } 0431 0432 case NamespaceEntry::IPTC: 0433 { 0434 if (!setIptcTagString(nameSpace, QString::number(entry.convertRatio.at(rating)))) 0435 { 0436 qCDebug(DIGIKAM_METAENGINE_LOG) << "Setting rating failed" << nameSpace; 0437 return false; 0438 } 0439 0440 break; 0441 } 0442 0443 case NamespaceEntry::EXIF: 0444 { 0445 if (!setExifTagLong(nameSpace, entry.convertRatio.at(rating))) 0446 { 0447 qCDebug(DIGIKAM_METAENGINE_LOG) << "Setting rating failed" << nameSpace; 0448 return false; 0449 } 0450 0451 break; 0452 } 0453 0454 default: 0455 { 0456 break; 0457 } 0458 } 0459 } 0460 0461 return true; 0462 } 0463 0464 } // namespace Digikam