~ubuntu-branches/ubuntu/vivid/digikam/vivid

1.7.1 by Mark Purcell
Import upstream version 2.2.0
1
/* ============================================================
2
 *
3
 * This file is a part of digiKam project
4
 * http://www.digikam.org
5
 *
6
 * Date        : 2008-05-12
7
 * Description : Access to copyright info of an image in the database
8
 *
9
 * Copyright (C) 2008-2009 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
10
 * Copyright (C) 2009 by Gilles Caulier <caulier dot gilles at gmail dot com>
11
 *
12
 * This program is free software; you can redistribute it
13
 * and/or modify it under the terms of the GNU General
14
 * Public License as published by the Free Software Foundation;
15
 * either version 2, or (at your option)
16
 * any later version.
17
 *
18
 * This program is distributed in the hope that it will be useful,
19
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
 * GNU General Public License for more details.
22
 *
23
 * ============================================================ */
24
25
#include "imagecopyright.h"
26
27
// KDE includes
28
29
30
#include <klocale.h>
31
#include <kglobal.h>
32
33
// Local includes
34
35
#include "albumdb.h"
36
#include "databaseaccess.h"
37
#include "imagescanner.h"
38
#include "template.h"
39
40
namespace Digikam
41
{
42
43
class ImageCopyrightCache
44
{
45
public:
46
47
    ImageCopyrightCache(ImageCopyright* object)
48
        : object(object)
49
    {
50
        // set this as cache
51
        object->m_cache = this;
52
        // read all properties
53
        infos = DatabaseAccess().db()->getImageCopyright(object->m_id, QString());
54
    }
55
    ~ImageCopyrightCache()
56
    {
57
        object->m_cache = 0;
58
    }
59
60
    QList<CopyrightInfo> infos;
61
62
private:
63
64
    ImageCopyright* object;
65
};
66
67
ImageCopyright::ImageCopyright(qlonglong imageid)
68
    : m_id(imageid), m_cache(0)
69
{
70
}
71
72
ImageCopyright::ImageCopyright()
73
    : m_id(0), m_cache(0)
74
{
75
}
76
77
ImageCopyright::ImageCopyright(const ImageCopyright& other)
78
    : m_id(other.m_id), m_cache(0)
79
{
80
    // the cache is only short-lived, to keep complexity low
81
}
82
83
ImageCopyright::~ImageCopyright()
84
{
85
    delete m_cache;
86
    m_cache = 0;
87
}
88
89
ImageCopyright& ImageCopyright::operator=(const ImageCopyright& other)
90
{
91
    delete m_cache;
92
    m_cache = 0;
93
94
    m_id = other.m_id;
95
    return *this;
96
}
97
98
void ImageCopyright::replaceFrom(const ImageCopyright& source)
99
{
100
    if (!m_id)
101
    {
102
        return;
103
    }
104
105
    DatabaseAccess access;
106
    access.db()->removeImageCopyrightProperties(m_id);
107
108
    if (!source.m_id)
109
    {
110
        return;
111
    }
112
113
    QList<CopyrightInfo> infos = access.db()->getImageCopyright(source.m_id, QString());
1.7.4 by Mark Purcell
Import upstream version 2.5.0
114
    foreach(const CopyrightInfo& info, infos)
1.7.1 by Mark Purcell
Import upstream version 2.2.0
115
    {
116
        access.db()->setImageCopyrightProperty(m_id, info.property, info.value,
117
                                               info.extraValue, AlbumDB::PropertyNoConstraint);
118
    }
119
}
120
121
QStringList ImageCopyright::creator() const
122
{
123
    QList<CopyrightInfo> infos = copyrightInfos(ImageScanner::iptcCorePropertyName(MetadataInfo::IptcCoreCreator));
124
    QStringList list;
125
    foreach(const CopyrightInfo& info, infos)
126
    {
127
        list << info.value;
128
    }
129
    return list;
130
}
131
132
void ImageCopyright::setCreator(const QString& creator, ReplaceMode mode)
133
{
134
    AlbumDB::CopyrightPropertyUnique uniqueness;
135
136
    if (mode == ReplaceAllEntries)
137
    {
138
        uniqueness = AlbumDB::PropertyUnique;
139
    }
140
    else
141
    {
142
        uniqueness = AlbumDB::PropertyNoConstraint;
143
    }
144
145
    DatabaseAccess().db()->setImageCopyrightProperty(m_id, ImageScanner::iptcCorePropertyName(MetadataInfo::IptcCoreCreator),
146
            creator, QString(), uniqueness);
147
}
148
149
void ImageCopyright::removeCreators()
150
{
151
    removeProperties(ImageScanner::iptcCorePropertyName(MetadataInfo::IptcCoreCreator));
152
}
153
154
QString ImageCopyright::provider() const
155
{
156
    return readSimpleProperty(ImageScanner::iptcCorePropertyName(MetadataInfo::IptcCoreProvider));
157
}
158
159
void ImageCopyright::setProvider(const QString& provider)
160
{
161
    setSimpleProperty(ImageScanner::iptcCorePropertyName(MetadataInfo::IptcCoreProvider), provider);
162
}
163
164
void ImageCopyright::removeProvider()
165
{
166
    removeProperties(ImageScanner::iptcCorePropertyName(MetadataInfo::IptcCoreProvider));
167
}
168
169
QString ImageCopyright::copyrightNotice(const QString& languageCode)
170
{
171
    return readLanguageProperty(ImageScanner::iptcCorePropertyName(MetadataInfo::IptcCoreCopyrightNotice), languageCode);
172
}
173
174
KExiv2Iface::KExiv2::AltLangMap ImageCopyright::allCopyrightNotices()
175
{
176
    return readLanguageProperties(ImageScanner::iptcCorePropertyName(MetadataInfo::IptcCoreCopyrightNotice));
177
}
178
179
void ImageCopyright::setCopyrightNotice(const QString& notice, const QString& languageCode, ReplaceMode mode)
180
{
181
    setLanguageProperty(ImageScanner::iptcCorePropertyName(MetadataInfo::IptcCoreCopyrightNotice), notice, languageCode, mode);
182
}
183
184
void ImageCopyright::removeCopyrightNotices()
185
{
186
    removeProperties(ImageScanner::iptcCorePropertyName(MetadataInfo::IptcCoreCopyrightNotice));
187
}
188
189
QString ImageCopyright::rightsUsageTerms(const QString& languageCode)
190
{
191
    return readLanguageProperty(ImageScanner::iptcCorePropertyName(MetadataInfo::IptcCoreRightsUsageTerms), languageCode);
192
}
193
194
KExiv2Iface::KExiv2::AltLangMap ImageCopyright::allRightsUsageTerms()
195
{
196
    return readLanguageProperties(ImageScanner::iptcCorePropertyName(MetadataInfo::IptcCoreRightsUsageTerms));
197
}
198
199
void ImageCopyright::setRightsUsageTerms(const QString& term, const QString& languageCode, ReplaceMode mode)
200
{
201
    setLanguageProperty(ImageScanner::iptcCorePropertyName(MetadataInfo::IptcCoreRightsUsageTerms), term, languageCode, mode);
202
}
203
204
void ImageCopyright::removeRightsUsageTerms()
205
{
206
    removeProperties(ImageScanner::iptcCorePropertyName(MetadataInfo::IptcCoreRightsUsageTerms));
207
}
208
209
QString ImageCopyright::source()
210
{
211
    return readSimpleProperty(ImageScanner::iptcCorePropertyName(MetadataInfo::IptcCoreSource));
212
}
213
214
void ImageCopyright::setSource(const QString& source)
215
{
216
    setSimpleProperty(ImageScanner::iptcCorePropertyName(MetadataInfo::IptcCoreSource), source);
217
}
218
219
void ImageCopyright::removeSource()
220
{
221
    removeProperties(ImageScanner::iptcCorePropertyName(MetadataInfo::IptcCoreSource));
222
}
223
224
QString ImageCopyright::creatorJobTitle() const
225
{
226
    return readSimpleProperty(ImageScanner::iptcCorePropertyName(MetadataInfo::IptcCoreCreatorJobTitle));
227
}
228
229
void ImageCopyright::setCreatorJobTitle(const QString& title)
230
{
231
    setSimpleProperty(ImageScanner::iptcCorePropertyName(MetadataInfo::IptcCoreCreatorJobTitle), title);
232
}
233
234
void ImageCopyright::removeCreatorJobTitle()
235
{
236
    removeProperties(ImageScanner::iptcCorePropertyName(MetadataInfo::IptcCoreCreatorJobTitle));
237
}
238
239
QString ImageCopyright::instructions()
240
{
241
    return readSimpleProperty(ImageScanner::iptcCorePropertyName(MetadataInfo::IptcCoreInstructions));
242
}
243
244
void ImageCopyright::setInstructions(const QString& instructions)
245
{
246
    setSimpleProperty(ImageScanner::iptcCorePropertyName(MetadataInfo::IptcCoreInstructions), instructions);
247
}
248
249
void ImageCopyright::removeInstructions()
250
{
251
    removeProperties(ImageScanner::iptcCorePropertyName(MetadataInfo::IptcCoreInstructions));
252
}
253
254
IptcCoreContactInfo ImageCopyright::contactInfo()
255
{
256
    IptcCoreContactInfo info;
257
    info.city = readSimpleProperty(ImageScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoCity));
258
    info.country = readSimpleProperty(ImageScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoCountry));
