• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdegraphics API Reference
  • KDE Home
  • Contact Us
 

libs/libkexiv2/libkexiv2

  • sources
  • kde-4.14
  • kdegraphics
  • libs
  • libkexiv2
  • libkexiv2
kexiv2xmp.cpp
Go to the documentation of this file.
1 
28 #include "kexiv2.h"
29 #include "kexiv2_p.h"
30 
31 namespace KExiv2Iface
32 {
33 
34 bool KExiv2::canWriteXmp(const QString& filePath)
35 {
36 #ifdef _XMP_SUPPORT_
37  try
38  {
39  Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open((const char*)
40  (QFile::encodeName(filePath)));
41 
42  Exiv2::AccessMode mode = image->checkMode(Exiv2::mdXmp);
43  return (mode == Exiv2::amWrite || mode == Exiv2::amReadWrite);
44  }
45  catch( Exiv2::Error& e )
46  {
47  std::string s(e.what());
48  kError() << "Cannot check Xmp access mode using Exiv2 (Error #"
49  << e.code() << ": " << s.c_str() << ")";
50  }
51  catch(...)
52  {
53  kError() << "Default exception from Exiv2";
54  }
55 
56 #else
57 
58  Q_UNUSED(filePath);
59 
60 #endif // _XMP_SUPPORT_
61 
62  return false;
63 }
64 
65 bool KExiv2::hasXmp() const
66 {
67 #ifdef _XMP_SUPPORT_
68 
69  return !d->xmpMetadata().empty();
70 
71 #else
72 
73  return false;
74 
75 #endif // _XMP_SUPPORT_
76 }
77 
78 bool KExiv2::clearXmp() const
79 {
80 #ifdef _XMP_SUPPORT_
81 
82  try
83  {
84  d->xmpMetadata().clear();
85  return true;
86  }
87  catch( Exiv2::Error& e )
88  {
89  d->printExiv2ExceptionError("Cannot clear Xmp data using Exiv2 ", e);
90  }
91  catch(...)
92  {
93  kError() << "Default exception from Exiv2";
94  }
95 
96 #endif // _XMP_SUPPORT_
97 
98  return false;
99 }
100 
101 QByteArray KExiv2::getXmp() const
102 {
103 #ifdef _XMP_SUPPORT_
104 
105  try
106  {
107  if (!d->xmpMetadata().empty())
108  {
109 
110  std::string xmpPacket;
111  Exiv2::XmpParser::encode(xmpPacket, d->xmpMetadata());
112  QByteArray data(xmpPacket.data(), xmpPacket.size());
113  return data;
114  }
115  }
116  catch( Exiv2::Error& e )
117  {
118  if (!d->filePath.isEmpty())
119 
120 
121  d->printExiv2ExceptionError("Cannot get Xmp data using Exiv2 ", e);
122  }
123  catch(...)
124  {
125  kError() << "Default exception from Exiv2";
126  }
127 
128 #endif // _XMP_SUPPORT_
129 
130  return QByteArray();
131 }
132 
133 bool KExiv2::setXmp(const QByteArray& data) const
134 {
135 #ifdef _XMP_SUPPORT_
136 
137  try
138  {
139  if (!data.isEmpty())
140  {
141 
142  std::string xmpPacket;
143  xmpPacket.assign(data.data(), data.size());
144  if (Exiv2::XmpParser::decode(d->xmpMetadata(), xmpPacket) != 0)
145  return false;
146  else
147  return true;
148  }
149  }
150  catch( Exiv2::Error& e )
151  {
152  if (!d->filePath.isEmpty())
153  kError() << "From file " << d->filePath.toAscii().constData();
154 
155  d->printExiv2ExceptionError("Cannot set Xmp data using Exiv2 ", e);
156  }
157  catch(...)
158  {
159  kError() << "Default exception from Exiv2";
160  }
161 
162 #else
163 
164  Q_UNUSED(data);
165 
166 #endif // _XMP_SUPPORT_
167 
168  return false;
169 }
170 
171 KExiv2::MetaDataMap KExiv2::getXmpTagsDataList(const QStringList& xmpKeysFilter, bool invertSelection) const
172 {
173 #ifdef _XMP_SUPPORT_
174 
175  if (d->xmpMetadata().empty())
176  return MetaDataMap();
177 
178  try
179  {
180  Exiv2::XmpData xmpData = d->xmpMetadata();
181  xmpData.sortByKey();
182 
183  QString ifDItemName;
184  MetaDataMap metaDataMap;
185 
186  for (Exiv2::XmpData::iterator md = xmpData.begin(); md != xmpData.end(); ++md)
187  {
188  QString key = QString::fromAscii(md->key().c_str());
189 
190  // Decode the tag value with a user friendly output.
191  std::ostringstream os;
192  os << *md;
193  QString value = QString::fromUtf8(os.str().c_str());
194 
195  // If the tag is a language alternative type, parse content to detect language.
196  if (md->typeId() == Exiv2::langAlt)
197  {
198  QString lang;
199  value = detectLanguageAlt(value, lang);
200  }
201  else
202  {
203  value = QString::fromUtf8(os.str().c_str());
204  }
205 
206  // To make a string just on one line.
207  value.replace('\n', ' ');
208 
209  // Some XMP key are redondancy. check if already one exist...
210  MetaDataMap::iterator it = metaDataMap.find(key);
211 
212  // We apply a filter to get only the XMP tags that we need.
213 
214  if (!xmpKeysFilter.isEmpty())
215  {
216  if (!invertSelection)
217  {
218  if (xmpKeysFilter.contains(key.section('.', 1, 1)))
219  {
220  if (it == metaDataMap.end())
221  {
222  metaDataMap.insert(key, value);
223  }
224  else
225  {
226  QString v = *it;
227  v.append(", ");
228  v.append(value);
229  metaDataMap.insert(key, v);
230  }
231  }
232  }
233  else
234  {
235  if (!xmpKeysFilter.contains(key.section('.', 1, 1)))
236  {
237  if (it == metaDataMap.end())
238  {
239  metaDataMap.insert(key, value);
240  }
241  else
242  {
243  QString v = *it;
244  v.append(", ");
245  v.append(value);
246  metaDataMap.insert(key, v);
247  }
248  }
249  }
250  }
251  else // else no filter at all.
252  {
253  if (it == metaDataMap.end())
254  {
255  metaDataMap.insert(key, value);
256  }
257  else
258  {
259  QString v = *it;
260  v.append(", ");
261  v.append(value);
262  metaDataMap.insert(key, v);
263  }
264  }
265  }
266 
267  return metaDataMap;
268  }
269  catch (Exiv2::Error& e)
270  {
271  d->printExiv2ExceptionError("Cannot parse Xmp metadata using Exiv2 ", e);
272  }
273  catch(...)
274  {
275  kError() << "Default exception from Exiv2";
276  }
277 
278 #else
279 
280  Q_UNUSED(xmpKeysFilter);
281  Q_UNUSED(invertSelection);
282 
283 #endif // _XMP_SUPPORT_
284 
285  return MetaDataMap();
286 }
287 
288 QString KExiv2::getXmpTagTitle(const char* xmpTagName)
289 {
290 #ifdef _XMP_SUPPORT_
291 
292  try
293  {
294  std::string xmpkey(xmpTagName);
295  Exiv2::XmpKey xk(xmpkey);
296  return QString::fromLocal8Bit( Exiv2::XmpProperties::propertyTitle(xk) );
297  }
298  catch (Exiv2::Error& e)
299  {
300  d->printExiv2ExceptionError("Cannot get Xmp metadata tag title using Exiv2 ", e);
301  }
302  catch(...)
303  {
304  kError() << "Default exception from Exiv2";
305  }
306 
307 #else
308 
309  Q_UNUSED(xmpTagName);
310 
311 #endif // _XMP_SUPPORT_
312 
313  return QString();
314 }
315 
316 QString KExiv2::getXmpTagDescription(const char* xmpTagName)
317 {
318 #ifdef _XMP_SUPPORT_
319  try
320  {
321  std::string xmpkey(xmpTagName);
322  Exiv2::XmpKey xk(xmpkey);
323  return QString::fromLocal8Bit( Exiv2::XmpProperties::propertyDesc(xk) );
324  }
325  catch (Exiv2::Error& e)
326  {
327  d->printExiv2ExceptionError("Cannot get Xmp metadata tag description using Exiv2 ", e);
328  }
329  catch(...)
330  {
331  kError() << "Default exception from Exiv2";
332  }
333 
334 #else
335 
336  Q_UNUSED(xmpTagName);
337 
338 #endif // _XMP_SUPPORT_
339 
340  return QString();
341 }
342 
343 QString KExiv2::getXmpTagString(const char* xmpTagName, bool escapeCR) const
344 {
345 #ifdef _XMP_SUPPORT_
346 
347  try
348  {
349  Exiv2::XmpData xmpData(d->xmpMetadata());
350  Exiv2::XmpKey key(xmpTagName);
351  Exiv2::XmpData::iterator it = xmpData.findKey(key);
352  if (it != xmpData.end())
353  {
354  std::ostringstream os;
355  os << *it;
356  QString tagValue = QString::fromUtf8(os.str().c_str());
357 
358  if (escapeCR)
359  tagValue.replace('\n', ' ');
360 
361  return tagValue;
362  }
363  }
364  catch( Exiv2::Error& e )
365  {
366  d->printExiv2ExceptionError(QString("Cannot find Xmp key '%1' into image using Exiv2 ")
367  .arg(xmpTagName), e);
368  }
369  catch(...)
370  {
371  kError() << "Default exception from Exiv2";
372  }
373 
374 #else
375 
376  Q_UNUSED(xmpTagName);
377  Q_UNUSED(escapeCR);
378 
379 #endif // _XMP_SUPPORT_
380 
381  return QString();
382 }
383 
384 bool KExiv2::setXmpTagString(const char* xmpTagName, const QString& value, bool setProgramName) const
385 {
386 #ifdef _XMP_SUPPORT_
387 
388  if (!setProgramId(setProgramName))
389  return false;
390 
391  try
392  {
393  const std::string &txt(value.toUtf8().constData());
394  Exiv2::Value::AutoPtr xmpTxtVal = Exiv2::Value::create(Exiv2::xmpText);
395  xmpTxtVal->read(txt);
396  d->xmpMetadata()[xmpTagName].setValue(xmpTxtVal.get());
397  return true;
398  }
399  catch( Exiv2::Error& e )
400  {
401  d->printExiv2ExceptionError("Cannot set Xmp tag string into image using Exiv2 ", e);
402  }
403  catch(...)
404  {
405  kError() << "Default exception from Exiv2";
406  }
407 
408 #else
409 
410  Q_UNUSED(xmpTagName);
411  Q_UNUSED(value);
412  Q_UNUSED(setProgramName);
413 
414 #endif // _XMP_SUPPORT_
415 
416  return false;
417 }
418 bool KExiv2::setXmpTagString(const char* xmpTagName, const QString& value,
419  KExiv2::XmpTagType type, bool setProgramName) const
420 {
421 #ifdef _XMP_SUPPORT_
422 
423  if (!setProgramId(setProgramName))
424  return false;
425 
426  try
427  {
428  const std::string &txt(value.toUtf8().constData());
429  Exiv2::XmpTextValue xmpTxtVal("");
430 
431  if(type == KExiv2::NormalTag) // normal type
432  {
433  xmpTxtVal.read(txt);
434  d->xmpMetadata().add(Exiv2::XmpKey(xmpTagName),&xmpTxtVal);
435  return true;
436  }
437  if(type == KExiv2::ArrayBagTag) // xmp type = bag
438  {
439  xmpTxtVal.setXmpArrayType(Exiv2::XmpValue::xaBag);
440  xmpTxtVal.read("");
441  d->xmpMetadata().add(Exiv2::XmpKey(xmpTagName),&xmpTxtVal);
442  }
443  if(type == KExiv2::StructureTag) // xmp type = struct
444  {
445  xmpTxtVal.setXmpStruct();
446  d->xmpMetadata().add(Exiv2::XmpKey(xmpTagName),&xmpTxtVal);
447  }
448  }
449  catch( Exiv2::Error& e )
450  {
451  d->printExiv2ExceptionError("Cannot set Xmp tag string into image using Exiv2 ", e);
452  }
453  catch(...)
454  {
455  kError() << "Default exception from Exiv2";
456  }
457 
458 #else
459 
460  Q_UNUSED(xmpTagName);
461  Q_UNUSED(value);
462  Q_UNUSED(setProgramName);
463 
464 #endif // _XMP_SUPPORT_
465 
466  return false;
467 }
468 KExiv2::AltLangMap KExiv2::getXmpTagStringListLangAlt(const char* xmpTagName, bool escapeCR) const
469 {
470 #ifdef _XMP_SUPPORT_
471 
472  try
473  {
474  Exiv2::XmpData xmpData = d->xmpMetadata();
475 
476  for (Exiv2::XmpData::iterator it = xmpData.begin(); it != xmpData.end(); ++it)
477  {
478  if (it->key() == xmpTagName && it->typeId() == Exiv2::langAlt)
479  {
480  AltLangMap map;
481  const Exiv2::LangAltValue &value = static_cast<const Exiv2::LangAltValue &>(it->value());
482 
483  for (Exiv2::LangAltValue::ValueType::const_iterator it2 = value.value_.begin();
484  it2 != value.value_.end(); ++it2)
485  {
486  QString lang = QString::fromUtf8(it2->first.c_str());
487  QString text = QString::fromUtf8(it2->second.c_str());
488  if (escapeCR)
489  text.replace('\n', ' ');
490 
491  map.insert(lang, text);
492  }
493 
494  return map;
495  }
496  }
497  }
498  catch( Exiv2::Error& e )
499  {
500  d->printExiv2ExceptionError(QString("Cannot find Xmp key '%1' into image using Exiv2 ")
501  .arg(xmpTagName), e);
502  }
503  catch(...)
504  {
505  kError() << "Default exception from Exiv2";
506  }
507 
508 #else
509 
510  Q_UNUSED(xmpTagName);
511  Q_UNUSED(escapeCR);
512 
513 #endif // _XMP_SUPPORT_
514 
515  return AltLangMap();
516 }
517 
518 bool KExiv2::setXmpTagStringListLangAlt(const char* xmpTagName, const KExiv2::AltLangMap& values,
519  bool setProgramName) const
520 {
521 #ifdef _XMP_SUPPORT_
522 
523  if (!setProgramId(setProgramName))
524  return false;
525 
526  try
527  {
528  // Remove old XMP alternative Language tag.
529  removeXmpTag(xmpTagName);
530 
531  if (!values.isEmpty())
532  {
533  Exiv2::Value::AutoPtr xmpTxtVal = Exiv2::Value::create(Exiv2::langAlt);
534 
535  for (AltLangMap::const_iterator it = values.constBegin(); it != values.constEnd(); ++it)
536  {
537  QString lang = it.key();
538  QString text = it.value();
539  QString txtLangAlt = QString("lang=%1 %2").arg(lang).arg(text);
540  const std::string &txt(txtLangAlt.toUtf8().constData());
541  xmpTxtVal->read(txt);
542  }
543 
544  // ...and add the new one instead.
545  d->xmpMetadata().add(Exiv2::XmpKey(xmpTagName), xmpTxtVal.get());
546  }
547  return true;
548  }
549  catch( Exiv2::Error& e )
550  {
551  d->printExiv2ExceptionError("Cannot set Xmp tag string lang-alt into image using Exiv2 ", e);
552  }
553  catch(...)
554  {
555  kError() << "Default exception from Exiv2";
556  }
557 
558 #else
559 
560  Q_UNUSED(xmpTagName);
561  Q_UNUSED(values);
562  Q_UNUSED(setProgramName);
563 
564 #endif // _XMP_SUPPORT_
565 
566  return false;
567 }
568 
569 QString KExiv2::getXmpTagStringLangAlt(const char* xmpTagName, const QString& langAlt, bool escapeCR) const
570 {
571 #ifdef _XMP_SUPPORT_
572 
573  try
574  {
575  Exiv2::XmpData xmpData(d->xmpMetadata());
576  Exiv2::XmpKey key(xmpTagName);
577  for (Exiv2::XmpData::iterator it = xmpData.begin(); it != xmpData.end(); ++it)
578  {
579  if (it->key() == xmpTagName && it->typeId() == Exiv2::langAlt)
580  {
581  for (int i = 0; i < it->count(); i++)
582  {
583  std::ostringstream os;
584  os << it->toString(i);
585  QString lang;
586  QString tagValue = QString::fromUtf8(os.str().c_str());
587  tagValue = detectLanguageAlt(tagValue, lang);
588  if (langAlt == lang)
589  {
590  if (escapeCR)
591  tagValue.replace('\n', ' ');
592 
593  return tagValue;
594  }
595  }
596  }
597  }
598  }
599  catch( Exiv2::Error& e )
600  {
601  d->printExiv2ExceptionError(QString("Cannot find Xmp key '%1' into image using Exiv2 ")
602  .arg(xmpTagName), e);
603  }
604  catch(...)
605  {
606  kError() << "Default exception from Exiv2";
607  }
608 
609 #else
610 
611  Q_UNUSED(xmpTagName);
612  Q_UNUSED(langAlt);
613  Q_UNUSED(escapeCR);
614 
615 #endif // _XMP_SUPPORT_
616 
617  return QString();
618 }
619 
620 bool KExiv2::setXmpTagStringLangAlt(const char* xmpTagName, const QString& value,
621  const QString& langAlt, bool setProgramName) const
622 {
623 #ifdef _XMP_SUPPORT_
624 
625  if (!setProgramId(setProgramName))
626  return false;
627 
628  try
629  {
630  QString language("x-default"); // default alternative language.
631 
632  if (!langAlt.isEmpty())
633  language = langAlt;
634 
635  QString txtLangAlt = QString("lang=%1 %2").arg(language).arg(value);
636 
637  const std::string &txt(txtLangAlt.toUtf8().constData());
638  Exiv2::Value::AutoPtr xmpTxtVal = Exiv2::Value::create(Exiv2::langAlt);
639 
640  // Search if an Xmp tag already exist.
641 
642  AltLangMap map = getXmpTagStringListLangAlt(xmpTagName, false);
643  if (!map.isEmpty())
644  {
645  for (AltLangMap::iterator it = map.begin(); it != map.end(); ++it)
646  {
647  if (it.key() != langAlt)
648  {
649  const std::string &val((*it).toUtf8().constData());
650  xmpTxtVal->read(val);
651  kDebug() << *it;
652  }
653  }
654  }
655 
656  xmpTxtVal->read(txt);
657  removeXmpTag(xmpTagName);
658  d->xmpMetadata().add(Exiv2::XmpKey(xmpTagName), xmpTxtVal.get());
659  return true;
660  }
661  catch( Exiv2::Error& e )
662  {
663  d->printExiv2ExceptionError("Cannot set Xmp tag string lang-alt into image using Exiv2 ", e);
664  }
665  catch(...)
666  {
667  kError() << "Default exception from Exiv2";
668  }
669 
670 #else
671 
672  Q_UNUSED(xmpTagName);
673  Q_UNUSED(value);
674  Q_UNUSED(langAlt);
675  Q_UNUSED(setProgramName);
676 
677 #endif // _XMP_SUPPORT_
678 
679  return false;
680 }
681 
682 QStringList KExiv2::getXmpTagStringSeq(const char* xmpTagName, bool escapeCR) const
683 {
684 #ifdef _XMP_SUPPORT_
685 
686  try
687  {
688  Exiv2::XmpData xmpData(d->xmpMetadata());
689  Exiv2::XmpKey key(xmpTagName);
690  Exiv2::XmpData::iterator it = xmpData.findKey(key);
691  if (it != xmpData.end())
692  {
693  if (it->typeId() == Exiv2::xmpSeq)
694  {
695  QStringList seq;
696 
697  for (int i = 0; i < it->count(); i++)
698  {
699  std::ostringstream os;
700  os << it->toString(i);
701  QString seqValue = QString::fromUtf8(os.str().c_str());
702 
703  if (escapeCR)
704  seqValue.replace('\n', ' ');
705 
706  seq.append(seqValue);
707  }
708  kDebug() << "XMP String Seq (" << xmpTagName << "): " << seq;
709 
710  return seq;
711  }
712  }
713  }
714  catch( Exiv2::Error& e )
715  {
716  d->printExiv2ExceptionError(QString("Cannot find Xmp key '%1' into image using Exiv2 ")
717  .arg(xmpTagName), e);
718  }
719  catch(...)
720  {
721  kError() << "Default exception from Exiv2";
722  }
723 
724 #else
725 
726  Q_UNUSED(xmpTagName);
727  Q_UNUSED(escapeCR);
728 
729 #endif // _XMP_SUPPORT_
730 
731  return QStringList();
732 }
733 
734 bool KExiv2::setXmpTagStringSeq(const char* xmpTagName, const QStringList& seq,
735  bool setProgramName) const
736 {
737 #ifdef _XMP_SUPPORT_
738 
739  if (!setProgramId(setProgramName))
740  return false;
741 
742  try
743  {
744  if (seq.isEmpty())
745  {
746  removeXmpTag(xmpTagName);
747  }
748  else
749  {
750  const QStringList list = seq;
751  Exiv2::Value::AutoPtr xmpTxtSeq = Exiv2::Value::create(Exiv2::xmpSeq);
752 
753  for (QStringList::const_iterator it = list.constBegin(); it != list.constEnd(); ++it )
754  {
755  const std::string &txt((*it).toUtf8().constData());
756  xmpTxtSeq->read(txt);
757  }
758  d->xmpMetadata()[xmpTagName].setValue(xmpTxtSeq.get());
759  }
760  return true;
761  }
762  catch( Exiv2::Error& e )
763  {
764  d->printExiv2ExceptionError("Cannot set Xmp tag string Seq into image using Exiv2 ", e);
765  }
766  catch(...)
767  {
768  kError() << "Default exception from Exiv2";
769  }
770 
771 #else
772 
773  Q_UNUSED(xmpTagName);
774  Q_UNUSED(seq);
775  Q_UNUSED(setProgramName);
776 
777 #endif // _XMP_SUPPORT_
778 
779  return false;
780 }
781 
782 QStringList KExiv2::getXmpTagStringBag(const char* xmpTagName, bool escapeCR) const
783 {
784 #ifdef _XMP_SUPPORT_
785 
786  try
787  {
788  Exiv2::XmpData xmpData(d->xmpMetadata());
789  Exiv2::XmpKey key(xmpTagName);
790  Exiv2::XmpData::iterator it = xmpData.findKey(key);
791  if (it != xmpData.end())
792  {
793  if (it->typeId() == Exiv2::xmpBag)
794  {
795  QStringList bag;
796 
797  for (int i = 0; i < it->count(); i++)
798  {
799  std::ostringstream os;
800  os << it->toString(i);
801  QString bagValue = QString::fromUtf8(os.str().c_str());
802 
803  if (escapeCR)
804  bagValue.replace('\n', ' ');
805 
806  bag.append(bagValue);
807  }
808 
809  return bag;
810  }
811  }
812  }
813  catch( Exiv2::Error& e )
814  {
815  d->printExiv2ExceptionError(QString("Cannot find Xmp key '%1' into image using Exiv2 ")
816  .arg(xmpTagName), e);
817  }
818  catch(...)
819  {
820  kError() << "Default exception from Exiv2";
821  }
822 
823 #else
824 
825  Q_UNUSED(xmpTagName);
826  Q_UNUSED(escapeCR);
827 
828 #endif // _XMP_SUPPORT_
829 
830  return QStringList();
831 }
832 
833 bool KExiv2::setXmpTagStringBag(const char* xmpTagName, const QStringList& bag,
834  bool setProgramName) const
835 {
836 #ifdef _XMP_SUPPORT_
837 
838  if (!setProgramId(setProgramName))
839  return false;
840 
841  try
842  {
843  if (bag.isEmpty())
844  {
845  removeXmpTag(xmpTagName);
846  }
847  else
848  {
849  QStringList list = bag;
850  Exiv2::Value::AutoPtr xmpTxtBag = Exiv2::Value::create(Exiv2::xmpBag);
851 
852  for (QStringList::const_iterator it = list.constBegin(); it != list.constEnd(); ++it )
853  {
854  const std::string &txt((*it).toUtf8().constData());
855  xmpTxtBag->read(txt);
856  }
857  d->xmpMetadata()[xmpTagName].setValue(xmpTxtBag.get());
858  }
859  return true;
860  }
861  catch( Exiv2::Error& e )
862  {
863  d->printExiv2ExceptionError("Cannot set Xmp tag string Bag into image using Exiv2 ", e);
864  }
865  catch(...)
866  {
867  kError() << "Default exception from Exiv2";
868  }
869 
870 #else
871 
872  Q_UNUSED(xmpTagName);
873  Q_UNUSED(bag);
874  Q_UNUSED(setProgramName);
875 
876 #endif // _XMP_SUPPORT_
877 
878  return false;
879 }
880 
881 bool KExiv2::addToXmpTagStringBag(const char* xmpTagName, const QStringList& entriesToAdd,
882  bool setProgramName) const
883 {
884  if (!setProgramId(setProgramName))
885  return false;
886 
887  QStringList oldEntries = getXmpTagStringBag(xmpTagName, false);
888  QStringList newEntries = entriesToAdd;
889 
890  // Create a list of keywords including old one which already exists.
891  for (QStringList::const_iterator it = oldEntries.constBegin(); it != oldEntries.constEnd(); ++it )
892  {
893  if (!newEntries.contains(*it))
894  newEntries.append(*it);
895  }
896 
897  if (setXmpTagStringBag(xmpTagName, newEntries, false))
898  return true;
899 
900  return false;
901 }
902 
903 bool KExiv2::removeFromXmpTagStringBag(const char* xmpTagName, const QStringList& entriesToRemove,
904  bool setProgramName) const
905 {
906  if (!setProgramId(setProgramName))
907  return false;
908 
909  QStringList currentEntries = getXmpTagStringBag(xmpTagName, false);
910  QStringList newEntries;
911 
912  // Create a list of current keywords except those that shall be removed
913  for (QStringList::const_iterator it = currentEntries.constBegin(); it != currentEntries.constEnd(); ++it )
914  {
915  if (!entriesToRemove.contains(*it))
916  newEntries.append(*it);
917  }
918 
919  if (setXmpTagStringBag(xmpTagName, newEntries, false))
920  return true;
921 
922  return false;
923 }
924 
925 QVariant KExiv2::getXmpTagVariant(const char* xmpTagName, bool rationalAsListOfInts, bool stringEscapeCR) const
926 {
927 #ifdef _XMP_SUPPORT_
928  try
929  {
930  Exiv2::XmpData xmpData(d->xmpMetadata());
931  Exiv2::XmpKey key(xmpTagName);
932  Exiv2::XmpData::iterator it = xmpData.findKey(key);
933  if (it != xmpData.end())
934  {
935  switch (it->typeId())
936  {
937  case Exiv2::unsignedByte:
938  case Exiv2::unsignedShort:
939  case Exiv2::unsignedLong:
940  case Exiv2::signedShort:
941  case Exiv2::signedLong:
942  return QVariant((int)it->toLong());
943  case Exiv2::unsignedRational:
944  case Exiv2::signedRational:
945  if (rationalAsListOfInts)
946  {
947  QList<QVariant> list;
948  list << (*it).toRational().first;
949  list << (*it).toRational().second;
950  return QVariant(list);
951  }
952  else
953  {
954  // prefer double precision
955  double num = (*it).toRational().first;
956  double den = (*it).toRational().second;
957  if (den == 0.0)
958  return QVariant(QVariant::Double);
959  return QVariant(num / den);
960  }
961  case Exiv2::date:
962  case Exiv2::time:
963  {
964  QDateTime dateTime = QDateTime::fromString(it->toString().c_str(), Qt::ISODate);
965  return QVariant(dateTime);
966  }
967  case Exiv2::asciiString:
968  case Exiv2::comment:
969  case Exiv2::string:
970  {
971  std::ostringstream os;
972  os << *it;
973  QString tagValue = QString::fromLocal8Bit(os.str().c_str());
974 
975  if (stringEscapeCR)
976  tagValue.replace('\n', ' ');
977 
978  return QVariant(tagValue);
979  }
980  case Exiv2::xmpText:
981  {
982  std::ostringstream os;
983  os << *it;
984  QString tagValue = QString::fromUtf8(os.str().c_str());
985 
986  if (stringEscapeCR)
987  tagValue.replace('\n', ' ');
988 
989  return tagValue;
990  }
991  case Exiv2::xmpBag:
992  case Exiv2::xmpSeq:
993  case Exiv2::xmpAlt:
994  {
995  QStringList list;
996  for (int i=0; i < it->count(); i++)
997  {
998  list << QString::fromUtf8(it->toString(i).c_str());
999  }
1000  return list;
1001  }
1002  case Exiv2::langAlt:
1003  {
1004  // access the value directly
1005  const Exiv2::LangAltValue &value = static_cast<const Exiv2::LangAltValue &>(it->value());
1006  QMap<QString, QVariant> map;
1007  // access the ValueType std::map< std::string, std::string>
1008  Exiv2::LangAltValue::ValueType::const_iterator i;
1009  for (i = value.value_.begin(); i != value.value_.end(); ++i)
1010  {
1011  map[QString::fromUtf8(i->first.c_str())] = QString::fromUtf8(i->second.c_str());
1012  }
1013  return map;
1014  }
1015  default:
1016  break;
1017  }
1018  }
1019  }
1020  catch( Exiv2::Error& e )
1021  {
1022  d->printExiv2ExceptionError(QString("Cannot find Xmp key '%1' into image using Exiv2 ")
1023  .arg(xmpTagName), e);
1024  }
1025  catch(...)
1026  {
1027  kError() << "Default exception from Exiv2";
1028  }
1029 
1030 #else
1031 
1032  Q_UNUSED(xmpTagName);
1033  Q_UNUSED(rationalAsListOfInts);
1034  Q_UNUSED(stringEscapeCR);
1035 
1036 #endif // _XMP_SUPPORT_
1037 
1038  return QVariant();
1039 }
1040 
1041 bool KExiv2::registerXmpNameSpace(const QString& uri, const QString& prefix)
1042 {
1043 #ifdef _XMP_SUPPORT_
1044 
1045  try
1046  {
1047  QString ns = uri;
1048  if (!uri.endsWith('/')) ns.append('/');
1049  Exiv2::XmpProperties::registerNs(ns.toAscii().constData(), prefix.toAscii().constData());
1050  return true;
1051  }
1052  catch( Exiv2::Error& e )
1053  {
1054  Private::printExiv2ExceptionError("Cannot register a new Xmp namespace using Exiv2 ", e);
1055  }
1056  catch(...)
1057  {
1058  kError() << "Default exception from Exiv2";
1059  }
1060 
1061 #else
1062 
1063  Q_UNUSED(uri);
1064  Q_UNUSED(prefix);
1065 
1066 #endif // _XMP_SUPPORT_
1067 
1068  return false;
1069 }
1070 
1071 bool KExiv2::unregisterXmpNameSpace(const QString& uri)
1072 {
1073 #ifdef _XMP_SUPPORT_
1074 
1075  try
1076  {
1077  QString ns = uri;
1078  if (!uri.endsWith('/')) ns.append('/');
1079  Exiv2::XmpProperties::unregisterNs(ns.toAscii().constData());
1080  return true;
1081  }
1082  catch( Exiv2::Error& e )
1083  {
1084  Private::printExiv2ExceptionError("Cannot unregister a new Xmp namespace using Exiv2 ", e);
1085  }
1086  catch(...)
1087  {
1088  kError() << "Default exception from Exiv2";
1089  }
1090 
1091 #else
1092 
1093  Q_UNUSED(uri);
1094 
1095 #endif // _XMP_SUPPORT_
1096 
1097  return false;
1098 }
1099 
1100 bool KExiv2::removeXmpTag(const char* xmpTagName, bool setProgramName) const
1101 {
1102 #ifdef _XMP_SUPPORT_
1103 
1104  if (!setProgramId(setProgramName))
1105  return false;
1106 
1107  try
1108  {
1109  Exiv2::XmpKey xmpKey(xmpTagName);
1110  Exiv2::XmpData::iterator it = d->xmpMetadata().findKey(xmpKey);
1111  if (it != d->xmpMetadata().end())
1112  {
1113  d->xmpMetadata().erase(it);
1114  return true;
1115  }
1116  }
1117  catch( Exiv2::Error& e )
1118  {
1119  d->printExiv2ExceptionError("Cannot remove Xmp tag using Exiv2 ", e);
1120  }
1121  catch(...)
1122  {
1123  kError() << "Default exception from Exiv2";
1124  }
1125 
1126 #else
1127 
1128  Q_UNUSED(xmpTagName);
1129  Q_UNUSED(setProgramName);
1130 
1131 #endif // _XMP_SUPPORT_
1132 
1133  return false;
1134 }
1135 
1136 QStringList KExiv2::getXmpKeywords() const
1137 {
1138  return (getXmpTagStringBag("Xmp.dc.subject", false));
1139 }
1140 
1141 bool KExiv2::setXmpKeywords(const QStringList& newKeywords, bool setProgramName) const
1142 {
1143  return addToXmpTagStringBag("Xmp.dc.subject", newKeywords, setProgramName);
1144 }
1145 
1146 bool KExiv2::removeXmpKeywords(const QStringList& keywordsToRemove, bool setProgramName)
1147 {
1148  return removeFromXmpTagStringBag("Xmp.dc.subject", keywordsToRemove, setProgramName);
1149 }
1150 
1151 QStringList KExiv2::getXmpSubCategories() const
1152 {
1153  return (getXmpTagStringBag("Xmp.photoshop.SupplementalCategories", false));
1154 }
1155 
1156 bool KExiv2::setXmpSubCategories(const QStringList& newSubCategories, bool setProgramName) const
1157 {
1158  return addToXmpTagStringBag("Xmp.photoshop.SupplementalCategories", newSubCategories, setProgramName);
1159 }
1160 
1161 bool KExiv2::removeXmpSubCategories(const QStringList& subCategoriesToRemove, bool setProgramName)
1162 {
1163  return removeFromXmpTagStringBag("Xmp.photoshop.SupplementalCategories", subCategoriesToRemove, setProgramName);
1164 }
1165 
1166 QStringList KExiv2::getXmpSubjects() const
1167 {
1168  return (getXmpTagStringBag("Xmp.iptc.SubjectCode", false));
1169 }
1170 
1171 bool KExiv2::setXmpSubjects(const QStringList& newSubjects, bool setProgramName) const
1172 {
1173  return addToXmpTagStringBag("Xmp.iptc.SubjectCode", newSubjects, setProgramName);
1174 }
1175 
1176 bool KExiv2::removeXmpSubjects(const QStringList& subjectsToRemove, bool setProgramName)
1177 {
1178  return removeFromXmpTagStringBag("Xmp.iptc.SubjectCode", subjectsToRemove, setProgramName);
1179 }
1180 
1181 KExiv2::TagsMap KExiv2::getXmpTagsList() const
1182 {
1183  try
1184  {
1185  TagsMap tagsMap;
1186  d->getXMPTagsListFromPrefix("dc", tagsMap);
1187  d->getXMPTagsListFromPrefix("digiKam", tagsMap);
1188  d->getXMPTagsListFromPrefix("xmp", tagsMap);
1189  d->getXMPTagsListFromPrefix("xmpRights", tagsMap);
1190  d->getXMPTagsListFromPrefix("xmpMM", tagsMap);
1191  d->getXMPTagsListFromPrefix("xmpBJ", tagsMap);
1192  d->getXMPTagsListFromPrefix("xmpTPg", tagsMap);
1193  d->getXMPTagsListFromPrefix("xmpDM", tagsMap);
1194  d->getXMPTagsListFromPrefix("MicrosoftPhoto", tagsMap);
1195  d->getXMPTagsListFromPrefix("pdf", tagsMap);
1196  d->getXMPTagsListFromPrefix("photoshop", tagsMap);
1197  d->getXMPTagsListFromPrefix("crs", tagsMap);
1198  d->getXMPTagsListFromPrefix("tiff", tagsMap);
1199  d->getXMPTagsListFromPrefix("exif", tagsMap);
1200  d->getXMPTagsListFromPrefix("aux", tagsMap);
1201  d->getXMPTagsListFromPrefix("iptc", tagsMap);
1202  d->getXMPTagsListFromPrefix("iptcExt", tagsMap);
1203  d->getXMPTagsListFromPrefix("plus", tagsMap);
1204  d->getXMPTagsListFromPrefix("mwg-rs", tagsMap);
1205  d->getXMPTagsListFromPrefix("dwc", tagsMap);
1206  return tagsMap;
1207  }
1208  catch( Exiv2::Error& e )
1209  {
1210  d->printExiv2ExceptionError("Cannot get Xmp Tags list using Exiv2 ", e);
1211  }
1212  catch(...)
1213  {
1214  kError() << "Default exception from Exiv2";
1215  }
1216 
1217  return TagsMap();
1218 }
1219 
1220 } // NameSpace KExiv2Iface
KExiv2Iface::KExiv2::canWriteXmp
static bool canWriteXmp(const QString &filePath)
Return 'true' if Xmp can be written in file.
Definition: kexiv2xmp.cpp:34
KExiv2Iface::KExiv2::getXmpTagStringSeq
QStringList getXmpTagStringSeq(const char *xmpTagName, bool escapeCR=true) const
Get a Xmp tag content like a sequence of strings.
Definition: kexiv2xmp.cpp:682
KExiv2Iface::KExiv2::getXmpSubjects
QStringList getXmpSubjects() const
Return a strings list of Xmp subjects from image.
Definition: kexiv2xmp.cpp:1166
KExiv2Iface::KExiv2::ArrayBagTag
Definition: kexiv2.h:115
QString::fromAscii
QString fromAscii(const char *str, int size)
KExiv2Iface::KExiv2::getXmpSubCategories
QStringList getXmpSubCategories() const
Return a strings list of Xmp sub-categories from image.
Definition: kexiv2xmp.cpp:1151
KExiv2Iface::KExiv2::registerXmpNameSpace
static bool registerXmpNameSpace(const QString &uri, const QString &prefix)
Register a namespace which Exiv2 doesn't know yet.
Definition: kexiv2xmp.cpp:1041
KExiv2Iface::KExiv2::getXmp
QByteArray getXmp() const
Return a Qt byte array copy of XMp container get from current image.
Definition: kexiv2xmp.cpp:101
QString::append
QString & append(QChar ch)
KExiv2Iface::KExiv2::AltLangMap
QMap< QString, QString > AltLangMap
A map used to store a list of Alternative Language values.
Definition: kexiv2.h:129
KExiv2Iface::KExiv2::StructureTag
Definition: kexiv2.h:116
QByteArray
KExiv2Iface::KExiv2::getXmpTagStringListLangAlt
KExiv2::AltLangMap getXmpTagStringListLangAlt(const char *xmpTagName, bool escapeCR=true) const
Get all redondant Alternative Language Xmp tags content like a map.
Definition: kexiv2xmp.cpp:468
QMap::constBegin
const_iterator constBegin() const
QMap
KExiv2Iface::KExiv2::setXmpTagString
bool setXmpTagString(const char *xmpTagName, const QString &value, bool setProgramName=true) const
Set a Xmp tag content using a string.
Definition: kexiv2xmp.cpp:384
KExiv2Iface::KExiv2::getXmpTagStringBag
QStringList getXmpTagStringBag(const char *xmpTagName, bool escapeCR) const
Get a Xmp tag content like a bag of strings.
Definition: kexiv2xmp.cpp:782
QStringList::contains
bool contains(const QString &str, Qt::CaseSensitivity cs) const
QByteArray::isEmpty
bool isEmpty() const
KExiv2Iface::KExiv2::Private::filePath
QString filePath
Definition: kexiv2_p.h:206
KExiv2Iface::KExiv2::getXmpKeywords
QStringList getXmpKeywords() const
Return a strings list of Xmp keywords from image.
Definition: kexiv2xmp.cpp:1136
QList::const_iterator
KExiv2Iface::KExiv2::setXmp
bool setXmp(const QByteArray &data) const
Set the Xmp data using a Qt byte array.
Definition: kexiv2xmp.cpp:133
KExiv2Iface::KExiv2::NormalTag
Definition: kexiv2.h:114
QString::fromLocal8Bit
QString fromLocal8Bit(const char *str, int size)
QList::append
void append(const T &value)
KExiv2Iface::KExiv2::XmpTagType
XmpTagType
Xmp tag types, used by setXmpTag, only first three types are used.
Definition: kexiv2.h:112
QString::fromUtf8
QString fromUtf8(const char *str, int size)
KExiv2Iface::KExiv2::detectLanguageAlt
static QString detectLanguageAlt(const QString &value, QString &lang)
Language Alternative autodetection.
Definition: kexiv2comments.cpp:86
QList::isEmpty
bool isEmpty() const
QString::isEmpty
bool isEmpty() const
KExiv2Iface::KExiv2::setXmpTagStringBag
bool setXmpTagStringBag(const char *xmpTagName, const QStringList &bag, bool setProgramName=true) const
Set a Xmp tag content using the bag of strings 'bag'.
Definition: kexiv2xmp.cpp:833
KExiv2Iface::KExiv2::MetaDataMap
QMap< QString, QString > MetaDataMap
A map used to store Tags Key and Tags Value.
Definition: kexiv2.h:123
QMap::constEnd
const_iterator constEnd() const
QByteArray::constData
const char * constData() const
KExiv2Iface::KExiv2::Private::getXMPTagsListFromPrefix
int getXMPTagsListFromPrefix(const QString &pf, KExiv2::TagsMap &tagsMap) const
QMap::const_iterator
QString::endsWith
bool endsWith(const QString &s, Qt::CaseSensitivity cs) const
QList::first
T & first()
KExiv2Iface::KExiv2::removeXmpSubjects
bool removeXmpSubjects(const QStringList &subjectsToRemove, bool setProgramName=true)
Remove those Xmp subjects that are listed in subjectsToRemove from the subjects in metadata...
Definition: kexiv2xmp.cpp:1176
KExiv2Iface::KExiv2::removeXmpTag
bool removeXmpTag(const char *xmpTagName, bool setProgramName=true) const
Remove the Xmp tag 'xmpTagName' from Xmp metadata.
Definition: kexiv2xmp.cpp:1100
QString
QList
KExiv2Iface::KExiv2::addToXmpTagStringBag
bool addToXmpTagStringBag(const char *xmpTagName, const QStringList &entriesToAdd, bool setProgramName) const
Set an Xmp tag content using a list of strings defined by the 'entriesToAdd' parameter.
Definition: kexiv2xmp.cpp:881
QMap::end
iterator end()
KExiv2Iface::KExiv2::removeFromXmpTagStringBag
bool removeFromXmpTagStringBag(const char *xmpTagName, const QStringList &entriesToRemove, bool setProgramName) const
Remove those Xmp tag entries that are listed in entriesToRemove from the entries in metadata...
Definition: kexiv2xmp.cpp:903
QMap::begin
iterator begin()
QStringList
KExiv2Iface::KExiv2::unregisterXmpNameSpace
static bool unregisterXmpNameSpace(const QString &uri)
Unregister a previously registered custom namespace.
Definition: kexiv2xmp.cpp:1071
KExiv2Iface::KExiv2::setXmpTagStringLangAlt
bool setXmpTagStringLangAlt(const char *xmpTagName, const QString &value, const QString &langAlt, bool setProgramName=true) const
Set a Xmp tag content using a string with an alternative language header.
Definition: kexiv2xmp.cpp:620
KExiv2Iface::KExiv2::setXmpTagStringListLangAlt
bool setXmpTagStringListLangAlt(const char *xmpTagName, const KExiv2::AltLangMap &values, bool setProgramName) const
Set an Alternative Language Xmp tag content using a map.
Definition: kexiv2xmp.cpp:518
KExiv2Iface::KExiv2::getXmpTagStringLangAlt
QString getXmpTagStringLangAlt(const char *xmpTagName, const QString &langAlt, bool escapeCR) const
Get a Xmp tag content like a string set with an alternative language header 'langAlt' (like "fr-FR" f...
Definition: kexiv2xmp.cpp:569
QDateTime::fromString
QDateTime fromString(const QString &string, Qt::DateFormat format)
KExiv2Iface::KExiv2::setProgramId
virtual bool setProgramId(bool on=true) const
Re-implement this method to set automatically the Program Name and Program Version information in Exi...
Definition: kexiv2.cpp:541
KExiv2Iface::KExiv2::setXmpSubjects
bool setXmpSubjects(const QStringList &newSubjects, bool setProgramName=true) const
Set Xmp subjects using a list of strings defined by 'newSubjects' parameter.
Definition: kexiv2xmp.cpp:1171
KExiv2Iface::KExiv2::clearXmp
bool clearXmp() const
Clear the Xmp metadata container in memory.
Definition: kexiv2xmp.cpp:78
KExiv2Iface::KExiv2::removeXmpSubCategories
bool removeXmpSubCategories(const QStringList &categoriesToRemove, bool setProgramName=true)
Remove those Xmp sub-categories that are listed in categoriesToRemove from the sub-categories in meta...
Definition: kexiv2xmp.cpp:1161
KExiv2Iface::KExiv2::getXmpTagTitle
QString getXmpTagTitle(const char *xmpTagName)
Return the Xmp Tag title or a null string.
Definition: kexiv2xmp.cpp:288
QString::replace
QString & replace(int position, int n, QChar after)
KExiv2Iface::KExiv2::getXmpTagString
QString getXmpTagString(const char *xmpTagName, bool escapeCR=true) const
Get a Xmp tag content like a string.
Definition: kexiv2xmp.cpp:343
KExiv2Iface::KExiv2::TagsMap
QMap< QString, QStringList > TagsMap
A map used to store Tags Key and a list of Tags properties :
Definition: kexiv2.h:136
KExiv2Iface::KExiv2::getXmpTagVariant
QVariant getXmpTagVariant(const char *xmpTagName, bool rationalAsListOfInts=true, bool stringEscapeCR=true) const
Get an Xmp tag content as a QVariant.
Definition: kexiv2xmp.cpp:925
KExiv2Iface::KExiv2::Private::printExiv2ExceptionError
static void printExiv2ExceptionError(const QString &msg, Exiv2::Error &e)
Generic method to print the Exiv2 C++ Exception error message from 'e'.
kexiv2_p.h
===========================================================This file is a part of digiKam project htt...
KExiv2Iface::KExiv2::removeXmpKeywords
bool removeXmpKeywords(const QStringList &keywordsToRemove, bool setProgramName=true)
Remove those Xmp keywords that are listed in keywordsToRemove from the keywords in metadata...
Definition: kexiv2xmp.cpp:1146
QByteArray::data
char * data()
QString::section
QString section(QChar sep, int start, int end, QFlags< QString::SectionFlag > flags) const
KExiv2Iface::KExiv2::setXmpSubCategories
bool setXmpSubCategories(const QStringList &newSubCategories, bool setProgramName=true) const
Set Xmp sub-categories using a list of strings defined by 'newSubCategories' parameter.
Definition: kexiv2xmp.cpp:1156
KExiv2Iface::KExiv2::hasXmp
bool hasXmp() const
Return 'true' if metadata container in memory as Xmp.
Definition: kexiv2xmp.cpp:65
QMap::insert
iterator insert(const Key &key, const T &value)
KExiv2Iface::KExiv2::getXmpTagDescription
QString getXmpTagDescription(const char *xmpTagName)
Return the Xmp Tag description or a null string.
Definition: kexiv2xmp.cpp:316
QMap::isEmpty
bool isEmpty() const
KExiv2Iface::KExiv2::getXmpTagsDataList
KExiv2::MetaDataMap getXmpTagsDataList(const QStringList &xmpKeysFilter=QStringList(), bool invertSelection=false) const
Return a map of Xmp tags name/value found in metadata sorted by Xmp keys given by 'xmpKeysFilter'...
Definition: kexiv2xmp.cpp:171
QList::constEnd
const_iterator constEnd() const
QList::constBegin
const_iterator constBegin() const
KExiv2Iface::KExiv2::setXmpTagStringSeq
bool setXmpTagStringSeq(const char *xmpTagName, const QStringList &seq, bool setProgramName=true) const
Set a Xmp tag content using the sequence of strings 'seq'.
Definition: kexiv2xmp.cpp:734
QByteArray::size
int size() const
QString::arg
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
KExiv2Iface::KExiv2::data
KExiv2Data data() const
Definition: kexiv2.cpp:218
KExiv2Iface::KExiv2::setXmpKeywords
bool setXmpKeywords(const QStringList &newKeywords, bool setProgramName=true) const
Set Xmp keywords using a list of strings defined by 'newKeywords' parameter.
Definition: kexiv2xmp.cpp:1141
QMap::find
iterator find(const Key &key)
QMap::iterator
kexiv2.h
===========================================================This file is a part of digiKam project htt...
QFile::encodeName
QByteArray encodeName(const QString &fileName)
QString::toAscii
QByteArray toAscii() const
QDateTime
KExiv2Iface::KExiv2::getXmpTagsList
KExiv2::TagsMap getXmpTagsList() const
Return a map of all standard Xmp tags supported by Exiv2.
Definition: kexiv2xmp.cpp:1181
QVariant
QString::toUtf8
QByteArray toUtf8() const
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:19:40 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

libs/libkexiv2/libkexiv2

Skip menu "libs/libkexiv2/libkexiv2"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdegraphics API Reference

Skip menu "kdegraphics API Reference"
  •     libkdcraw
  •     libkexiv2
  •     libkipi
  •     libksane
  • okular

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal