~ubuntu-branches/ubuntu/saucy/digikam/saucy

« back to all changes in this revision

Viewing changes to libs/dmetadata/dmetadata.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Scott Kitterman
  • Date: 2010-12-21 23:19:11 UTC
  • mfrom: (1.2.33 upstream) (3.1.7 experimental)
  • Revision ID: james.westby@ubuntu.com-20101221231911-z9jip7s5aht1jqn9
Tags: 2:1.7.0-1ubuntu1
* Merge from Debian Experimental. Remaining Ubuntu changes:
  - Export .pot name and copy to plugins in debian/rules
  - Version build-depends on kipi-plugins-dev to ensure build is against the
    same version on all archs
* Drop debian/patches/kubuntu_01_linker.diff, incoporated upstream
* Remove patches directory and unused patches

Show diffs side-by-side

added added

removed removed

Lines of Context:
56
56
{
57
57
 
58
58
DMetadata::DMetadata()
59
 
         : KExiv2()
 
59
    : KExiv2()
60
60
{
61
61
}
62
62
 
63
63
DMetadata::DMetadata(const QString& filePath)
64
 
         : KExiv2()
 
64
    : KExiv2()
65
65
{
66
66
    load(filePath);
67
67
}
68
68
 
69
69
#if KEXIV2_VERSION >= 0x010000
70
70
DMetadata::DMetadata(const KExiv2Data& data)
71
 
         : KExiv2Iface::KExiv2(data)
 
71
    : KExiv2Iface::KExiv2(data)
72
72
{
73
73
}
74
74
#endif
85
85
    if (!KExiv2::load(filePath))
86
86
    {
87
87
        if (!loadUsingDcraw(filePath))
 
88
        {
88
89
            return false;
 
90
        }
89
91
    }
90
92
 
91
93
    return true;
94
96
bool DMetadata::loadUsingDcraw(const QString& filePath) const
95
97
{
96
98
    DcrawInfoContainer identify;
 
99
 
97
100
    if (KDcraw::rawFileIdentify(identify, filePath))
98
101
    {
99
102
        long int num=1, den=1;
100
103
 
101
104
        if (!identify.model.isNull())
 
105
        {
102
106
            setExifTagString("Exif.Image.Model", identify.model.toLatin1(), false);
 
107
        }
103
108
 
104
109
        if (!identify.make.isNull())
 
110
        {
105
111
            setExifTagString("Exif.Image.Make", identify.make.toLatin1(), false);
 
112
        }
106
113
 
107
114
        if (!identify.owner.isNull())
 
115
        {
108
116
            setExifTagString("Exif.Image.Artist", identify.owner.toLatin1(), false);
 
117
        }
109
118
 
110
119
        if (identify.sensitivity != -1)
 
120
        {
111
121
            setExifTagLong("Exif.Photo.ISOSpeedRatings", lroundf(identify.sensitivity), false);
 
122
        }
112
123
 
113
124
        if (identify.dateTime.isValid())
 
125
        {
114
126
            setImageDateTime(identify.dateTime, false, false);
 
127
        }
115
128
 
116
129
        if (identify.exposureTime != -1.0)
117
130
        {
132
145
        }
133
146
 
134
147
        if (identify.imageSize.isValid())
 
148
        {
135
149
            setImageDimensions(identify.imageSize, false);
 
150
        }
136
151
 
137
152
        // A RAW image is always uncalibrated. */
138
153
        setImageColorWorkSpace(WORKSPACE_UNCALIBRATED, false);
158
173
CaptionsMap DMetadata::getImageComments() const
159
174
{
160
175
    if (getFilePath().isEmpty())
 
176
    {
161
177
        return CaptionsMap();
 
178
    }
162
179
 
163
180
    CaptionsMap        captionsMap;
164
181
    KExiv2::AltLangMap authorsMap;
176
193
 
177
194
    // Get author name from IPTC DescriptionWriter. Private namespace above gets precedence.
178
195
    QVariant descriptionWriter = getMetadataField(MetadataInfo::DescriptionWriter);
 
196
 
179
197
    if (!descriptionWriter.isNull())
 
198
    {
180
199
        commonAuthor = descriptionWriter.toString();
 
200
    }
181
201
 
182
202
    // In first, we check XMP alternative language tags to create map of values.
183
203
 
184
204
    if (hasXmp())
185
205
    {
186
206
        commentsMap = getXmpTagStringListLangAlt("Xmp.dc.description", false);
 
207
 
187
208
        if (!commentsMap.isEmpty())
188
209
        {
189
210
            captionsMap.setData(commentsMap, authorsMap, commonAuthor, datesMap);
191
212
        }
192
213
 
193
214
        QString xmpComment = getXmpTagStringLangAlt("Xmp.exif.UserComment", QString(), false);
 
215
 
194
216
        if (!xmpComment.isEmpty())
195
217
        {
196
218
            commentsMap.insert(QString("x-default"), xmpComment);
199
221
        }
200
222
 
201
223
        xmpComment = getXmpTagStringLangAlt("Xmp.tiff.ImageDescription", QString(), false);
 
224
 
202
225
        if (!xmpComment.isEmpty())
203
226
        {
204
227
            commentsMap.insert(QString("x-default"), xmpComment);
212
235
    // For PNG, string is extracted from iTXt chunk.
213
236
 
214
237
    QString comment = getCommentsDecoded();
 
238
 
215
239
    if (!comment.isEmpty())
216
240
    {
217
241
        commentsMap.insert(QString("x-default"), comment);
224
248
    if (hasExif())
225
249
    {
226
250
        QString exifComment = getExifComment();
 
251
 
227
252
        if (!exifComment.isEmpty())
228
253
        {
229
254
            commentsMap.insert(QString("x-default"), exifComment);
237
262
    if (hasIptc())
238
263
    {
239
264
        QString iptcComment = getIptcTagString("Iptc.Application2.Caption", false);
 
265
 
240
266
        if (!iptcComment.isEmpty() && !iptcComment.trimmed().isEmpty())
241
267
        {
242
268
            commentsMap.insert(QString("x-default"), iptcComment);
261
287
    if (supportXmp())
262
288
    {
263
289
        if (!setXmpTagStringListLangAlt("Xmp.digiKam.CaptionsAuthorNames", comments.authorsList(), false))
 
290
        {
264
291
            return false;
 
292
        }
265
293
 
266
294
        if (!setXmpTagStringListLangAlt("Xmp.digiKam.CaptionsDateTimeStamps", comments.datesList(), false))
 
295
        {
267
296
            return false;
 
297
        }
268
298
    }
269
299
 
270
300
    QString defaultComment = comments[QString("x-default")].caption;
272
302
    // In first we set image comments, outside of Exif, XMP, and IPTC.
273
303
 
274
304
    if (!setComments(defaultComment.toUtf8()))
 
305
    {
275
306
        return false;
 
307
    }
276
308
 
277
309
    // In Second we write comments into Exif.
278
310
 
279
311
    if (!setExifComment(defaultComment))
 
312
    {
280
313
        return false;
 
314
    }
281
315
 
282
316
    // In Third we write comments into XMP. Language Alternative rule is not yet used.
283
317
 
285
319
    {
286
320
        // NOTE : setXmpTagStringListLangAlt remove xmp tag before to add new values
287
321
        if (!setXmpTagStringListLangAlt("Xmp.dc.description", comments.toAltLangMap(), false))
 
322
        {
288
323
            return false;
 
324
        }
289
325
 
290
326
        removeXmpTag("Xmp.exif.UserComment");
291
327
 
292
328
        if (!defaultComment.isNull())
293
329
            if (!setXmpTagStringLangAlt("Xmp.exif.UserComment", defaultComment, QString(), false))
 
330
            {
294
331
                return false;
 
332
            }
295
333
 
296
334
        removeXmpTag("Xmp.tiff.ImageDescription");
 
335
 
297
336
        if (!defaultComment.isNull())
298
337
            if (!setXmpTagStringLangAlt("Xmp.tiff.ImageDescription", defaultComment, QString(), false))
 
338
            {
299
339
                return false;
 
340
            }
300
341
    }
 
342
 
301
343
    // In Four we write comments into IPTC.
302
344
    // Note that Caption IPTC tag is limited to 2000 char and ASCII charset.
303
345
 
308
350
        defaultComment.truncate(2000);
309
351
 
310
352
        if (!setIptcTagString("Iptc.Application2.Caption", defaultComment))
 
353
        {
311
354
            return false;
 
355
        }
312
356
    }
313
357
 
314
358
    return true;
317
361
int DMetadata::getImageRating() const
318
362
{
319
363
    if (getFilePath().isEmpty())
 
364
    {
320
365
        return -1;
 
366
    }
321
367
 
322
368
    if (hasXmp())
323
369
    {
324
370
        QString value = getXmpTagString("Xmp.xmp.Rating", false);
 
371
 
325
372
        if (!value.isEmpty())
326
373
        {
327
374
            bool ok     = false;
328
375
            long rating = value.toLong(&ok);
 
376
 
329
377
            if (ok && rating >= RatingMin && rating <= RatingMax)
 
378
            {
330
379
                return rating;
 
380
            }
331
381
        }
332
382
 
333
383
        value = getXmpTagString("Xmp.MicrosoftPhoto.Rating", false);
 
384
 
334
385
        if (!value.isEmpty())
335
386
        {
336
387
            bool ok            = false;
337
388
            long ratingPercent = value.toLong(&ok);
 
389
 
338
390
            if (ok)
339
391
            {
340
392
                // Wrapper around rating percents managed by Windows Vista.
341
393
                long rating = -1;
342
 
                switch(ratingPercent)
 
394
 
 
395
                switch (ratingPercent)
343
396
                {
344
397
                    case 0:
345
398
                        rating = 0;
362
415
                }
363
416
 
364
417
                if (rating != -1 && rating >= RatingMin && rating <= RatingMax)
 
418
                {
365
419
                    return rating;
 
420
                }
366
421
            }
367
422
        }
368
423
    }
374
429
    if (hasExif())
375
430
    {
376
431
        long rating = -1;
 
432
 
377
433
        if (getExifTagLong("Exif.Image.0x4746", rating))
378
434
        {
379
435
            if (rating >= RatingMin && rating <= RatingMax)
 
436
            {
380
437
                return rating;
 
438
            }
381
439
        }
382
440
    }
383
441
 
405
463
        if (!IptcUrgency.isEmpty())
406
464
        {
407
465
            if (IptcUrgency == QString("1"))
 
466
            {
408
467
                return 5;
 
468
            }
409
469
            else if (IptcUrgency == QString("2"))
 
470
            {
410
471
                return 4;
 
472
            }
411
473
            else if (IptcUrgency == QString("3"))
 
474
            {
412
475
                return 4;
 
476
            }
413
477
            else if (IptcUrgency == QString("4"))
 
478
            {
414
479
                return 3;
 
480
            }
415
481
            else if (IptcUrgency == QString("5"))
 
482
            {
416
483
                return 2;
 
484
            }
417
485
            else if (IptcUrgency == QString("6"))
 
486
            {
418
487
                return 1;
 
488
            }
419
489
            else if (IptcUrgency == QString("7"))
 
490
            {
420
491
                return 1;
 
492
            }
421
493
            else if (IptcUrgency == QString("8"))
 
494
            {
422
495
                return 0;
 
496
            }
423
497
        }
424
498
    }
425
499
 
440
514
    kDebug() << getFilePath() << " ==> Rating: " << rating;
441
515
 
442
516
    if (!setProgramId())
 
517
    {
443
518
        return false;
 
519
    }
444
520
 
445
521
    // Set standard XMP rating tag.
446
522
 
447
523
    if (supportXmp())
448
524
    {
449
525
        if (!setXmpTagString("Xmp.xmp.Rating", QString::number(rating)))
 
526
        {
450
527
            return false;
 
528
        }
451
529
    }
452
530
 
453
531
    // Set Exif rating tag used by Windows Vista.
454
532
 
455
533
    if (!setExifTagLong("Exif.Image.0x4746", rating))
 
534
    {
456
535
        return false;
 
536
    }
457
537
 
458
538
    // Wrapper around rating percents managed by Windows Vista.
459
539
    int ratePercents = 0;
460
 
    switch(rating)
 
540
 
 
541
    switch (rating)
461
542
    {
462
543
        case 0:
463
544
            ratePercents = 0;
482
563
    if (supportXmp())
483
564
    {
484
565
        if (!setXmpTagString("Xmp.MicrosoftPhoto.Rating", QString::number(ratePercents)))
 
566
        {
485
567
            return false;
 
568
        }
486
569
    }
487
570
 
488
571
    if (!setExifTagLong("Exif.Image.0x4749", ratePercents))
 
572
    {
489
573
        return false;
 
574
    }
490
575
 
491
576
    return true;
492
577
}
500
585
        photoInfo.dateTime = getImageDateTime();
501
586
 
502
587
        photoInfo.make     = getExifTagString("Exif.Image.Make");
 
588
 
503
589
        if (photoInfo.make.isEmpty())
 
590
        {
504
591
            photoInfo.make = getXmpTagString("Xmp.tiff.Make");
 
592
        }
505
593
 
506
594
        photoInfo.model    = getExifTagString("Exif.Image.Model");
 
595
 
507
596
        if (photoInfo.model.isEmpty())
 
597
        {
508
598
            photoInfo.model = getXmpTagString("Xmp.tiff.Model");
 
599
        }
509
600
 
510
601
        photoInfo.lens     = getLensDescription();
511
602
 
512
603
        photoInfo.aperture = getExifTagString("Exif.Photo.FNumber");
 
604
 
513
605
        if (photoInfo.aperture.isEmpty())
 
606
        {
514
607
            photoInfo.aperture = getExifTagString("Exif.Photo.ApertureValue");
 
608
        }
 
609
 
515
610
        if (photoInfo.aperture.isEmpty())
 
611
        {
516
612
            photoInfo.aperture = getXmpTagString("Xmp.exif.FNumber");
 
613
        }
 
614
 
517
615
        if (photoInfo.aperture.isEmpty())
 
616
        {
518
617
            photoInfo.aperture = getXmpTagString("Xmp.exif.ApertureValue");
 
618
        }
519
619
 
520
620
        photoInfo.exposureTime = getExifTagString("Exif.Photo.ExposureTime");
 
621
 
521
622
        if (photoInfo.exposureTime.isEmpty())
 
623
        {
522
624
            photoInfo.exposureTime = getExifTagString("Exif.Photo.ShutterSpeedValue");
 
625
        }
 
626
 
523
627
        if (photoInfo.exposureTime.isEmpty())
 
628
        {
524
629
            photoInfo.exposureTime = getXmpTagString("Xmp.exif.ExposureTime");
 
630
        }
 
631
 
525
632
        if (photoInfo.exposureTime.isEmpty())
 
633
        {
526
634
            photoInfo.exposureTime = getXmpTagString("Xmp.exif.ShutterSpeedValue");
 
635
        }
527
636
 
528
637
        photoInfo.exposureMode    = getExifTagString("Exif.Photo.ExposureMode");
 
638
 
529
639
        if (photoInfo.exposureMode.isEmpty())
 
640
        {
530
641
            photoInfo.exposureMode = getXmpTagString("Xmp.exif.ExposureMode");
 
642
        }
 
643
 
531
644
        if (photoInfo.exposureMode.isEmpty())
 
645
        {
532
646
            photoInfo.exposureMode = getExifTagString("Exif.CanonCs.MeteringMode");
 
647
        }
533
648
 
534
649
        photoInfo.exposureProgram = getExifTagString("Exif.Photo.ExposureProgram");
 
650
 
535
651
        if (photoInfo.exposureProgram.isEmpty())
 
652
        {
536
653
            photoInfo.exposureProgram = getXmpTagString("Xmp.exif.ExposureProgram");
 
654
        }
 
655
 
537
656
        if (photoInfo.exposureProgram.isEmpty())
 
657
        {
538
658
            photoInfo.exposureProgram = getExifTagString("Exif.CanonCs.ExposureProgram");
 
659
        }
539
660
 
540
661
        photoInfo.focalLength     = getExifTagString("Exif.Photo.FocalLength");
 
662
 
541
663
        if (photoInfo.focalLength.isEmpty())
 
664
        {
542
665
            photoInfo.focalLength = getXmpTagString("Xmp.exif.FocalLength");
 
666
        }
 
667
 
543
668
        if (photoInfo.focalLength.isEmpty())
 
669
        {
544
670
            photoInfo.focalLength = getExifTagString("Exif.Canon.FocalLength");
 
671
        }
545
672
 
546
673
        photoInfo.focalLength35mm = getExifTagString("Exif.Photo.FocalLengthIn35mmFilm");
 
674
 
547
675
        if (photoInfo.focalLength35mm.isEmpty())
 
676
        {
548
677
            photoInfo.focalLength35mm = getXmpTagString("Xmp.exif.FocalLengthIn35mmFilm");
 
678
        }
549
679
 
550
680
        photoInfo.sensitivity = getExifTagString("Exif.Photo.ISOSpeedRatings");
 
681
 
551
682
        if (photoInfo.sensitivity.isEmpty())
 
683
        {
552
684
            photoInfo.sensitivity = getExifTagString("Exif.Photo.ExposureIndex");
 
685
        }
 
686
 
553
687
        if (photoInfo.sensitivity.isEmpty())
 
688
        {
554
689
            photoInfo.sensitivity = getXmpTagString("Xmp.exif.ISOSpeedRatings");
 
690
        }
 
691
 
555
692
        if (photoInfo.sensitivity.isEmpty())
 
693
        {
556
694
            photoInfo.sensitivity = getXmpTagString("Xmp.exif.ExposureIndex");
 
695
        }
 
696
 
557
697
        if (photoInfo.sensitivity.isEmpty())
 
698
        {
558
699
            photoInfo.sensitivity = getExifTagString("Exif.CanonSi.ISOSpeed");
 
700
        }
559
701
 
560
702
        photoInfo.flash = getExifTagString("Exif.Photo.Flash");
 
703
 
561
704
        if (photoInfo.flash.isEmpty())
 
705
        {
562
706
            photoInfo.flash = getXmpTagString("Xmp.exif.Flash");
 
707
        }
 
708
 
563
709
        if (photoInfo.flash.isEmpty())
 
710
        {
564
711
            photoInfo.flash = getExifTagString("Exif.CanonCs.FlashActivity");
 
712
        }
565
713
 
566
714
        photoInfo.whiteBalance = getExifTagString("Exif.Photo.WhiteBalance");
 
715
 
567
716
        if (photoInfo.whiteBalance.isEmpty())
 
717
        {
568
718
            photoInfo.whiteBalance = getXmpTagString("Xmp.exif.WhiteBalance");
 
719
        }
569
720
    }
570
721
 
571
722
    return photoInfo;
575
726
{
576
727
    // Try to get Tags Path list from XMP in first.
577
728
    tagsPath = getXmpTagStringSeq("Xmp.digiKam.TagsList", false);
 
729
 
578
730
    if (!tagsPath.isEmpty())
 
731
    {
579
732
        return true;
 
733
    }
580
734
 
581
735
    // Try to get Tags Path list from XMP in first.
582
736
    tagsPath = getXmpTagStringBag("Xmp.lr.hierarchicalSubject", false);
583
737
 
584
738
    // See B.K.O #221460: there is another LR tag for hierarchical subjects.
585
739
    if (tagsPath.isEmpty())
 
740
    {
586
741
        tagsPath = getXmpTagStringSeq("Xmp.lr.HierarchicalSubject", false);
 
742
    }
587
743
 
588
744
    if (!tagsPath.isEmpty())
589
745
    {
595
751
 
596
752
    // Try to get Tags Path list from XMP keywords.
597
753
    tagsPath = getXmpKeywords();
 
754
 
598
755
    if (!tagsPath.isEmpty())
 
756
    {
599
757
        return true;
 
758
    }
600
759
 
601
760
    // Try to get Tags Path list from IPTC keywords.
602
761
    // digiKam 0.9.x has used IPTC keywords to store Tags Path list.
604
763
    // do not support UTF-8 and have strings size limitation. But we will
605
764
    // let the capability to import it for interworking issues.
606
765
    tagsPath = getIptcKeywords();
 
766
 
607
767
    if (!tagsPath.isEmpty())
608
768
    {
609
769
        // Work around to Imach tags path list hosted in IPTC with '.' as separator.
610
770
        QStringList ntp = tagsPath.replaceInStrings(".", "/");
 
771
 
611
772
        if (ntp != tagsPath)
612
773
        {
613
774
            tagsPath = ntp;
614
 
            kDebug() << "Tags Path imported from Imach: " << tagsPath;
 
775
            kDebug() << "Tags Path imported from Imach: " << tagsPath;
615
776
        }
 
777
 
616
778
        return true;
617
779
    }
618
780
 
629
791
    if (supportXmp())
630
792
    {
631
793
        if (!setXmpTagStringSeq("Xmp.digiKam.TagsList", tagsPath))
 
794
        {
632
795
            return false;
 
796
        }
633
797
 
634
798
        QStringList LRtagsPath = tagsPath;
635
799
        LRtagsPath             = LRtagsPath.replaceInStrings("/", "|");
 
800
 
636
801
        if (!setXmpTagStringBag("Xmp.lr.hierarchicalSubject", LRtagsPath))
 
802
        {
637
803
            return false;
 
804
        }
638
805
    }
 
806
 
639
807
    return true;
640
808
}
641
809
 
642
810
bool DMetadata::setMetadataTemplate(const Template& t) const
643
811
{
644
 
    if (t.isNull()) return false;
 
812
    if (t.isNull())
 
813
    {
 
814
        return false;
 
815
    }
645
816
 
646
817
    if (!setProgramId())
 
818
    {
647
819
        return false;
 
820
    }
648
821
 
649
822
    QStringList authors           = t.authors();
650
823
    QString authorsPosition       = t.authorsPosition();
661
834
    if (supportXmp())
662
835
    {
663
836
        if (!setXmpTagStringSeq("Xmp.dc.creator", authors, false))
 
837
        {
664
838
            return false;
 
839
        }
665
840
 
666
841
        if (!setXmpTagStringSeq("Xmp.tiff.Artist", authors, false))
 
842
        {
667
843
            return false;
 
844
        }
668
845
 
669
846
        if (!setXmpTagString("Xmp.photoshop.AuthorsPosition", authorsPosition, false))
 
847
        {
670
848
            return false;
 
849
        }
671
850
 
672
851
        if (!setXmpTagString("Xmp.photoshop.Credit", credit, false))
 
852
        {
673
853
            return false;
 
854
        }
674
855
 
675
856
        if (!setXmpTagString("Xmp.photoshop.Source", source, false))
 
857
        {
676
858
            return false;
 
859
        }
677
860
 
678
861
        if (!setXmpTagString("Xmp.dc.source", source, false))
 
862
        {
679
863
            return false;
 
864
        }
680
865
 
681
866
        if (!setXmpTagStringListLangAlt("Xmp.dc.rights", copyright, false))
 
867
        {
682
868
            return false;
 
869
        }
683
870
 
684
871
        if (!setXmpTagStringListLangAlt("Xmp.tiff.Copyright", copyright, false))
 
872
        {
685
873
            return false;
 
874
        }
686
875
 
687
876
        if (!setXmpTagStringListLangAlt("Xmp.xmpRights.UsageTerms", rightUsage, false))
 
877
        {
688
878
            return false;
 
879
        }
689
880
 
690
881
        if (!setXmpTagString("Xmp.photoshop.Instructions", instructions, false))
 
882
        {
691
883
            return false;
 
884
        }
692
885
    }
693
886
 
694
887
    // Set IPTC tags.
695
888
 
696
889
    if (!setIptcTagsStringList("Iptc.Application2.Byline", 32,
697
890
                               getIptcTagsStringList("Iptc.Application2.Byline"),
698
 
                               authors, false)) return false;
699
 
 
700
 
    if (!setIptcTag(authorsPosition,        32,  "Authors Title", "Iptc.Application2.BylineTitle"))         return false;
701
 
    if (!setIptcTag(credit,                 32,  "Credit",        "Iptc.Application2.Credit"))              return false;
702
 
    if (!setIptcTag(source,                 32,  "Source",        "Iptc.Application2.Source"))              return false;
703
 
    if (!setIptcTag(copyright["x-default"], 128, "Copyright",     "Iptc.Application2.Copyright"))           return false;
704
 
    if (!setIptcTag(instructions,           256, "Instructions",  "Iptc.Application2.SpecialInstructions")) return false;
705
 
 
706
 
    if (!setIptcCoreLocation(t.locationInfo())) return false;
707
 
    if (!setCreatorContactInfo(t.contactInfo())) return false;
 
891
                               authors, false))
 
892
    {
 
893
        return false;
 
894
    }
 
895
 
 
896
    if (!setIptcTag(authorsPosition,        32,  "Authors Title", "Iptc.Application2.BylineTitle"))
 
897
    {
 
898
        return false;
 
899
    }
 
900
 
 
901
    if (!setIptcTag(credit,                 32,  "Credit",        "Iptc.Application2.Credit"))
 
902
    {
 
903
        return false;
 
904
    }
 
905
 
 
906
    if (!setIptcTag(source,                 32,  "Source",        "Iptc.Application2.Source"))
 
907
    {
 
908
        return false;
 
909
    }
 
910
 
 
911
    if (!setIptcTag(copyright["x-default"], 128, "Copyright",     "Iptc.Application2.Copyright"))
 
912
    {
 
913
        return false;
 
914
    }
 
915
 
 
916
    if (!setIptcTag(instructions,           256, "Instructions",  "Iptc.Application2.SpecialInstructions"))
 
917
    {
 
918
        return false;
 
919
    }
 
920
 
 
921
    if (!setIptcCoreLocation(t.locationInfo()))
 
922
    {
 
923
        return false;
 
924
    }
 
925
 
 
926
    if (!setCreatorContactInfo(t.contactInfo()))
 
927
    {
 
928
        return false;
 
929
    }
708
930
 
709
931
    if (supportXmp())
710
932
    {
711
 
        if (!setXmpSubjects(t.IptcSubjects())) return false;
 
933
        if (!setXmpSubjects(t.IptcSubjects()))
 
934
        {
 
935
            return false;
 
936
        }
712
937
    }
713
938
 
714
939
    // Synchronize Iptc subjects tags with Xmp subjects tags.
720
945
        {
721
946
            str.replace(0, 3, "IPTC");
722
947
        }
 
948
 
723
949
        newList.append(str);
724
950
    }
725
 
    if (!setIptcSubjects(getIptcSubjects(), newList)) return false;
 
951
 
 
952
    if (!setIptcSubjects(getIptcSubjects(), newList))
 
953
    {
 
954
        return false;
 
955
    }
726
956
 
727
957
    return true;
728
958
}
794
1024
    return t;
795
1025
}
796
1026
 
797
 
static bool hasValidField(const QVariantList &list)
 
1027
static bool hasValidField(const QVariantList& list)
798
1028
{
799
1029
    for (QVariantList::const_iterator it = list.constBegin();
800
1030
         it != list.constEnd(); ++it)
801
1031
    {
802
1032
        if (!(*it).isNull())
 
1033
        {
803
1034
            return true;
 
1035
        }
804
1036
    }
 
1037
 
805
1038
    return false;
806
1039
}
807
1040
 
808
 
bool DMetadata::getCopyrightInformation(Template &t) const
 
1041
bool DMetadata::getCopyrightInformation(Template& t) const
809
1042
{
810
1043
    MetadataFields fields;
811
1044
    fields << MetadataInfo::IptcCoreCopyrightNotice
820
1053
    IptcCoreContactInfo contactInfo = getCreatorContactInfo();
821
1054
 
822
1055
    if (!hasValidField(metadataInfos) && contactInfo.isNull())
 
1056
    {
823
1057
        return false;
 
1058
    }
824
1059
 
825
1060
    t.setCopyright(toAltLangMap(metadataInfos[0]));
826
1061
    t.setAuthors(metadataInfos[1].toStringList());
850
1085
    QVariantList metadataInfos = getMetadataFields(fields);
851
1086
 
852
1087
    IptcCoreContactInfo info;
 
1088
 
853
1089
    if (metadataInfos.size() == 8)
854
1090
    {
855
1091
        info.city          = metadataInfos[0].toString();
861
1097
        info.phone         = metadataInfos[6].toString();
862
1098
        info.webUrl        = metadataInfos[7].toString();
863
1099
    }
 
1100
 
864
1101
    return info;
865
1102
}
866
1103
 
867
1104
bool DMetadata::setCreatorContactInfo(const IptcCoreContactInfo& info) const
868
1105
{
869
1106
    if (!supportXmp())
 
1107
    {
870
1108
        return false;
 
1109
    }
871
1110
 
872
1111
    if (!setXmpTagString("Xmp.iptc.CiAdrCity", info.city, false))
 
1112
    {
873
1113
        return false;
 
1114
    }
874
1115
 
875
1116
    if (!setXmpTagString("Xmp.iptc.CiAdrCtry", info.country, false))
 
1117
    {
876
1118
        return false;
 
1119
    }
877
1120
 
878
1121
    if (!setXmpTagString("Xmp.iptc.CiAdrExtadr", info.address, false))
 
1122
    {
879
1123
        return false;
 
1124
    }
880
1125
 
881
1126
    if (!setXmpTagString("Xmp.iptc.CiAdrPcode", info.postalCode, false))
 
1127
    {
882
1128
        return false;
 
1129
    }
883
1130
 
884
1131
    if (!setXmpTagString("Xmp.iptc.CiAdrRegion", info.provinceState, false))
 
1132
    {
885
1133
        return false;
 
1134
    }
886
1135
 
887
1136
    if (!setXmpTagString("Xmp.iptc.CiEmailWork", info.email, false))
 
1137
    {
888
1138
        return false;
 
1139
    }
889
1140
 
890
1141
    if (!setXmpTagString("Xmp.iptc.CiTelWork", info.phone, false))
 
1142
    {
891
1143
        return false;
 
1144
    }
892
1145
 
893
1146
    if (!setXmpTagString("Xmp.iptc.CiUrlWork", info.webUrl, false))
 
1147
    {
894
1148
        return false;
 
1149
    }
895
1150
 
896
1151
    return true;
897
1152
}
908
1163
    QVariantList metadataInfos = getMetadataFields(fields);
909
1164
 
910
1165
    IptcCoreLocationInfo location;
 
1166
 
911
1167
    if (fields.size() == 5)
912
1168
    {
913
1169
        location.country       = metadataInfos[0].toString();
916
1172
        location.location      = metadataInfos[3].toString();
917
1173
        location.provinceState = metadataInfos[4].toString();
918
1174
    }
 
1175
 
919
1176
    return location;
920
1177
}
921
1178
 
924
1181
    if (supportXmp())
925
1182
    {
926
1183
        if (!setXmpTagString("Xmp.photoshop.Country", location.country, false))
 
1184
        {
927
1185
            return false;
 
1186
        }
928
1187
 
929
1188
        if (!setXmpTagString("Xmp.iptc.CountryCode", location.countryCode, false))
 
1189
        {
930
1190
            return false;
 
1191
        }
931
1192
 
932
1193
        if (!setXmpTagString("Xmp.photoshop.City", location.city, false))
 
1194
        {
933
1195
            return false;
 
1196
        }
934
1197
 
935
1198
        if (!setXmpTagString("Xmp.iptc.Location", location.location, false))
 
1199
        {
936
1200
            return false;
 
1201
        }
937
1202
 
938
1203
        if (!setXmpTagString("Xmp.photoshop.State", location.provinceState, false))
 
1204
        {
939
1205
            return false;
940
 
    }
941
 
 
942
 
    if (!setIptcTag(location.country,       64,  "Country",        "Iptc.Application2.CountryName"))    return false;
943
 
    if (!setIptcTag(location.countryCode,    3,  "Country Code",   "Iptc.Application2.CountryCode"))    return false;
944
 
    if (!setIptcTag(location.city,          32,  "City",           "Iptc.Application2.City"))           return false;
945
 
    if (!setIptcTag(location.location,      32,  "SubLocation",    "Iptc.Application2.SubLocation"))    return false;
946
 
    if (!setIptcTag(location.provinceState, 32,  "Province/State", "Iptc.Application2.ProvinceState"))  return false;
 
1206
        }
 
1207
    }
 
1208
 
 
1209
    if (!setIptcTag(location.country,       64,  "Country",        "Iptc.Application2.CountryName"))
 
1210
    {
 
1211
        return false;
 
1212
    }
 
1213
 
 
1214
    if (!setIptcTag(location.countryCode,    3,  "Country Code",   "Iptc.Application2.CountryCode"))
 
1215
    {
 
1216
        return false;
 
1217
    }
 
1218
 
 
1219
    if (!setIptcTag(location.city,          32,  "City",           "Iptc.Application2.City"))
 
1220
    {
 
1221
        return false;
 
1222
    }
 
1223
 
 
1224
    if (!setIptcTag(location.location,      32,  "SubLocation",    "Iptc.Application2.SubLocation"))
 
1225
    {
 
1226
        return false;
 
1227
    }
 
1228
 
 
1229
    if (!setIptcTag(location.provinceState, 32,  "Province/State", "Iptc.Application2.ProvinceState"))
 
1230
    {
 
1231
        return false;
 
1232
    }
947
1233
 
948
1234
    return true;
949
1235
}
951
1237
QStringList DMetadata::getIptcCoreSubjects() const
952
1238
{
953
1239
    QStringList list = getXmpSubjects();
 
1240
 
954
1241
    if (!list.isEmpty())
 
1242
    {
955
1243
        return list;
 
1244
    }
956
1245
 
957
1246
    return getIptcSubjects();
958
1247
}
994
1283
    for (QStringList::Iterator it = lensExifTags.begin(); it != lensExifTags.end(); ++it)
995
1284
    {
996
1285
        lens = getExifTagString((*it).toAscii());
 
1286
 
997
1287
        if ( !lens.isEmpty() &&
998
1288
             !(lens.startsWith('(') && lens.endsWith(')')) )   // To prevent undecoded tag values from Exiv2 as "(65535)".
 
1289
        {
999
1290
            return lens;
 
1291
        }
1000
1292
    }
1001
1293
 
1002
1294
    // -------------------------------------------------------------------
1003
1295
    // Try to get Lens Data information from XMP.
1004
1296
    // XMP aux tags.
1005
1297
    lens = getXmpTagString("Xmp.aux.Lens");
 
1298
 
1006
1299
    if (lens.isEmpty())
1007
1300
    {
1008
1301
        // XMP M$ tags (Lens Maker + Lens Model).
1009
1302
        lens = getXmpTagString("Xmp.MicrosoftPhoto.LensManufacturer");
 
1303
 
1010
1304
        if (!lens.isEmpty())
 
1305
        {
1011
1306
            lens.append(" ");
 
1307
        }
1012
1308
 
1013
1309
        lens.append(getXmpTagString("Xmp.MicrosoftPhoto.LensModel"));
1014
1310
    }
1020
1316
{
1021
1317
    // Check if Exif data contains an ICC color profile.
1022
1318
    QByteArray data = getExifTagData("Exif.Image.InterColorProfile");
 
1319
 
1023
1320
    if (!data.isNull())
1024
1321
    {
1025
1322
        kDebug() << "Found an ICC profile in Exif metadata";
1057
1354
    return setIptcTagString(tagKey, truncatedText);    // returns false if failed
1058
1355
}
1059
1356
 
1060
 
inline QVariant DMetadata::fromExifOrXmp(const char *exifTagName, const char *xmpTagName) const
 
1357
inline QVariant DMetadata::fromExifOrXmp(const char* exifTagName, const char* xmpTagName) const
1061
1358
{
1062
1359
    QVariant var;
1063
1360
 
1064
1361
    if (exifTagName)
1065
1362
    {
1066
1363
        var = getExifTagVariant(exifTagName, false);
 
1364
 
1067
1365
        if (!var.isNull())
 
1366
        {
1068
1367
            return var;
 
1368
        }
1069
1369
    }
1070
1370
 
1071
1371
    if (xmpTagName)
1072
1372
    {
1073
1373
        var = getXmpTagVariant(xmpTagName);
 
1374
 
1074
1375
        if (!var.isNull())
 
1376
        {
1075
1377
            return var;
 
1378
        }
1076
1379
    }
1077
1380
 
1078
1381
    return var;
1079
1382
}
1080
1383
 
1081
 
inline QVariant DMetadata::fromIptcOrXmp(const char *iptcTagName, const char *xmpTagName) const
 
1384
inline QVariant DMetadata::fromIptcOrXmp(const char* iptcTagName, const char* xmpTagName) const
1082
1385
{
1083
1386
    if (iptcTagName)
1084
1387
    {
1085
1388
        QString iptcValue = getIptcTagString(iptcTagName);
 
1389
 
1086
1390
        if (!iptcValue.isNull())
 
1391
        {
1087
1392
            return iptcValue;
 
1393
        }
1088
1394
    }
1089
1395
 
1090
1396
    if (xmpTagName)
1091
1397
    {
1092
1398
        QVariant var = getXmpTagVariant(xmpTagName);
 
1399
 
1093
1400
        if (!var.isNull())
 
1401
        {
1094
1402
            return var;
 
1403
        }
1095
1404
    }
1096
1405
 
1097
1406
    return QVariant(QVariant::String);
1098
1407
}
1099
1408
 
1100
 
inline QVariant DMetadata::fromIptcEmulateList(const char *iptcTagName) const
 
1409
inline QVariant DMetadata::fromIptcEmulateList(const char* iptcTagName) const
1101
1410
{
1102
1411
    return toStringListVariant(getIptcTagsStringList(iptcTagName));
1103
1412
}
1104
1413
 
1105
 
inline QVariant DMetadata::fromXmpList(const char *xmpTagName) const
 
1414
inline QVariant DMetadata::fromXmpList(const char* xmpTagName) const
1106
1415
{
1107
1416
    QVariant var = getXmpTagVariant(xmpTagName);
1108
1417
 
1109
1418
    if (var.isNull())
 
1419
    {
1110
1420
        return QVariant(QVariant::StringList);
 
1421
    }
 
1422
 
1111
1423
    return var;
1112
1424
}
1113
1425
 
1114
 
inline QVariant DMetadata::fromIptcEmulateLangAlt(const char *iptcTagName) const
 
1426
inline QVariant DMetadata::fromIptcEmulateLangAlt(const char* iptcTagName) const
1115
1427
{
1116
1428
    QString str = getIptcTagString(iptcTagName);
 
1429
 
1117
1430
    if (str.isNull())
 
1431
    {
1118
1432
        return QVariant(QVariant::Map);
 
1433
    }
1119
1434
 
1120
1435
    QMap<QString, QVariant> map;
1121
1436
    map["x-default"] = str;
1122
1437
    return map;
1123
1438
}
1124
1439
 
1125
 
inline QVariant DMetadata::fromXmpLangAlt(const char *xmpTagName) const
 
1440
inline QVariant DMetadata::fromXmpLangAlt(const char* xmpTagName) const
1126
1441
{
1127
1442
    QVariant var = getXmpTagVariant(xmpTagName);
1128
1443
 
1129
1444
    if (var.isNull())
 
1445
    {
1130
1446
        return QVariant(QVariant::Map);
 
1447
    }
 
1448
 
1131
1449
    return var;
1132
1450
}
1133
1451
 
1134
 
inline QVariant DMetadata::toStringListVariant(const QStringList &list) const
 
1452
inline QVariant DMetadata::toStringListVariant(const QStringList& list) const
1135
1453
{
1136
1454
    if (list.isEmpty())
 
1455
    {
1137
1456
        return QVariant(QVariant::StringList);
 
1457
    }
1138
1458
 
1139
1459
    return list;
1140
1460
}
1155
1475
        case MetadataInfo::Description:
1156
1476
        {
1157
1477
            QVariant var = fromXmpLangAlt("Xmp.dc.description");
 
1478
 
1158
1479
            if (!var.isNull())
 
1480
            {
1159
1481
                return var;
 
1482
            }
1160
1483
 
1161
1484
            var = fromXmpLangAlt("Xmp.tiff.ImageDescription");
 
1485
 
1162
1486
            if (!var.isNull())
 
1487
            {
1163
1488
                return var;
 
1489
            }
1164
1490
 
1165
1491
            return fromIptcEmulateLangAlt("Iptc.Application2.Caption");
1166
1492
        }
1169
1495
        case MetadataInfo::Title:
1170
1496
        {
1171
1497
            QVariant var = fromXmpLangAlt("Xmp.dc.title");
 
1498
 
1172
1499
            if (!var.isNull())
 
1500
            {
1173
1501
                return var;
 
1502
            }
1174
1503
 
1175
1504
            return fromIptcEmulateLangAlt("Iptc.Application2.ObjectName");
1176
1505
        }
1202
1531
        case MetadataInfo::Aperture:
1203
1532
        {
1204
1533
            QVariant var = fromExifOrXmp("Exif.Photo.FNumber", "Xmp.exif.FNumber");
 
1534
 
1205
1535
            if (var.isNull())
1206
1536
            {
1207
1537
                var = fromExifOrXmp("Exif.Photo.ApertureValue", "Xmp.exif.ApertureValue");
 
1538
 
1208
1539
                if (!var.isNull())
 
1540
                {
1209
1541
                    var = apexApertureToFNumber(var.toDouble());
 
1542
                }
1210
1543
            }
 
1544
 
1211
1545
            return var;
1212
1546
        }
1213
1547
        case MetadataInfo::FocalLength:
1217
1551
        case MetadataInfo::ExposureTime:
1218
1552
        {
1219
1553
            QVariant var = fromExifOrXmp("Exif.Photo.ExposureTime", "Xmp.exif.ExposureTime");
 
1554
 
1220
1555
            if (var.isNull())
1221
1556
            {
1222
1557
                var = fromExifOrXmp("Exif.Photo.ShutterSpeedValue", "Xmp.exif.ShutterSpeedValue");
 
1558
 
1223
1559
                if (!var.isNull())
 
1560
                {
1224
1561
                    var = apexShutterSpeedToExposureTime(var.toDouble());
 
1562
                }
1225
1563
            }
 
1564
 
1226
1565
            return var;
1227
1566
        }
1228
1567
        case MetadataInfo::ExposureProgram:
1233
1572
        {
1234
1573
            QVariant var = fromExifOrXmp("Exif.Photo.ISOSpeedRatings", "Xmp.exif.ISOSpeedRatings");
1235
1574
            //if (var.isNull())
1236
 
                // TODO: has this ISO format??? We must convert to the format of ISOSpeedRatings!
1237
 
              //  var = fromExifOrXmp("Exif.Photo.ExposureIndex", "Xmp.exif.ExposureIndex");
 
1575
            // TODO: has this ISO format??? We must convert to the format of ISOSpeedRatings!
 
1576
            //  var = fromExifOrXmp("Exif.Photo.ExposureIndex", "Xmp.exif.ExposureIndex");
1238
1577
            return var;
1239
1578
        }
1240
1579
        case MetadataInfo::FlashMode:
1256
1595
        case MetadataInfo::LongitudeNumber:
1257
1596
        {
1258
1597
            double longitude;
 
1598
 
1259
1599
            if (getGPSLongitudeNumber(&longitude))
 
1600
            {
1260
1601
                return longitude;
 
1602
            }
1261
1603
            else
 
1604
            {
1262
1605
                return QVariant(QVariant::Double);
 
1606
            }
1263
1607
        }
1264
1608
        case MetadataInfo::Latitude:
1265
1609
            return getGPSLatitudeString();
1266
1610
        case MetadataInfo::LatitudeNumber:
1267
1611
        {
1268
1612
            double latitude;
 
1613
 
1269
1614
            if (getGPSLatitudeNumber(&latitude))
 
1615
            {
1270
1616
                return latitude;
 
1617
            }
1271
1618
            else
 
1619
            {
1272
1620
                return QVariant(QVariant::Double);
 
1621
            }
1273
1622
        }
1274
1623
        case MetadataInfo::Altitude:
1275
1624
        {
1276
1625
            double altitude;
 
1626
 
1277
1627
            if (getGPSAltitude(&altitude))
 
1628
            {
1278
1629
                return altitude;
 
1630
            }
1279
1631
            else
 
1632
            {
1280
1633
                return QVariant(QVariant::Double);
 
1634
            }
1281
1635
        }
1282
1636
        case MetadataInfo::PositionOrientation:
1283
1637
        case MetadataInfo::PositionTilt:
1292
1646
        case MetadataInfo::IptcCoreCopyrightNotice:
1293
1647
        {
1294
1648
            QVariant var = fromXmpLangAlt("Xmp.dc.rights");
 
1649
 
1295
1650
            if (!var.isNull())
 
1651
            {
1296
1652
                return var;
 
1653
            }
1297
1654
 
1298
1655
            var = fromXmpLangAlt("Xmp.tiff.Copyright");
 
1656
 
1299
1657
            if (!var.isNull())
 
1658
            {
1300
1659
                return var;
 
1660
            }
1301
1661
 
1302
1662
            return fromIptcEmulateLangAlt("Iptc.Application2.Copyright");
1303
1663
        }
1304
1664
        case MetadataInfo::IptcCoreCreator:
1305
1665
        {
1306
1666
            QVariant var = fromXmpList("Xmp.dc.creator");
 
1667
 
1307
1668
            if (!var.isNull())
 
1669
            {
1308
1670
                return var;
 
1671
            }
1309
1672
 
1310
1673
            QString artist = getXmpTagString("Xmp.tiff.Artist");
 
1674
 
1311
1675
            if (!artist.isNull())
1312
1676
            {
1313
1677
                QStringList list;
1332
1696
        case MetadataInfo::IptcCoreLocationInfo:
1333
1697
        {
1334
1698
            IptcCoreLocationInfo location = getIptcCoreLocation();
 
1699
 
1335
1700
            if (location.isNull())
 
1701
            {
1336
1702
                return QVariant();
 
1703
            }
 
1704
 
1337
1705
            return QVariant::fromValue(location);
1338
1706
        }
1339
1707
        case MetadataInfo::IptcCoreCountryCode:
1359
1727
        case MetadataInfo::IptcCoreContactInfo:
1360
1728
        {
1361
1729
            IptcCoreContactInfo info = getCreatorContactInfo();
 
1730
 
1362
1731
            if (info.isNull())
 
1732
            {
1363
1733
                return QVariant();
 
1734
            }
 
1735
 
1364
1736
            return QVariant::fromValue(info);
1365
1737
        }
1366
1738
        case MetadataInfo::IptcCoreContactInfoCity:
1407
1779
        case MetadataInfo::DigitizationDate:
1408
1780
            return value.toDateTime().toString(Qt::LocaleDate);
1409
1781
        case MetadataInfo::Orientation:
 
1782
 
1410
1783
            switch (value.toInt())
1411
1784
            {
1412
 
                // Example why the English text differs from the enum names: ORIENTATION_ROT_90.
1413
 
                // Rotation by 90 degrees is right (clockwise) rotation.
1414
 
                // But: The enum names describe what needs to be done to get the image right again.
1415
 
                // And an image that needs to be rotated 90 degrees is currently rotated 270 degrees = left.
 
1785
                    // Example why the English text differs from the enum names: ORIENTATION_ROT_90.
 
1786
                    // Rotation by 90 degrees is right (clockwise) rotation.
 
1787
                    // But: The enum names describe what needs to be done to get the image right again.
 
1788
                    // And an image that needs to be rotated 90 degrees is currently rotated 270 degrees = left.
1416
1789
 
1417
1790
                case ORIENTATION_UNSPECIFIED:
1418
1791
                    return i18n("Unspecified");
1473
1846
            int degrees, minutes;
1474
1847
            double seconds;
1475
1848
            char directionRef;
 
1849
 
1476
1850
            if (!convertToUserPresentableNumbers(value.toString(), &degrees, &minutes, &seconds, &directionRef))
 
1851
            {
1477
1852
                return QString();
 
1853
            }
 
1854
 
1478
1855
            QString direction = (directionRef == 'W') ?
1479
1856
                                i18nc("For use in longitude coordinate", "West") : i18nc("For use in longitude coordinate", "East");
1480
1857
            return QString("%1%2%3%4%L5%6 %7").arg(degrees).arg(QChar(0xB0))
1481
 
                                              .arg(minutes).arg(QChar(0x2032))
1482
 
                                              .arg(seconds, 'f').arg(QChar(0x2033)).arg(direction);
 
1858
                   .arg(minutes).arg(QChar(0x2032))
 
1859
                   .arg(seconds, 'f').arg(QChar(0x2033)).arg(direction);
1483
1860
        }
1484
1861
        case MetadataInfo::LongitudeNumber:
1485
1862
        {
1490
1867
            QString direction = (directionRef == 'W') ?
1491
1868
                                i18nc("For use in longitude coordinate", "West") : i18nc("For use in longitude coordinate", "East");
1492
1869
            return QString("%1%2%3%4%L5%6 %7").arg(degrees).arg(QChar(0xB0))
1493
 
                                              .arg(minutes).arg(QChar(0x2032))
1494
 
                                              .arg(seconds, 'f').arg(QChar(0x2033)).arg(direction);
 
1870
                   .arg(minutes).arg(QChar(0x2032))
 
1871
                   .arg(seconds, 'f').arg(QChar(0x2033)).arg(direction);
1495
1872
        }
1496
1873
        case MetadataInfo::Latitude:
1497
1874
        {
1498
1875
            int degrees, minutes;
1499
1876
            double seconds;
1500
1877
            char directionRef;
 
1878
 
1501
1879
            if (!convertToUserPresentableNumbers(value.toString(), &degrees, &minutes, &seconds, &directionRef))
 
1880
            {
1502
1881
                return QString();
 
1882
            }
 
1883
 
1503
1884
            QString direction = (directionRef == 'N') ?
1504
1885
                                i18nc("For use in latitude coordinate", "North") : i18nc("For use in latitude coordinate", "South");
1505
1886
            return QString("%1%2%3%4%L5%6 %7").arg(degrees).arg(QChar(0xB0))
1506
 
                                              .arg(minutes).arg(QChar(0x2032))
1507
 
                                              .arg(seconds, 'f').arg(QChar(0x2033)).arg(direction);
 
1887
                   .arg(minutes).arg(QChar(0x2032))
 
1888
                   .arg(seconds, 'f').arg(QChar(0x2033)).arg(direction);
1508
1889
        }
1509
1890
        case MetadataInfo::LatitudeNumber:
1510
1891
        {
1515
1896
            QString direction = (directionRef == 'N') ?
1516
1897
                                i18nc("For use in latitude coordinate", "North") : i18nc("For use in latitude coordinate", "North");
1517
1898
            return QString("%1%2%3%4%L5%6 %7").arg(degrees).arg(QChar(0xB0))
1518
 
                                              .arg(minutes).arg(QChar(0x2032))
1519
 
                                              .arg(seconds, 'f').arg(QChar(0x2033)).arg(direction);
 
1899
                   .arg(minutes).arg(QChar(0x2032))
 
1900
                   .arg(seconds, 'f').arg(QChar(0x2033)).arg(direction);
1520
1901
        }
1521
1902
        case MetadataInfo::Altitude:
1522
1903
        {
1534
1915
        case MetadataInfo::PositionDescription:
1535
1916
            return value.toString();
1536
1917
 
1537
 
        // Lang Alt
 
1918
            // Lang Alt
1538
1919
        case MetadataInfo::IptcCoreCopyrightNotice:
1539
1920
        case MetadataInfo::IptcCoreRightsUsageTerms:
1540
1921
        case MetadataInfo::Description:
1541
1922
        case MetadataInfo::Title:
1542
1923
        {
1543
1924
            QMap<QString, QVariant> map = value.toMap();
 
1925
 
1544
1926
            // the most common cases
1545
1927
            if (map.isEmpty())
 
1928
            {
1546
1929
                return QString();
 
1930
            }
1547
1931
            else if (map.size() == 1)
 
1932
            {
1548
1933
                return map.begin().value().toString();
 
1934
            }
 
1935
 
1549
1936
            // Try "en-us"
1550
 
            KLocale *locale = KGlobal::locale();
 
1937
            KLocale* locale = KGlobal::locale();
1551
1938
            QString spec = locale->language().toLower() + '-' + locale->country().toLower();
 
1939
 
1552
1940
            if (map.contains(spec))
 
1941
            {
1553
1942
                return map[spec].toString();
 
1943
            }
1554
1944
 
1555
1945
            // Try "en-"
1556
1946
            QStringList keys = map.keys();
1557
1947
            QRegExp exp(locale->language().toLower() + '-');
1558
1948
            QStringList matches = keys.filter(exp);
 
1949
 
1559
1950
            if (!matches.isEmpty())
 
1951
            {
1560
1952
                return map[matches.first()].toString();
 
1953
            }
1561
1954
 
1562
1955
            // return default
1563
1956
            if (map.contains("x-default"))
 
1957
            {
1564
1958
                return map["x-default"].toString();
 
1959
            }
1565
1960
 
1566
1961
            // return first entry
1567
1962
            return map.begin().value().toString();
1573
1968
        case MetadataInfo::IptcCoreSubjectCode:
1574
1969
            return value.toStringList().join(" ");
1575
1970
 
1576
 
        // Text
 
1971
            // Text
1577
1972
        case MetadataInfo::Comment:
1578
1973
        case MetadataInfo::CommentJfif:
1579
1974
        case MetadataInfo::CommentExif:
1604
1999
    Q_ASSERT(size == values.size());
1605
2000
 
1606
2001
    QStringList list;
 
2002
 
1607
2003
    for (int i=0; i<size; ++i)
1608
2004
    {
1609
2005
        list << valueToString(values[i], fields[i]);
1610
2006
    }
 
2007
 
1611
2008
    return list;
1612
2009
}
1613
2010
 
1615
2012
{
1616
2013
    QMap<int, QString> map;
1617
2014
    int min, max;
 
2015
 
1618
2016
    switch (field)
1619
2017
    {
1620
2018
        case MetadataInfo::Orientation:                      /// Int, enum from libkexiv2
1658
2056
    {
1659
2057
        map[i] = valueToString(i, field);
1660
2058
    }
 
2059
 
1661
2060
    return map;
1662
2061
}
1663
2062
 
1665
2064
{
1666
2065
    // convert from APEX. See Exif spec, Annex C.
1667
2066
    if (aperture == 0.0)
 
2067
    {
1668
2068
        return 1;
 
2069
    }
1669
2070
    else if (aperture == 1.0)
 
2071
    {
1670
2072
        return 1.4;
 
2073
    }
1671
2074
    else if (aperture == 2.0)
 
2075
    {
1672
2076
        return 2;
 
2077
    }
1673
2078
    else if (aperture == 3.0)
 
2079
    {
1674
2080
        return 2.8;
 
2081
    }
1675
2082
    else if (aperture == 4.0)
 
2083
    {
1676
2084
        return 4;
 
2085
    }
1677
2086
    else if (aperture == 5.0)
 
2087
    {
1678
2088
        return 5.6;
 
2089
    }
1679
2090
    else if (aperture == 6.0)
 
2091
    {
1680
2092
        return 8;
 
2093
    }
1681
2094
    else if (aperture == 7.0)
 
2095
    {
1682
2096
        return 11;
 
2097
    }
1683
2098
    else if (aperture == 8.0)
 
2099
    {
1684
2100
        return 16;
 
2101
    }
1685
2102
    else if (aperture == 9.0)
 
2103
    {
1686
2104
        return 22;
 
2105
    }
1687
2106
    else if (aperture == 10.0)
 
2107
    {
1688
2108
        return 32;
 
2109
    }
 
2110
 
1689
2111
    return exp(log(2) * aperture / 2.0);
1690
2112
}
1691
2113
 
1693
2115
{
1694
2116
    // convert from APEX. See Exif spec, Annex C.
1695
2117
    if (shutterSpeed == -5.0)
 
2118
    {
1696
2119
        return 30;
 
2120
    }
1697
2121
    else if (shutterSpeed == -4.0)
 
2122
    {
1698
2123
        return 15;
 
2124
    }
1699
2125
    else if (shutterSpeed == -3.0)
 
2126
    {
1700
2127
        return 8;
 
2128
    }
1701
2129
    else if (shutterSpeed == -2.0)
 
2130
    {
1702
2131
        return 4;
 
2132
    }
1703
2133
    else if (shutterSpeed == -1.0)
 
2134
    {
1704
2135
        return 2;
 
2136
    }
1705
2137
    else if (shutterSpeed == 0.0)
 
2138
    {
1706
2139
        return 1;
 
2140
    }
1707
2141
    else if (shutterSpeed == 1.0)
 
2142
    {
1708
2143
        return 0.5;
 
2144
    }
1709
2145
    else if (shutterSpeed == 2.0)
 
2146
    {
1710
2147
        return 0.25;
 
2148
    }
1711
2149
    else if (shutterSpeed == 3.0)
 
2150
    {
1712
2151
        return 0.125;
 
2152
    }
1713
2153
    else if (shutterSpeed == 4.0)
 
2154
    {
1714
2155
        return 1.0 / 15.0;
 
2156
    }
1715
2157
    else if (shutterSpeed == 5.0)
 
2158
    {
1716
2159
        return 1.0 / 30.0;
 
2160
    }
1717
2161
    else if (shutterSpeed == 6.0)
 
2162
    {
1718
2163
        return 1.0 / 60.0;
 
2164
    }
1719
2165
    else if (shutterSpeed == 7.0)
1720
 
        return 0.008; // 1/125
 
2166
    {
 
2167
        return 0.008;    // 1/125
 
2168
    }
1721
2169
    else if (shutterSpeed == 8.0)
1722
 
        return 0.004; // 1/250
 
2170
    {
 
2171
        return 0.004;    // 1/250
 
2172
    }
1723
2173
    else if (shutterSpeed == 9.0)
1724
 
        return 0.002; // 1/500
 
2174
    {
 
2175
        return 0.002;    // 1/500
 
2176
    }
1725
2177
    else if (shutterSpeed == 10.0)
1726
 
        return 0.001; // 1/1000
 
2178
    {
 
2179
        return 0.001;    // 1/1000
 
2180
    }
1727
2181
    else if (shutterSpeed == 11.0)
1728
 
        return 0.0005; // 1/2000
 
2182
    {
 
2183
        return 0.0005;    // 1/2000
 
2184
    }
1729
2185
    // additions by me
1730
2186
    else if (shutterSpeed == 12.0)
1731
 
        return 0.00025; // 1/4000
 
2187
    {
 
2188
        return 0.00025;    // 1/4000
 
2189
    }
1732
2190
    else if (shutterSpeed == 13.0)
1733
 
        return 0.000125; // 1/8000
 
2191
    {
 
2192
        return 0.000125;    // 1/8000
 
2193
    }
1734
2194
 
1735
2195
    return exp( - log(2) * shutterSpeed);
1736
2196
}
1737
2197
 
1738
 
KExiv2::AltLangMap DMetadata::toAltLangMap(const QVariant &var)
 
2198
KExiv2::AltLangMap DMetadata::toAltLangMap(const QVariant& var)
1739
2199
{
1740
2200
    KExiv2::AltLangMap map;
1741
2201
 
1742
2202
    if (var.isNull())
 
2203
    {
1743
2204
        return map;
 
2205
    }
1744
2206
 
1745
2207
    switch (var.type())
1746
2208
    {
1750
2212
        case QVariant::Map:
1751
2213
        {
1752
2214
            QMap<QString, QVariant> varMap = var.toMap();
 
2215
 
1753
2216
            for (QMap<QString, QVariant>::const_iterator it = varMap.constBegin(); it != varMap.constEnd(); ++it)
 
2217
            {
1754
2218
                map.insert(it.key(), it.value().toString());
 
2219
            }
 
2220
 
1755
2221
            break;
1756
2222
        }
1757
2223
        default:
1763
2229
 
1764
2230
// ---------- Pushed to libkexiv2 for KDE 4.4 --------------
1765
2231
 
1766
 
bool DMetadata::addToXmpTagStringBag(const char *xmpTagName, const QStringList& entriesToAdd,
 
2232
bool DMetadata::addToXmpTagStringBag(const char* xmpTagName, const QStringList& entriesToAdd,
1767
2233
                                     bool setProgramName) const
1768
2234
{
1769
 
//#ifdef _XMP_SUPPORT_
 
2235
    //#ifdef _XMP_SUPPORT_
1770
2236
 
1771
2237
    if (!setProgramId(setProgramName))
 
2238
    {
1772
2239
        return false;
 
2240
    }
1773
2241
 
1774
2242
    QStringList oldEntries = getXmpTagStringBag(xmpTagName, false);
1775
2243
    QStringList newEntries = entriesToAdd;
1778
2246
    for (QStringList::const_iterator it = oldEntries.constBegin(); it != oldEntries.constEnd(); ++it )
1779
2247
    {
1780
2248
        if (!newEntries.contains(*it))
 
2249
        {
1781
2250
            newEntries.append(*it);
 
2251
        }
1782
2252
    }
1783
2253
 
1784
2254
    if (setXmpTagStringBag(xmpTagName, newEntries, false))
 
2255
    {
1785
2256
        return true;
 
2257
    }
1786
2258
 
1787
 
//#endif // _XMP_SUPPORT_
 
2259
    //#endif // _XMP_SUPPORT_
1788
2260
 
1789
2261
    return false;
1790
2262
}
1791
2263
 
1792
 
bool DMetadata::removeFromXmpTagStringBag(const char *xmpTagName, const QStringList& entriesToRemove,
1793
 
                                          bool setProgramName) const
 
2264
bool DMetadata::removeFromXmpTagStringBag(const char* xmpTagName, const QStringList& entriesToRemove,
 
2265
        bool setProgramName) const
1794
2266
{
1795
 
//#ifdef _XMP_SUPPORT_
 
2267
    //#ifdef _XMP_SUPPORT_
1796
2268
 
1797
2269
    if (!setProgramId(setProgramName))
 
2270
    {
1798
2271
        return false;
 
2272
    }
1799
2273
 
1800
2274
    QStringList currentEntries = getXmpTagStringBag(xmpTagName, false);
1801
2275
    QStringList newEntries;
1804
2278
    for (QStringList::const_iterator it = currentEntries.constBegin(); it != currentEntries.constEnd(); ++it )
1805
2279
    {
1806
2280
        if (!entriesToRemove.contains(*it))
 
2281
        {
1807
2282
            newEntries.append(*it);
 
2283
        }
1808
2284
    }
1809
2285
 
1810
2286
    if (setXmpTagStringBag(xmpTagName, newEntries, false))
 
2287
    {
1811
2288
        return true;
 
2289
    }
1812
2290
 
1813
 
//#endif // _XMP_SUPPORT_
 
2291
    //#endif // _XMP_SUPPORT_
1814
2292
 
1815
2293
    return false;
1816
2294
}