259
    info.address = readSimpleProperty(ImageScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoAddress));
260
    info.postalCode = readSimpleProperty(ImageScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoPostalCode));
261
    info.provinceState = readSimpleProperty(ImageScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoProvinceState));
262
    info.email = readSimpleProperty(ImageScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoEmail));
263
    info.phone = readSimpleProperty(ImageScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoPhone));
264
    info.webUrl = readSimpleProperty(ImageScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoWebUrl));
265
    return info;
266
}
267
268
void ImageCopyright::setContactInfo(const IptcCoreContactInfo& info)
269
{
270
    setSimpleProperty(ImageScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoCity), info.city);
271
    setSimpleProperty(ImageScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoCountry), info.country);
272
    setSimpleProperty(ImageScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoAddress), info.address);
273
    setSimpleProperty(ImageScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoPostalCode), info.postalCode);
274
    setSimpleProperty(ImageScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoProvinceState), info.provinceState);
275
    setSimpleProperty(ImageScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoEmail), info.email);
276
    setSimpleProperty(ImageScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoPhone), info.phone);
277
    setSimpleProperty(ImageScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoWebUrl), info.webUrl);
278
}
279
280
void ImageCopyright::removeContactInfo()
281
{
282
    removeProperties(ImageScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoCity));
