File indexing completed on 2024-04-21 15:22:26
0001 /* 0002 SPDX-FileCopyrightText: 2006-2015 Gilles Caulier <caulier dot gilles at gmail dot com> 0003 SPDX-FileCopyrightText: 2006-2012 Marcel Wiesweg <marcel dot wiesweg at gmx dot de> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 // Local includes 0009 0010 #include "kexiv2.h" 0011 #include "kexiv2_p.h" 0012 #include "libkexiv2_debug.h" 0013 0014 namespace KExiv2Iface 0015 { 0016 0017 bool KExiv2::canWriteIptc(const QString& filePath) 0018 { 0019 try 0020 { 0021 #if EXIV2_TEST_VERSION(0,28,0) 0022 Exiv2::Image::UniquePtr image = 0023 #else 0024 Exiv2::Image::AutoPtr image = 0025 #endif 0026 Exiv2::ImageFactory::open((const char*) 0027 (QFile::encodeName(filePath).constData())); 0028 0029 Exiv2::AccessMode mode = image->checkMode(Exiv2::mdIptc); 0030 return (mode == Exiv2::amWrite || mode == Exiv2::amReadWrite); 0031 } 0032 catch(Exiv2::Error& e) 0033 { 0034 std::string s(e.what()); 0035 qCCritical(LIBKEXIV2_LOG) << "Cannot check Iptc access mode using Exiv2 (Error #" 0036 #if EXIV2_TEST_VERSION(0,28,0) 0037 << Exiv2::Error(e.code()).what() 0038 #else 0039 << e.code() << ": " << s.c_str() 0040 #endif 0041 << ")"; 0042 } 0043 catch(...) 0044 { 0045 qCCritical(LIBKEXIV2_LOG) << "Default exception from Exiv2"; 0046 } 0047 0048 return false; 0049 } 0050 0051 bool KExiv2::hasIptc() const 0052 { 0053 return !d->iptcMetadata().empty(); 0054 } 0055 0056 bool KExiv2::clearIptc() const 0057 { 0058 try 0059 { 0060 d->iptcMetadata().clear(); 0061 return true; 0062 } 0063 catch(Exiv2::Error& e) 0064 { 0065 d->printExiv2ExceptionError(QString::fromLatin1("Cannot clear Iptc data using Exiv2 "), e); 0066 } 0067 catch(...) 0068 { 0069 qCCritical(LIBKEXIV2_LOG) << "Default exception from Exiv2"; 0070 } 0071 0072 return false; 0073 } 0074 0075 QByteArray KExiv2::getIptc(bool addIrbHeader) const 0076 { 0077 try 0078 { 0079 if (!d->iptcMetadata().empty()) 0080 { 0081 Exiv2::IptcData& iptc = d->iptcMetadata(); 0082 Exiv2::DataBuf c2; 0083 0084 if (addIrbHeader) 0085 { 0086 c2 = Exiv2::Photoshop::setIptcIrb(nullptr, 0, iptc); 0087 } 0088 else 0089 { 0090 c2 = Exiv2::IptcParser::encode(d->iptcMetadata()); 0091 } 0092 0093 #if EXIV2_TEST_VERSION(0,28,0) 0094 QByteArray data((const char*)c2.c_data(), c2.size()); 0095 #else 0096 QByteArray data((const char*)c2.pData_, c2.size_); 0097 #endif 0098 return data; 0099 0100 } 0101 } 0102 catch(Exiv2::Error& e) 0103 { 0104 if (!d->filePath.isEmpty()) 0105 { 0106 qCCritical(LIBKEXIV2_LOG) << "From file " << d->filePath.toLatin1().constData(); 0107 } 0108 0109 d->printExiv2ExceptionError(QString::fromLatin1("Cannot get Iptc data using Exiv2 "), e); 0110 } 0111 catch(...) 0112 { 0113 qCCritical(LIBKEXIV2_LOG) << "Default exception from Exiv2"; 0114 } 0115 0116 return QByteArray(); 0117 } 0118 0119 bool KExiv2::setIptc(const QByteArray& data) const 0120 { 0121 try 0122 { 0123 if (!data.isEmpty()) 0124 { 0125 Exiv2::IptcParser::decode(d->iptcMetadata(), (const Exiv2::byte*)data.data(), data.size()); 0126 return (!d->iptcMetadata().empty()); 0127 } 0128 } 0129 catch(Exiv2::Error& e) 0130 { 0131 if (!d->filePath.isEmpty()) 0132 { 0133 qCCritical(LIBKEXIV2_LOG) << "From file " << d->filePath.toLatin1().constData(); 0134 } 0135 0136 d->printExiv2ExceptionError(QString::fromLatin1("Cannot set Iptc data using Exiv2 "), e); 0137 } 0138 catch(...) 0139 { 0140 qCCritical(LIBKEXIV2_LOG) << "Default exception from Exiv2"; 0141 } 0142 0143 return false; 0144 } 0145 0146 KExiv2::MetaDataMap KExiv2::getIptcTagsDataList(const QStringList& iptcKeysFilter, bool invertSelection) const 0147 { 0148 if (d->iptcMetadata().empty()) 0149 return MetaDataMap(); 0150 0151 try 0152 { 0153 Exiv2::IptcData iptcData = d->iptcMetadata(); 0154 iptcData.sortByKey(); 0155 0156 QString ifDItemName; 0157 MetaDataMap metaDataMap; 0158 0159 for (Exiv2::IptcData::iterator md = iptcData.begin(); md != iptcData.end(); ++md) 0160 { 0161 QString key = QString::fromLocal8Bit(md->key().c_str()); 0162 0163 // Decode the tag value with a user friendly output. 0164 std::ostringstream os; 0165 os << *md; 0166 0167 QString value; 0168 0169 if (key == QString::fromLatin1("Iptc.Envelope.CharacterSet")) 0170 { 0171 value = QString::fromLatin1(iptcData.detectCharset()); 0172 } 0173 else 0174 { 0175 value = QString::fromUtf8(os.str().c_str()); 0176 } 0177 0178 // To make a string just on one line. 0179 value.replace(QString::fromLatin1("\n"), QString::fromLatin1(" ")); 0180 0181 // Some Iptc key are redondancy. check if already one exist... 0182 MetaDataMap::iterator it = metaDataMap.find(key); 0183 0184 // We apply a filter to get only the Iptc tags that we need. 0185 0186 if (!iptcKeysFilter.isEmpty()) 0187 { 0188 if (!invertSelection) 0189 { 0190 if (iptcKeysFilter.contains(key.section(QString::fromLatin1("."), 1, 1))) 0191 { 0192 if (it == metaDataMap.end()) 0193 { 0194 metaDataMap.insert(key, value); 0195 } 0196 else 0197 { 0198 QString v = *it; 0199 v.append(QString::fromLatin1(", ")); 0200 v.append(value); 0201 metaDataMap.insert(key, v); 0202 } 0203 } 0204 } 0205 else 0206 { 0207 if (!iptcKeysFilter.contains(key.section(QString::fromLatin1("."), 1, 1))) 0208 { 0209 if (it == metaDataMap.end()) 0210 { 0211 metaDataMap.insert(key, value); 0212 } 0213 else 0214 { 0215 QString v = *it; 0216 v.append(QString::fromLatin1(", ")); 0217 v.append(value); 0218 metaDataMap.insert(key, v); 0219 } 0220 } 0221 } 0222 } 0223 else // else no filter at all. 0224 { 0225 if (it == metaDataMap.end()) 0226 { 0227 metaDataMap.insert(key, value); 0228 } 0229 else 0230 { 0231 QString v = *it; 0232 v.append(QString::fromLatin1(", ")); 0233 v.append(value); 0234 metaDataMap.insert(key, v); 0235 } 0236 } 0237 0238 } 0239 0240 return metaDataMap; 0241 } 0242 catch (Exiv2::Error& e) 0243 { 0244 d->printExiv2ExceptionError(QString::fromLatin1("Cannot parse Iptc metadata using Exiv2 "), e); 0245 } 0246 catch(...) 0247 { 0248 qCCritical(LIBKEXIV2_LOG) << "Default exception from Exiv2"; 0249 } 0250 0251 return MetaDataMap(); 0252 } 0253 0254 QString KExiv2::getIptcTagTitle(const char* iptcTagName) 0255 { 0256 try 0257 { 0258 std::string iptckey(iptcTagName); 0259 Exiv2::IptcKey ik(iptckey); 0260 return QString::fromLocal8Bit( Exiv2::IptcDataSets::dataSetTitle(ik.tag(), ik.record()) ); 0261 } 0262 catch (Exiv2::Error& e) 0263 { 0264 d->printExiv2ExceptionError(QString::fromLatin1("Cannot get metadata tag title using Exiv2 "), e); 0265 } 0266 catch(...) 0267 { 0268 qCCritical(LIBKEXIV2_LOG) << "Default exception from Exiv2"; 0269 } 0270 0271 return QString(); 0272 } 0273 0274 QString KExiv2::getIptcTagDescription(const char* iptcTagName) 0275 { 0276 try 0277 { 0278 std::string iptckey(iptcTagName); 0279 Exiv2::IptcKey ik(iptckey); 0280 return QString::fromLocal8Bit( Exiv2::IptcDataSets::dataSetDesc(ik.tag(), ik.record()) ); 0281 } 0282 catch (Exiv2::Error& e) 0283 { 0284 d->printExiv2ExceptionError(QString::fromLatin1("Cannot get metadata tag description using Exiv2 "), e); 0285 } 0286 catch(...) 0287 { 0288 qCCritical(LIBKEXIV2_LOG) << "Default exception from Exiv2"; 0289 } 0290 0291 return QString(); 0292 } 0293 0294 bool KExiv2::removeIptcTag(const char* iptcTagName, bool setProgramName) const 0295 { 0296 if (!setProgramId(setProgramName)) 0297 return false; 0298 0299 try 0300 { 0301 Exiv2::IptcData::iterator it = d->iptcMetadata().begin(); 0302 int i = 0; 0303 0304 while(it != d->iptcMetadata().end()) 0305 { 0306 QString key = QString::fromLocal8Bit(it->key().c_str()); 0307 0308 if (key == QString::fromLatin1(iptcTagName)) 0309 { 0310 it = d->iptcMetadata().erase(it); 0311 ++i; 0312 } 0313 else 0314 { 0315 ++it; 0316 } 0317 }; 0318 0319 if (i > 0) 0320 return true; 0321 } 0322 catch(Exiv2::Error& e) 0323 { 0324 d->printExiv2ExceptionError(QString::fromLatin1("Cannot remove Iptc tag using Exiv2 "), e); 0325 } 0326 catch(...) 0327 { 0328 qCCritical(LIBKEXIV2_LOG) << "Default exception from Exiv2"; 0329 } 0330 0331 return false; 0332 } 0333 0334 bool KExiv2::setIptcTagData(const char* iptcTagName, const QByteArray& data, bool setProgramName) const 0335 { 0336 if (data.isEmpty()) 0337 return false; 0338 0339 if (!setProgramId(setProgramName)) 0340 return false; 0341 0342 try 0343 { 0344 Exiv2::DataValue val((Exiv2::byte *)data.data(), data.size()); 0345 d->iptcMetadata()[iptcTagName] = val; 0346 return true; 0347 } 0348 catch(Exiv2::Error& e) 0349 { 0350 d->printExiv2ExceptionError(QString::fromLatin1("Cannot set Iptc tag data into image using Exiv2 "), e); 0351 } 0352 catch(...) 0353 { 0354 qCCritical(LIBKEXIV2_LOG) << "Default exception from Exiv2"; 0355 } 0356 0357 return false; 0358 } 0359 0360 QByteArray KExiv2::getIptcTagData(const char* iptcTagName) const 0361 { 0362 try 0363 { 0364 Exiv2::IptcKey iptcKey(iptcTagName); 0365 Exiv2::IptcData iptcData(d->iptcMetadata()); 0366 Exiv2::IptcData::iterator it = iptcData.findKey(iptcKey); 0367 0368 if (it != iptcData.end()) 0369 { 0370 char* const s = new char[(*it).size()]; 0371 (*it).copy((Exiv2::byte*)s, Exiv2::bigEndian); 0372 QByteArray data(s, (*it).size()); 0373 delete [] s; 0374 return data; 0375 } 0376 } 0377 catch(Exiv2::Error& e) 0378 { 0379 d->printExiv2ExceptionError(QString::fromLatin1("Cannot find Iptc key '%1' into image using Exiv2 ").arg(QString::fromLatin1(iptcTagName)), e); 0380 } 0381 catch(...) 0382 { 0383 qCCritical(LIBKEXIV2_LOG) << "Default exception from Exiv2"; 0384 } 0385 0386 return QByteArray(); 0387 } 0388 0389 QString KExiv2::getIptcTagString(const char* iptcTagName, bool escapeCR) const 0390 { 0391 try 0392 { 0393 Exiv2::IptcKey iptcKey(iptcTagName); 0394 Exiv2::IptcData iptcData(d->iptcMetadata()); 0395 Exiv2::IptcData::iterator it = iptcData.findKey(iptcKey); 0396 0397 if (it != iptcData.end()) 0398 { 0399 std::ostringstream os; 0400 os << *it; 0401 QString tagValue(QString::fromLatin1(os.str().c_str())); 0402 0403 if (escapeCR) 0404 tagValue.replace(QString::fromLatin1("\n"), QString::fromLatin1(" ")); 0405 0406 return tagValue; 0407 } 0408 } 0409 catch(Exiv2::Error& e) 0410 { 0411 d->printExiv2ExceptionError(QString::fromLatin1("Cannot find Iptc key '%1' into image using Exiv2 ").arg(QString::fromLatin1(iptcTagName)), e); 0412 } 0413 catch(...) 0414 { 0415 qCCritical(LIBKEXIV2_LOG) << "Default exception from Exiv2"; 0416 } 0417 0418 return QString(); 0419 } 0420 0421 bool KExiv2::setIptcTagString(const char* iptcTagName, const QString& value, bool setProgramName) const 0422 { 0423 if (!setProgramId(setProgramName)) 0424 return false; 0425 0426 try 0427 { 0428 d->iptcMetadata()[iptcTagName] = std::string(value.toUtf8().constData()); 0429 0430 // Make sure we have set the charset to UTF-8 0431 d->iptcMetadata()["Iptc.Envelope.CharacterSet"] = "\33%G"; 0432 return true; 0433 } 0434 catch(Exiv2::Error& e) 0435 { 0436 d->printExiv2ExceptionError(QString::fromLatin1("Cannot set Iptc tag string into image using Exiv2 "), e); 0437 } 0438 catch(...) 0439 { 0440 qCCritical(LIBKEXIV2_LOG) << "Default exception from Exiv2"; 0441 } 0442 0443 return false; 0444 } 0445 0446 QStringList KExiv2::getIptcTagsStringList(const char* iptcTagName, bool escapeCR) const 0447 { 0448 try 0449 { 0450 if (!d->iptcMetadata().empty()) 0451 { 0452 QStringList values; 0453 Exiv2::IptcData iptcData(d->iptcMetadata()); 0454 0455 for (Exiv2::IptcData::iterator it = iptcData.begin(); it != iptcData.end(); ++it) 0456 { 0457 QString key = QString::fromLocal8Bit(it->key().c_str()); 0458 0459 if (key == QString::fromLatin1(iptcTagName)) 0460 { 0461 QString tagValue = QString::fromUtf8(it->toString().c_str()); 0462 0463 if (escapeCR) 0464 tagValue.replace(QString::fromLatin1("\n"), QString::fromLatin1(" ")); 0465 0466 values.append(tagValue); 0467 } 0468 } 0469 0470 return values; 0471 } 0472 } 0473 catch(Exiv2::Error& e) 0474 { 0475 d->printExiv2ExceptionError(QString::fromLatin1("Cannot find Iptc key '%1' into image using Exiv2 ").arg(QString::fromLatin1(iptcTagName)), e); 0476 } 0477 catch(...) 0478 { 0479 qCCritical(LIBKEXIV2_LOG) << "Default exception from Exiv2"; 0480 } 0481 0482 return QStringList(); 0483 } 0484 0485 bool KExiv2::setIptcTagsStringList(const char* iptcTagName, int maxSize, 0486 const QStringList& oldValues, const QStringList& newValues, 0487 bool setProgramName) const 0488 { 0489 if (!setProgramId(setProgramName)) 0490 return false; 0491 0492 try 0493 { 0494 QStringList oldvals = oldValues; 0495 QStringList newvals = newValues; 0496 0497 qCDebug(LIBKEXIV2_LOG) << d->filePath.toLatin1().constData() << " : " << iptcTagName 0498 << " => " << newvals.join(QString::fromLatin1(",")).toLatin1().constData(); 0499 0500 // Remove all old values. 0501 Exiv2::IptcData iptcData(d->iptcMetadata()); 0502 Exiv2::IptcData::iterator it = iptcData.begin(); 0503 0504 while(it != iptcData.end()) 0505 { 0506 QString key = QString::fromLocal8Bit(it->key().c_str()); 0507 QString val = QString::fromUtf8(it->toString().c_str()); 0508 0509 // Also remove new values to avoid duplicates. They will be added again below. 0510 if ( key == QString::fromLatin1(iptcTagName) && 0511 (oldvals.contains(val) || newvals.contains(val)) 0512 ) 0513 it = iptcData.erase(it); 0514 else 0515 ++it; 0516 }; 0517 0518 // Add new values. 0519 0520 Exiv2::IptcKey iptcTag(iptcTagName); 0521 0522 for (QStringList::iterator it = newvals.begin(); it != newvals.end(); ++it) 0523 { 0524 QString key = *it; 0525 key.truncate(maxSize); 0526 0527 #if EXIV2_TEST_VERSION(0,28,0) 0528 Exiv2::Value::UniquePtr val = Exiv2::Value::create(Exiv2::string); 0529 #else 0530 Exiv2::Value::AutoPtr val = Exiv2::Value::create(Exiv2::string); 0531 #endif 0532 val->read(key.toUtf8().constData()); 0533 iptcData.add(iptcTag, val.get()); 0534 } 0535 0536 d->iptcMetadata() = iptcData; 0537 0538 // Make sure character set is UTF-8 0539 setIptcTagString("Iptc.Envelope.CharacterSet", QString::fromLatin1("\33%G"), false); 0540 0541 return true; 0542 } 0543 catch(Exiv2::Error& e) 0544 { 0545 d->printExiv2ExceptionError(QString::fromLatin1("Cannot set Iptc key '%1' into image using Exiv2 ").arg(QString::fromLatin1(iptcTagName)), e); 0546 } 0547 catch(...) 0548 { 0549 qCCritical(LIBKEXIV2_LOG) << "Default exception from Exiv2"; 0550 } 0551 0552 return false; 0553 } 0554 0555 QStringList KExiv2::getIptcKeywords() const 0556 { 0557 try 0558 { 0559 if (!d->iptcMetadata().empty()) 0560 { 0561 QStringList keywords; 0562 Exiv2::IptcData iptcData(d->iptcMetadata()); 0563 0564 for (Exiv2::IptcData::iterator it = iptcData.begin(); it != iptcData.end(); ++it) 0565 { 0566 QString key = QString::fromLocal8Bit(it->key().c_str()); 0567 0568 if (key == QString::fromLatin1("Iptc.Application2.Keywords")) 0569 { 0570 QString val = QString::fromUtf8(it->toString().c_str()); 0571 keywords.append(val); 0572 } 0573 } 0574 0575 qCDebug(LIBKEXIV2_LOG) << d->filePath << " ==> Read Iptc Keywords: " << keywords; 0576 0577 return keywords; 0578 } 0579 } 0580 catch(Exiv2::Error& e) 0581 { 0582 d->printExiv2ExceptionError(QString::fromLatin1("Cannot get Iptc Keywords from image using Exiv2 "), e); 0583 } 0584 catch(...) 0585 { 0586 qCCritical(LIBKEXIV2_LOG) << "Default exception from Exiv2"; 0587 } 0588 0589 return QStringList(); 0590 } 0591 0592 bool KExiv2::setIptcKeywords(const QStringList& oldKeywords, const QStringList& newKeywords, 0593 bool setProgramName) const 0594 { 0595 if (!setProgramId(setProgramName)) 0596 return false; 0597 0598 try 0599 { 0600 QStringList oldkeys = oldKeywords; 0601 QStringList newkeys = newKeywords; 0602 0603 qCDebug(LIBKEXIV2_LOG) << d->filePath << " ==> New Iptc Keywords: " << newkeys; 0604 0605 // Remove all old keywords. 0606 Exiv2::IptcData iptcData(d->iptcMetadata()); 0607 Exiv2::IptcData::iterator it = iptcData.begin(); 0608 0609 while(it != iptcData.end()) 0610 { 0611 QString key = QString::fromLocal8Bit(it->key().c_str()); 0612 QString val = QString::fromUtf8(it->toString().c_str()); 0613 0614 // Also remove new keywords to avoid duplicates. They will be added again below. 0615 if ( key == QString::fromLatin1("Iptc.Application2.Keywords") && 0616 (oldKeywords.contains(val) || newKeywords.contains(val)) 0617 ) 0618 it = iptcData.erase(it); 0619 else 0620 ++it; 0621 }; 0622 0623 // Add new keywords. Note that Keywords Iptc tag is limited to 64 char but can be redondant. 0624 0625 Exiv2::IptcKey iptcTag("Iptc.Application2.Keywords"); 0626 0627 for (QStringList::iterator it = newkeys.begin(); it != newkeys.end(); ++it) 0628 { 0629 QString key = *it; 0630 key.truncate(64); 0631 0632 #if EXIV2_TEST_VERSION(0,28,0) 0633 Exiv2::Value::UniquePtr val = Exiv2::Value::create(Exiv2::string); 0634 #else 0635 Exiv2::Value::AutoPtr val = Exiv2::Value::create(Exiv2::string); 0636 #endif 0637 val->read(key.toUtf8().constData()); 0638 iptcData.add(iptcTag, val.get()); 0639 } 0640 0641 d->iptcMetadata() = iptcData; 0642 0643 // Make sure character set is UTF-8 0644 setIptcTagString("Iptc.Envelope.CharacterSet", QString::fromLatin1("\33%G"), false); 0645 0646 return true; 0647 } 0648 catch(Exiv2::Error& e) 0649 { 0650 d->printExiv2ExceptionError(QString::fromLatin1("Cannot set Iptc Keywords into image using Exiv2 "), e); 0651 } 0652 catch(...) 0653 { 0654 qCCritical(LIBKEXIV2_LOG) << "Default exception from Exiv2"; 0655 } 0656 0657 return false; 0658 } 0659 0660 QStringList KExiv2::getIptcSubjects() const 0661 { 0662 try 0663 { 0664 if (!d->iptcMetadata().empty()) 0665 { 0666 QStringList subjects; 0667 Exiv2::IptcData iptcData(d->iptcMetadata()); 0668 0669 for (Exiv2::IptcData::iterator it = iptcData.begin(); it != iptcData.end(); ++it) 0670 { 0671 QString key = QString::fromLocal8Bit(it->key().c_str()); 0672 0673 if (key == QString::fromLatin1("Iptc.Application2.Subject")) 0674 { 0675 QString val(QString::fromLatin1(it->toString().c_str())); 0676 subjects.append(val); 0677 } 0678 } 0679 0680 return subjects; 0681 } 0682 } 0683 catch(Exiv2::Error& e) 0684 { 0685 d->printExiv2ExceptionError(QString::fromLatin1("Cannot get Iptc Subjects from image using Exiv2 "), e); 0686 } 0687 catch(...) 0688 { 0689 qCCritical(LIBKEXIV2_LOG) << "Default exception from Exiv2"; 0690 } 0691 0692 return QStringList(); 0693 } 0694 0695 bool KExiv2::setIptcSubjects(const QStringList& oldSubjects, const QStringList& newSubjects, 0696 bool setProgramName) const 0697 { 0698 if (!setProgramId(setProgramName)) 0699 return false; 0700 0701 try 0702 { 0703 QStringList oldDef = oldSubjects; 0704 QStringList newDef = newSubjects; 0705 0706 // Remove all old subjects. 0707 Exiv2::IptcData iptcData(d->iptcMetadata()); 0708 Exiv2::IptcData::iterator it = iptcData.begin(); 0709 0710 while(it != iptcData.end()) 0711 { 0712 QString key = QString::fromLocal8Bit(it->key().c_str()); 0713 QString val = QString::fromUtf8(it->toString().c_str()); 0714 0715 if (key == QString::fromLatin1("Iptc.Application2.Subject") && oldDef.contains(val)) 0716 it = iptcData.erase(it); 0717 else 0718 ++it; 0719 }; 0720 0721 // Add new subjects. Note that Keywords Iptc tag is limited to 236 char but can be redondant. 0722 0723 Exiv2::IptcKey iptcTag("Iptc.Application2.Subject"); 0724 0725 for (QStringList::iterator it = newDef.begin(); it != newDef.end(); ++it) 0726 { 0727 QString key = *it; 0728 key.truncate(236); 0729 0730 #if EXIV2_TEST_VERSION(0,28,0) 0731 Exiv2::Value::UniquePtr val = Exiv2::Value::create(Exiv2::string); 0732 #else 0733 Exiv2::Value::AutoPtr val = Exiv2::Value::create(Exiv2::string); 0734 #endif 0735 val->read(key.toUtf8().constData()); 0736 iptcData.add(iptcTag, val.get()); 0737 } 0738 0739 d->iptcMetadata() = iptcData; 0740 0741 // Make sure character set is UTF-8 0742 setIptcTagString("Iptc.Envelope.CharacterSet", QString::fromLatin1("\33%G"), false); 0743 0744 return true; 0745 } 0746 catch(Exiv2::Error& e) 0747 { 0748 d->printExiv2ExceptionError(QString::fromLatin1("Cannot set Iptc Subjects into image using Exiv2 "), e); 0749 } 0750 catch(...) 0751 { 0752 qCCritical(LIBKEXIV2_LOG) << "Default exception from Exiv2"; 0753 } 0754 0755 return false; 0756 } 0757 0758 QStringList KExiv2::getIptcSubCategories() const 0759 { 0760 try 0761 { 0762 if (!d->iptcMetadata().empty()) 0763 { 0764 QStringList subCategories; 0765 Exiv2::IptcData iptcData(d->iptcMetadata()); 0766 0767 for (Exiv2::IptcData::iterator it = iptcData.begin(); it != iptcData.end(); ++it) 0768 { 0769 QString key = QString::fromLocal8Bit(it->key().c_str()); 0770 0771 if (key == QString::fromLatin1("Iptc.Application2.SuppCategory")) 0772 { 0773 QString val(QString::fromLatin1(it->toString().c_str())); 0774 subCategories.append(val); 0775 } 0776 } 0777 0778 return subCategories; 0779 } 0780 } 0781 catch(Exiv2::Error& e) 0782 { 0783 d->printExiv2ExceptionError(QString::fromLatin1("Cannot get Iptc Sub Categories from image using Exiv2 "), e); 0784 } 0785 catch(...) 0786 { 0787 qCCritical(LIBKEXIV2_LOG) << "Default exception from Exiv2"; 0788 } 0789 0790 return QStringList(); 0791 } 0792 0793 bool KExiv2::setIptcSubCategories(const QStringList& oldSubCategories, const QStringList& newSubCategories, 0794 bool setProgramName) const 0795 { 0796 if (!setProgramId(setProgramName)) 0797 return false; 0798 0799 try 0800 { 0801 QStringList oldkeys = oldSubCategories; 0802 QStringList newkeys = newSubCategories; 0803 0804 // Remove all old Sub Categories. 0805 Exiv2::IptcData iptcData(d->iptcMetadata()); 0806 Exiv2::IptcData::iterator it = iptcData.begin(); 0807 0808 while(it != iptcData.end()) 0809 { 0810 QString key = QString::fromLocal8Bit(it->key().c_str()); 0811 QString val = QString::fromUtf8(it->toString().c_str()); 0812 0813 if (key == QString::fromLatin1("Iptc.Application2.SuppCategory") && oldSubCategories.contains(val)) 0814 it = iptcData.erase(it); 0815 else 0816 ++it; 0817 }; 0818 0819 // Add new Sub Categories. Note that SubCategories Iptc tag is limited to 32 0820 // characters but can be redondant. 0821 0822 Exiv2::IptcKey iptcTag("Iptc.Application2.SuppCategory"); 0823 0824 for (QStringList::iterator it = newkeys.begin(); it != newkeys.end(); ++it) 0825 { 0826 QString key = *it; 0827 key.truncate(32); 0828 0829 #if EXIV2_TEST_VERSION(0,28,0) 0830 Exiv2::Value::UniquePtr val = Exiv2::Value::create(Exiv2::string); 0831 #else 0832 Exiv2::Value::AutoPtr val = Exiv2::Value::create(Exiv2::string); 0833 #endif 0834 val->read(key.toUtf8().constData()); 0835 iptcData.add(iptcTag, val.get()); 0836 } 0837 0838 d->iptcMetadata() = iptcData; 0839 0840 // Make sure character set is UTF-8 0841 setIptcTagString("Iptc.Envelope.CharacterSet", QString::fromLatin1("\33%G"), false); 0842 0843 return true; 0844 } 0845 catch(Exiv2::Error& e) 0846 { 0847 d->printExiv2ExceptionError(QString::fromLatin1("Cannot set Iptc Sub Categories into image using Exiv2 "), e); 0848 } 0849 catch(...) 0850 { 0851 qCCritical(LIBKEXIV2_LOG) << "Default exception from Exiv2"; 0852 } 0853 0854 return false; 0855 } 0856 0857 KExiv2::TagsMap KExiv2::getIptcTagsList() const 0858 { 0859 try 0860 { 0861 QList<const Exiv2::DataSet*> tags; 0862 tags << Exiv2::IptcDataSets::envelopeRecordList() 0863 << Exiv2::IptcDataSets::application2RecordList(); 0864 0865 TagsMap tagsMap; 0866 0867 for (QList<const Exiv2::DataSet*>::iterator it = tags.begin(); it != tags.end(); ++it) 0868 { 0869 do 0870 { 0871 QString key = QLatin1String( Exiv2::IptcKey( (*it)->number_, (*it)->recordId_ ).key().c_str() ); 0872 QStringList values; 0873 values << QString::fromLatin1((*it)->name_) << QString::fromLatin1((*it)->title_) << QString::fromLatin1((*it)->desc_); 0874 tagsMap.insert(key, values); 0875 ++(*it); 0876 } 0877 while((*it)->number_ != 0xffff); 0878 } 0879 0880 return tagsMap; 0881 } 0882 catch(Exiv2::Error& e) 0883 { 0884 d->printExiv2ExceptionError(QString::fromLatin1("Cannot get Iptc Tags list using Exiv2 "), e); 0885 } 0886 catch(...) 0887 { 0888 qCCritical(LIBKEXIV2_LOG) << "Default exception from Exiv2"; 0889 } 0890 0891 return TagsMap(); 0892 } 0893 0894 } // NameSpace KExiv2Iface