283
    removeProperties(ImageScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoCountry));
284
    removeProperties(ImageScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoAddress));
285
    removeProperties(ImageScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoPostalCode));
286
    removeProperties(ImageScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoProvinceState));
287
    removeProperties(ImageScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoEmail));
288
    removeProperties(ImageScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoPhone));
289
    removeProperties(ImageScanner::iptcCorePropertyName(MetadataInfo::IptcCoreContactInfoWebUrl));
290
}
291
292
void ImageCopyright::fillTemplate(Template& t)
293
{
294
    ImageCopyrightCache cache(this);
295
296
    t.setAuthors(author());
297
    t.setAuthorsPosition(authorsPosition());
298
    t.setCredit(credit());
299
    t.setCopyright(allCopyrightNotices());
300
    t.setRightUsageTerms(allRightsUsageTerms());
301
    t.setSource(source());
302
    t.setInstructions(instructions());
303
    t.setContactInfo(contactInfo());
304
}
305
306
void ImageCopyright::setFromTemplate(const Template& t)
307
{
308
    foreach(QString author, t.authors()) // krazy:exclude=foreach
309
    {
310
        setAuthor(author, ImageCopyright::AddEntryToExisting);
311
    }
312
313
    setCredit(t.credit());
314
315
    KExiv2::AltLangMap copyrights = t.copyright();
316
    KExiv2::AltLangMap::const_iterator it;
317
318
    for (it = copyrights.constBegin() ; it != copyrights.constEnd() ; ++it)
319
    {
320
        setRights(it.value(), it.key(), ImageCopyright::AddEntryToExisting);
321
    }
322
323
    KExiv2::AltLangMap usages = t.rightUsageTerms();
324
    KExiv2::AltLangMap::const_iterator it2;
325
326
    for (it2 = usages.constBegin() ; it2 != usages.constEnd() ; ++it2)
327
    {
328
        setRightsUsageTerms(it2.value(), it2.key(), ImageCopyright::AddEntryToExisting);
329
    }
330
331
    setSource(t.source());
332
    setAuthorsPosition(t.authorsPosition());
333
    setInstructions(t.instructions());
334
    setContactInfo(t.contactInfo());
335
}
336
337
void ImageCopyright::removeAll()
338
{
339
    ImageCopyrightCache cache(this);
340
341
    removeCreators();
342
    removeProvider();
343
    removeCopyrightNotices();
344
    removeRightsUsageTerms();
345
    removeSource();
346
    removeCreatorJobTitle();
347
    removeInstructions();
348
    removeContactInfo();
349
}
350
351
CopyrightInfo ImageCopyright::copyrightInfo(const QString& property) const
352
{
353
    if (m_cache)
354
    {
1.7.4 by Mark Purcell
Import upstream version 2.5.0
355
        foreach(const CopyrightInfo& info, m_cache->infos)
1.7.1 by Mark Purcell
Import upstream version 2.2.0
356
        {
357
            if (info.property == property)
358
            {
359
                return info;
360
            }
361
        }
362
    }
363
    else
364
    {
365
        QList<CopyrightInfo> infos = DatabaseAccess().db()->getImageCopyright(m_id, property);
366
367
        if (!infos.isEmpty())
368
        {
369
            return infos.first();
370
        }
371
    }
372
373
    return CopyrightInfo();
374
}
375
376
QList<CopyrightInfo> ImageCopyright::copyrightInfos(const QString& property) const
377
{
378
    if (m_cache)
379
    {
380
        QList<CopyrightInfo> infos;
1.7.4 by Mark Purcell
Import upstream version 2.5.0
381
        foreach(const CopyrightInfo& info, m_cache->infos)
1.7.1 by Mark Purcell
Import upstream version 2.2.0
382
        {
383
            if (info.property == property)
384
            {
385
                infos << info;
386
            }
387
        }
388
        return infos;
389
    }
390
    else
391
    {
392
        return DatabaseAccess().db()->getImageCopyright(m_id, property);
393
    }
394
}
395
396
QString ImageCopyright::readSimpleProperty(const QString& property) const
397
{
398
    return copyrightInfo(property).value;
399
}
400
401
void ImageCopyright::setSimpleProperty(const QString& property, const QString& value)
402
{
403
    DatabaseAccess().db()->setImageCopyrightProperty(m_id, property, value, QString(), AlbumDB::PropertyUnique);
404
}
405
406
QString ImageCopyright::readLanguageProperty(const QString& property, const QString& languageCode)
407
{
408
    QList<CopyrightInfo> infos = copyrightInfos(property);
409
    int index = languageMatch(infos, languageCode);
410
411
    if (index == -1)
412
    {
413
        return QString();
414
    }
415
    else
416
    {
417
        return infos.at(index).value;
418
    }
419
}
420
421
KExiv2Iface::KExiv2::AltLangMap ImageCopyright::readLanguageProperties(const QString& property)
422
{
423
    KExiv2Iface::KExiv2::AltLangMap map;
424
    QList<CopyrightInfo> infos = copyrightInfos(property);
1.7.4 by Mark Purcell
Import upstream version 2.5.0
425
    foreach(const CopyrightInfo& info, infos)
1.7.1 by Mark Purcell
Import upstream version 2.2.0
426
    {
427
        map[info.extraValue] = info.value;
428
    }
429
    return map;
430
}
431
432
void ImageCopyright::setLanguageProperty(const QString& property, const QString& value,
433
        const QString& languageCode, ReplaceMode mode)
434
{
435
    AlbumDB::CopyrightPropertyUnique uniqueness;
436
437
    if (mode == ReplaceAllEntries)
438
    {
439
        uniqueness = AlbumDB::PropertyUnique;
440
    }
441
    else if (mode == ReplaceLanguageEntry)
442
    {
443
        uniqueness = AlbumDB::PropertyExtraValueUnique;
444
    }
445
    else
446
    {
447
        uniqueness = AlbumDB::PropertyNoConstraint;
448
    }
449
450
    QString language = languageCode;
451
452
    if (language.isNull())
453
    {
454
        language = "x-default";
455
    }
456
457
    DatabaseAccess().db()->setImageCopyrightProperty(m_id, property, value, language, uniqueness);
458
}
459
460
void ImageCopyright::removeProperties(const QString& property)
461
{
462
    // if we have a cache, find out if anything need to be done at all
463
    if (m_cache && copyrightInfo(property).isNull())
464
    {
465
        return;
466
    }
467
468
    DatabaseAccess().db()->removeImageCopyrightProperties(m_id, property);
469
}
470
471
void ImageCopyright::removeLanguageProperty(const QString& property, const QString& languageCode)
472
{
473
    if (m_cache && copyrightInfo(property).isNull())
474
    {
475
        return;
476
    }
477
478
    DatabaseAccess().db()->removeImageCopyrightProperties(m_id, property, languageCode);
479
}
480
481
int ImageCopyright::languageMatch(const QList<CopyrightInfo> infos, const QString& languageCode) const
482
{
483
    QString langCode;
484
    QString fullCode = languageCode;
485
486
    if (languageCode.isNull())
487
    {
488
        // find local language
489
        KLocale* locale = KGlobal::locale();
490
        langCode = locale->language().toLower() + '-';
491
        fullCode = langCode + locale->country().toLower();
492
    }
493
    else if (languageCode == "x-default")
494
    {
495
        langCode = languageCode;
496
    }
497
    else
498
    {
499
        // en-us => en-
500
        langCode = languageCode.section('-', 0, 0, QString::SectionIncludeTrailingSep);
501
    }
502
503
    int fullCodeMatch, langCodeMatch, defaultCodeMatch, firstMatch;
504
    fullCodeMatch    = -1;
505
    langCodeMatch    = -1;
506
    defaultCodeMatch = -1;
507
    firstMatch       = -1;
508
509
    if (infos.isEmpty())
510
    {
511
        return -1;
512
    }
513
    else
514
    {
515
        firstMatch = 0; // index of first entry - at least we have one
516
    }
517
518
    // First we search for a full match
519
    // Second for a match of the language code
520
    // Third for the default code
521
    // Fourth we return the first comment
522
523
    QLatin1String defaultCode("x-default");
524
525
    for (int i=0; i<infos.size(); ++i)
526
    {
527
        const CopyrightInfo& info = infos.at(i);
528
529
        if (info.extraValue == fullCode)
530
        {
531
            fullCodeMatch = i;
532
            break;
533
        }
534
        else if (info.extraValue.startsWith(langCode) && langCodeMatch == -1)
535
        {
536
            langCodeMatch = i;
537
        }
538
        else if (info.extraValue == defaultCode)
539
        {
540
            defaultCodeMatch = i;
541
        }
542
    }
543
544
    int chosen = fullCodeMatch;
545
546
    if (chosen == -1)
547
    {
548
        chosen = langCodeMatch;
549
    }
550
551
    if (chosen == -1)
552
    {
553
        chosen = defaultCodeMatch;
554
    }
555
556
    if (chosen == -1)
557
    {
558
        chosen = firstMatch;
559
    }
560
561
    return chosen;
562
}
563
564
} // namespace Digikam