~ubuntu-branches/ubuntu/precise/gwenview/precise-proposed

« back to all changes in this revision

Viewing changes to lib/imagemetainfomodel.cpp

  • Committer: Package Import Robot
  • Author(s): Jonathan Riddell
  • Date: 2011-12-15 14:17:54 UTC
  • mto: This revision was merged to the branch mainline in revision 12.
  • Revision ID: package-import@ubuntu.com-20111215141754-z043hyx69dulbggf
Tags: upstream-4.7.90
ImportĀ upstreamĀ versionĀ 4.7.90

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
// vim: set tabstop=4 shiftwidth=4 noexpandtab:
 
1
// vim: set tabstop=4 shiftwidth=4 expandtab:
2
2
/*
3
3
Gwenview: an image viewer
4
4
Copyright 2007 AurĆ©lien GĆ¢teau <agateau@kde.org>
36
36
 
37
37
// Local
38
38
 
39
 
 
40
 
namespace Gwenview {
41
 
 
 
39
namespace Gwenview
 
40
{
42
41
 
43
42
enum GroupRow {
44
 
        NoGroupSpace= -2,
45
 
        NoGroup = -1,
46
 
        GeneralGroup,
47
 
        ExifGroup,
48
 
        IptcGroup,
49
 
        XmpGroup
 
43
    NoGroupSpace = -2,
 
44
    NoGroup = -1,
 
45
    GeneralGroup,
 
46
    ExifGroup,
 
47
    IptcGroup,
 
48
    XmpGroup
50
49
};
51
50
 
52
 
 
53
 
class MetaInfoGroup {
 
51
class MetaInfoGroup
 
52
{
54
53
public:
55
 
        enum {
56
 
                InvalidRow = -1
57
 
        };
58
 
 
59
 
        class Entry {
60
 
        public:
61
 
                Entry(const QString& key, const QString& label, const QString& value)
62
 
                : mKey(key), mLabel(label.trimmed()), mValue(value.trimmed())
63
 
                {}
64
 
 
65
 
                QString key() const { return mKey; }
66
 
                QString label() const { return mLabel; }
67
 
 
68
 
                QString value() const { return mValue; }
69
 
                void setValue(const QString& value) { mValue = value.trimmed(); }
70
 
 
71
 
                void appendValue(const QString& value) {
72
 
                        if (mValue.length() > 0) {
73
 
                                mValue += '\n';
74
 
                        }
75
 
                        mValue += value.trimmed();
76
 
                }
77
 
 
78
 
        private:
79
 
                QString mKey;
80
 
                QString mLabel;
81
 
                QString mValue;
82
 
        };
83
 
 
84
 
        MetaInfoGroup(const QString& label)
85
 
        : mLabel(label) {}
86
 
 
87
 
 
88
 
        ~MetaInfoGroup() {
89
 
                qDeleteAll(mList);
90
 
        }
91
 
 
92
 
 
93
 
        void clear() {
94
 
                qDeleteAll(mList);
95
 
                mList.clear();
96
 
                mRowForKey.clear();
97
 
        }
98
 
 
99
 
 
100
 
        void addEntry(const QString& key, const QString& label, const QString& value) {
101
 
                addEntry(new Entry(key, label, value));
102
 
        }
103
 
 
104
 
 
105
 
        void addEntry(Entry* entry) {
106
 
                mList << entry;
107
 
                mRowForKey[entry->key()] = mList.size() - 1;
108
 
        }
109
 
 
110
 
 
111
 
        void getInfoForKey(const QString& key, QString* label, QString* value) const {
112
 
                Entry* entry = getEntryForKey(key);
113
 
                if (entry) {
114
 
                        *label = entry->label();
115
 
                        *value = entry->value();
116
 
                }
117
 
        }
118
 
 
119
 
 
120
 
        QString getKeyAt(int row) const {
121
 
                Q_ASSERT(row < mList.size());
122
 
                return mList[row]->key();
123
 
        }
124
 
 
125
 
 
126
 
        QString getLabelForKeyAt(int row) const {
127
 
                Q_ASSERT(row < mList.size());
128
 
                return mList[row]->label();
129
 
        }
130
 
 
131
 
 
132
 
        QString getValueForKeyAt(int row) const {
133
 
                Q_ASSERT(row < mList.size());
134
 
                return mList[row]->value();
135
 
        }
136
 
 
137
 
 
138
 
        void setValueForKeyAt(int row, const QString& value) {
139
 
                Q_ASSERT(row < mList.size());
140
 
                mList[row]->setValue(value);
141
 
        }
142
 
 
143
 
 
144
 
        int getRowForKey(const QString& key) const {
145
 
                return mRowForKey.value(key, InvalidRow);
146
 
        }
147
 
 
148
 
 
149
 
        int size() const {
150
 
                return mList.size();
151
 
        }
152
 
 
153
 
 
154
 
        QString label() const {
155
 
                return mLabel;
156
 
        }
157
 
 
158
 
        const QList<Entry*>& entryList() const {
159
 
                return mList;
160
 
        }
 
54
    enum {
 
55
        InvalidRow = -1
 
56
    };
 
57
 
 
58
    class Entry
 
59
    {
 
60
    public:
 
61
        Entry(const QString& key, const QString& label, const QString& value)
 
62
            : mKey(key), mLabel(label.trimmed()), mValue(value.trimmed())
 
63
        {}
 
64
 
 
65
        QString key() const {
 
66
            return mKey;
 
67
        }
 
68
        QString label() const {
 
69
            return mLabel;
 
70
        }
 
71
 
 
72
        QString value() const {
 
73
            return mValue;
 
74
        }
 
75
        void setValue(const QString& value)
 
76
    {
 
77
            mValue = value.trimmed();
 
78
        }
 
79
 
 
80
        void appendValue(const QString& value)
 
81
    {
 
82
            if (mValue.length() > 0) {
 
83
                mValue += '\n';
 
84
            }
 
85
            mValue += value.trimmed();
 
86
        }
 
87
 
 
88
    private:
 
89
        QString mKey;
 
90
        QString mLabel;
 
91
        QString mValue;
 
92
    };
 
93
 
 
94
    MetaInfoGroup(const QString& label)
 
95
        : mLabel(label) {}
 
96
 
 
97
    ~MetaInfoGroup() {
 
98
        qDeleteAll(mList);
 
99
    }
 
100
 
 
101
    void clear()
 
102
    {
 
103
        qDeleteAll(mList);
 
104
        mList.clear();
 
105
        mRowForKey.clear();
 
106
    }
 
107
 
 
108
    void addEntry(const QString& key, const QString& label, const QString& value)
 
109
    {
 
110
        addEntry(new Entry(key, label, value));
 
111
    }
 
112
 
 
113
    void addEntry(Entry* entry)
 
114
    {
 
115
        mList << entry;
 
116
        mRowForKey[entry->key()] = mList.size() - 1;
 
117
    }
 
118
 
 
119
    void getInfoForKey(const QString& key, QString* label, QString* value) const
 
120
    {
 
121
        Entry* entry = getEntryForKey(key);
 
122
        if (entry) {
 
123
            *label = entry->label();
 
124
            *value = entry->value();
 
125
        }
 
126
    }
 
127
 
 
128
    QString getKeyAt(int row) const {
 
129
        Q_ASSERT(row < mList.size());
 
130
        return mList[row]->key();
 
131
    }
 
132
 
 
133
    QString getLabelForKeyAt(int row) const {
 
134
        Q_ASSERT(row < mList.size());
 
135
        return mList[row]->label();
 
136
    }
 
137
 
 
138
    QString getValueForKeyAt(int row) const {
 
139
        Q_ASSERT(row < mList.size());
 
140
        return mList[row]->value();
 
141
    }
 
142
 
 
143
    void setValueForKeyAt(int row, const QString& value)
 
144
    {
 
145
        Q_ASSERT(row < mList.size());
 
146
        mList[row]->setValue(value);
 
147
    }
 
148
 
 
149
    int getRowForKey(const QString& key) const {
 
150
        return mRowForKey.value(key, InvalidRow);
 
151
    }
 
152
 
 
153
    int size() const {
 
154
        return mList.size();
 
155
    }
 
156
 
 
157
    QString label() const {
 
158
        return mLabel;
 
159
    }
 
160
 
 
161
    const QList<Entry*>& entryList() const {
 
162
        return mList;
 
163
    }
161
164
 
162
165
private:
163
 
        Entry* getEntryForKey(const QString& key) const {
164
 
                int row = getRowForKey(key);
165
 
                if (row == InvalidRow) {
166
 
                        return 0;
167
 
                }
168
 
                return mList[row];
169
 
        }
 
166
    Entry* getEntryForKey(const QString& key) const {
 
167
        int row = getRowForKey(key);
 
168
        if (row == InvalidRow) {
 
169
            return 0;
 
170
        }
 
171
        return mList[row];
 
172
    }
170
173
 
171
 
        QList<Entry*> mList;
172
 
        QHash<QString, int> mRowForKey;
173
 
        QString mLabel;
 
174
    QList<Entry*> mList;
 
175
    QHash<QString, int> mRowForKey;
 
176
    QString mLabel;
174
177
};
175
178
 
176
 
 
177
179
struct ImageMetaInfoModelPrivate {
178
 
        QVector<MetaInfoGroup*> mMetaInfoGroupVector;
179
 
        ImageMetaInfoModel* mModel;
180
 
 
181
 
 
182
 
        void clearGroup(MetaInfoGroup* group, const QModelIndex& parent) {
183
 
                if (group->size() > 0) {
184
 
                        mModel->beginRemoveRows(parent, 0, group->size() - 1);
185
 
                        group->clear();
186
 
                        mModel->endRemoveRows();
187
 
                }
188
 
        }
189
 
 
190
 
 
191
 
        void setGroupEntryValue(GroupRow groupRow, const QString& key, const QString& value) {
192
 
                MetaInfoGroup* group = mMetaInfoGroupVector[groupRow];
193
 
                int entryRow = group->getRowForKey(key);
194
 
                if (entryRow == MetaInfoGroup::InvalidRow) {
195
 
                        kWarning() << "No row for key" << key;
196
 
                        return;
197
 
                }
198
 
                group->setValueForKeyAt(entryRow, value);
199
 
                QModelIndex groupIndex = mModel->index(groupRow, 0);
200
 
                QModelIndex entryIndex = mModel->index(entryRow, 1, groupIndex);
201
 
                emit mModel->dataChanged(entryIndex, entryIndex);
202
 
        }
203
 
 
204
 
 
205
 
        QVariant displayData(const QModelIndex& index) const {
206
 
                if (index.internalId() == NoGroup) {
207
 
                        if (index.column() != 0) {
208
 
                                return QVariant();
209
 
                        }
210
 
                        QString label = mMetaInfoGroupVector[index.row()]->label();
211
 
                        return QVariant(label);
212
 
                }
213
 
 
214
 
                if (index.internalId() == NoGroupSpace) {
215
 
                        return QVariant(QString());
216
 
                }
217
 
 
218
 
                MetaInfoGroup* group = mMetaInfoGroupVector[index.internalId()];
219
 
                if (index.column() == 0) {
220
 
                        return group->getLabelForKeyAt(index.row());
221
 
                } else {
222
 
                        return group->getValueForKeyAt(index.row());
223
 
                }
224
 
        }
225
 
 
226
 
 
227
 
        void initGeneralGroup() {
228
 
                MetaInfoGroup* group = mMetaInfoGroupVector[GeneralGroup];
229
 
                group->addEntry("General.Name", i18nc("@item:intable Image file name", "Name"), QString());
230
 
                group->addEntry("General.Size", i18nc("@item:intable", "File Size"), QString());
231
 
                group->addEntry("General.Time", i18nc("@item:intable", "File Time"), QString());
232
 
                group->addEntry("General.ImageSize", i18nc("@item:intable", "Image Size"), QString());
233
 
        }
234
 
 
235
 
 
236
 
        template <class Container, class Iterator>
237
 
        void fillExivGroup(const QModelIndex& parent, MetaInfoGroup* group, const Container& container) {
238
 
                // key aren't always unique (for example, "Iptc.Application2.Keywords"
239
 
                // may appear multiple times) so we can't know how many rows we will
240
 
                // insert before going through them. That's why we create a hash
241
 
                // before.
242
 
                typedef QHash<QString, MetaInfoGroup::Entry*> EntryHash;
243
 
                EntryHash hash;
244
 
 
245
 
                Iterator
246
 
                        it = container.begin(),
247
 
                        end = container.end();
248
 
 
249
 
                if (it == end) {
250
 
                        return;
251
 
                }
252
 
 
253
 
                for (;it != end; ++it) {
254
 
                        QString key = QString::fromUtf8(it->key().c_str());
255
 
                        QString label = QString::fromLocal8Bit(it->tagLabel().c_str());
256
 
                        std::ostringstream stream;
257
 
                        stream << *it;
258
 
                        QString value = QString::fromLocal8Bit(stream.str().c_str());
259
 
 
260
 
                        EntryHash::iterator hashIt = hash.find(key);
261
 
                        if (hashIt != hash.end()) {
262
 
                                hashIt.value()->appendValue(value);
263
 
                        } else {
264
 
                                hash.insert(key, new MetaInfoGroup::Entry(key, label, value));
265
 
                        }
266
 
                }
267
 
 
268
 
                mModel->beginInsertRows(parent, 0, hash.size() - 1);
269
 
                Q_FOREACH(MetaInfoGroup::Entry* entry, hash) {
270
 
                        group->addEntry(entry);
271
 
                }
272
 
                mModel->endInsertRows();
273
 
        }
 
180
    QVector<MetaInfoGroup*> mMetaInfoGroupVector;
 
181
    ImageMetaInfoModel* q;
 
182
 
 
183
    void clearGroup(MetaInfoGroup* group, const QModelIndex& parent)
 
184
    {
 
185
        if (group->size() > 0) {
 
186
            q->beginRemoveRows(parent, 0, group->size() - 1);
 
187
            group->clear();
 
188
            q->endRemoveRows();
 
189
        }
 
190
    }
 
191
 
 
192
    void setGroupEntryValue(GroupRow groupRow, const QString& key, const QString& value)
 
193
    {
 
194
        MetaInfoGroup* group = mMetaInfoGroupVector[groupRow];
 
195
        int entryRow = group->getRowForKey(key);
 
196
        if (entryRow == MetaInfoGroup::InvalidRow) {
 
197
            kWarning() << "No row for key" << key;
 
198
            return;
 
199
        }
 
200
        group->setValueForKeyAt(entryRow, value);
 
201
        QModelIndex groupIndex = q->index(groupRow, 0);
 
202
        QModelIndex entryIndex = q->index(entryRow, 1, groupIndex);
 
203
        emit q->dataChanged(entryIndex, entryIndex);
 
204
    }
 
205
 
 
206
    QVariant displayData(const QModelIndex& index) const {
 
207
        if (index.internalId() == NoGroup) {
 
208
            if (index.column() != 0) {
 
209
                return QVariant();
 
210
            }
 
211
            QString label = mMetaInfoGroupVector[index.row()]->label();
 
212
            return QVariant(label);
 
213
        }
 
214
 
 
215
        if (index.internalId() == NoGroupSpace) {
 
216
            return QVariant(QString());
 
217
        }
 
218
 
 
219
        MetaInfoGroup* group = mMetaInfoGroupVector[index.internalId()];
 
220
        if (index.column() == 0) {
 
221
            return group->getLabelForKeyAt(index.row());
 
222
        } else {
 
223
            return group->getValueForKeyAt(index.row());
 
224
        }
 
225
    }
 
226
 
 
227
    void initGeneralGroup()
 
228
    {
 
229
        MetaInfoGroup* group = mMetaInfoGroupVector[GeneralGroup];
 
230
        group->addEntry("General.Name", i18nc("@item:intable Image file name", "Name"), QString());
 
231
        group->addEntry("General.Size", i18nc("@item:intable", "File Size"), QString());
 
232
        group->addEntry("General.Time", i18nc("@item:intable", "File Time"), QString());
 
233
        group->addEntry("General.ImageSize", i18nc("@item:intable", "Image Size"), QString());
 
234
        group->addEntry("General.Comment", i18nc("@item:intable", "Comment"), QString());
 
235
    }
 
236
 
 
237
    template <class Container, class Iterator>
 
238
    void fillExivGroup(const QModelIndex& parent, MetaInfoGroup* group, const Container& container)
 
239
    {
 
240
        // key aren't always unique (for example, "Iptc.Application2.Keywords"
 
241
        // may appear multiple times) so we can't know how many rows we will
 
242
        // insert before going through them. That's why we create a hash
 
243
        // before.
 
244
        typedef QHash<QString, MetaInfoGroup::Entry*> EntryHash;
 
245
        EntryHash hash;
 
246
 
 
247
        Iterator
 
248
        it = container.begin(),
 
249
        end = container.end();
 
250
 
 
251
        if (it == end) {
 
252
            return;
 
253
        }
 
254
 
 
255
        for (; it != end; ++it) {
 
256
            QString key = QString::fromUtf8(it->key().c_str());
 
257
            QString label = QString::fromLocal8Bit(it->tagLabel().c_str());
 
258
            std::ostringstream stream;
 
259
            stream << *it;
 
260
            QString value = QString::fromLocal8Bit(stream.str().c_str());
 
261
 
 
262
            EntryHash::iterator hashIt = hash.find(key);
 
263
            if (hashIt != hash.end()) {
 
264
                hashIt.value()->appendValue(value);
 
265
            } else {
 
266
                hash.insert(key, new MetaInfoGroup::Entry(key, label, value));
 
267
            }
 
268
        }
 
269
 
 
270
        q->beginInsertRows(parent, 0, hash.size() - 1);
 
271
        Q_FOREACH(MetaInfoGroup::Entry * entry, hash) {
 
272
            group->addEntry(entry);
 
273
        }
 
274
        q->endInsertRows();
 
275
    }
274
276
};
275
277
 
276
 
 
277
278
ImageMetaInfoModel::ImageMetaInfoModel()
278
 
: d(new ImageMetaInfoModelPrivate) {
279
 
        d->mModel = this;
280
 
        d->mMetaInfoGroupVector.resize(4);
281
 
        d->mMetaInfoGroupVector[GeneralGroup] = new MetaInfoGroup(i18nc("@title:group General info about the image", "General"));
282
 
        d->mMetaInfoGroupVector[ExifGroup] = new MetaInfoGroup("EXIF");
283
 
        d->mMetaInfoGroupVector[IptcGroup] = new MetaInfoGroup("IPTC");
284
 
        d->mMetaInfoGroupVector[XmpGroup]  = new MetaInfoGroup("XMP");
285
 
        d->initGeneralGroup();
286
 
}
287
 
 
288
 
 
289
 
ImageMetaInfoModel::~ImageMetaInfoModel() {
290
 
        qDeleteAll(d->mMetaInfoGroupVector);
291
 
        delete d;
292
 
}
293
 
 
294
 
 
295
 
void ImageMetaInfoModel::setUrl(const KUrl& url) {
296
 
        KFileItem item(KFileItem::Unknown, KFileItem::Unknown, url);
297
 
        QString sizeString = KGlobal::locale()->formatByteSize(item.size());
298
 
 
299
 
        d->setGroupEntryValue(GeneralGroup, "General.Name", item.name());
300
 
        d->setGroupEntryValue(GeneralGroup, "General.Size", sizeString);
301
 
        d->setGroupEntryValue(GeneralGroup, "General.Time", item.timeString());
302
 
}
303
 
 
304
 
 
305
 
void ImageMetaInfoModel::setImageSize(const QSize& size) {
306
 
        QString imageSize;
307
 
        if (size.isValid()) {
308
 
                imageSize = i18nc(
309
 
                        "@item:intable %1 is image width, %2 is image height",
310
 
                        "%1x%2", size.width(), size.height());
311
 
 
312
 
                double megaPixels = size.width() * size.height() / 1000000.;
313
 
                if (megaPixels > 0.1) {
314
 
                        QString megaPixelsString = QString::number(megaPixels, 'f', 1);
315
 
                        imageSize += ' ';
316
 
                        imageSize += i18nc(
317
 
                                "@item:intable %1 is number of millions of pixels in image",
318
 
                                "(%1MP)", megaPixelsString);
319
 
                }
320
 
        } else {
321
 
                imageSize = "-";
322
 
        }
323
 
        d->setGroupEntryValue(GeneralGroup, "General.ImageSize", imageSize);
324
 
}
325
 
 
326
 
 
327
 
void ImageMetaInfoModel::setExiv2Image(const Exiv2::Image* image) {
328
 
        MetaInfoGroup* exifGroup = d->mMetaInfoGroupVector[ExifGroup];
329
 
        MetaInfoGroup* iptcGroup = d->mMetaInfoGroupVector[IptcGroup];
330
 
        MetaInfoGroup* xmpGroup  = d->mMetaInfoGroupVector[XmpGroup];
331
 
        QModelIndex exifIndex = index(ExifGroup, 0);
332
 
        QModelIndex iptcIndex = index(IptcGroup, 0);
333
 
        QModelIndex xmpIndex  = index(XmpGroup, 0);
334
 
        d->clearGroup(exifGroup, exifIndex);
335
 
        d->clearGroup(iptcGroup, iptcIndex);
336
 
        d->clearGroup(xmpGroup,  xmpIndex);
337
 
 
338
 
        if (!image) {
339
 
                return;
340
 
        }
341
 
 
342
 
        if (image->checkMode(Exiv2::mdExif) & Exiv2::amRead) {
343
 
                const Exiv2::ExifData& exifData = image->exifData();
344
 
                d->fillExivGroup<Exiv2::ExifData, Exiv2::ExifData::const_iterator>(exifIndex, exifGroup, exifData);
345
 
        }
346
 
 
347
 
        if (image->checkMode(Exiv2::mdIptc) & Exiv2::amRead) {
348
 
                const Exiv2::IptcData& iptcData = image->iptcData();
349
 
                d->fillExivGroup<Exiv2::IptcData, Exiv2::IptcData::const_iterator>(iptcIndex, iptcGroup, iptcData);
350
 
        }
351
 
 
352
 
        if (image->checkMode(Exiv2::mdXmp) & Exiv2::amRead) {
353
 
                const Exiv2::XmpData& xmpData = image->xmpData();
354
 
                d->fillExivGroup<Exiv2::XmpData, Exiv2::XmpData::const_iterator>(xmpIndex, xmpGroup, xmpData);
355
 
        }
356
 
}
357
 
 
358
 
 
359
 
void ImageMetaInfoModel::getInfoForKey(const QString& key, QString* label, QString* value) const {
360
 
        MetaInfoGroup* group;
361
 
        if (key.startsWith(QLatin1String("General"))) {
362
 
                group = d->mMetaInfoGroupVector[GeneralGroup];
363
 
        } else if (key.startsWith(QLatin1String("Exif"))) {
364
 
                group = d->mMetaInfoGroupVector[ExifGroup];
365
 
        } else if (key.startsWith(QLatin1String("Iptc"))) {
366
 
                group = d->mMetaInfoGroupVector[IptcGroup];
367
 
        } else if (key.startsWith(QLatin1String("Xmp"))) {
368
 
                group = d->mMetaInfoGroupVector[XmpGroup];
369
 
        } else {
370
 
                kWarning() << "Unknown metainfo key" << key;
371
 
                return;
372
 
        }
373
 
        group->getInfoForKey(key, label, value);
374
 
}
375
 
 
376
 
 
377
 
QString ImageMetaInfoModel::getValueForKey(const QString& key) const {
378
 
        QString label, value;
379
 
        getInfoForKey(key, &label, &value);
380
 
        return value;
381
 
}
382
 
 
383
 
 
384
 
QString ImageMetaInfoModel::keyForIndex(const QModelIndex& index) const {
385
 
        if (index.internalId() == NoGroup) {
386
 
                return QString();
387
 
        }
388
 
        MetaInfoGroup* group = d->mMetaInfoGroupVector[index.internalId()];
389
 
        return group->getKeyAt(index.row());
390
 
}
391
 
 
392
 
 
393
 
QModelIndex ImageMetaInfoModel::index(int row, int col, const QModelIndex& parent) const {
394
 
        if (col < 0 || col > 1) {
395
 
                return QModelIndex();
396
 
        }
397
 
        if (!parent.isValid()) {
398
 
                // This is a group
399
 
                if (row < 0 || row >= d->mMetaInfoGroupVector.size()) {
400
 
                        return QModelIndex();
401
 
                }
402
 
                return createIndex(row, col, col == 0 ? NoGroup : NoGroupSpace);
403
 
        } else {
404
 
                // This is an entry
405
 
                int group = parent.row();
406
 
                if (row < 0 || row >= d->mMetaInfoGroupVector[group]->size()) {
407
 
                        return QModelIndex();
408
 
                }
409
 
                return createIndex(row, col, group);
410
 
        }
411
 
}
412
 
 
413
 
 
414
 
QModelIndex ImageMetaInfoModel::parent(const QModelIndex& index) const {
415
 
        if (!index.isValid()) {
416
 
                return QModelIndex();
417
 
        }
418
 
        if (index.internalId() == NoGroup || index.internalId() == NoGroupSpace) {
419
 
                return QModelIndex();
420
 
        } else {
421
 
                return createIndex(index.internalId(), 0, NoGroup);
422
 
        }
423
 
}
424
 
 
425
 
 
426
 
int ImageMetaInfoModel::rowCount(const QModelIndex& parent) const {
427
 
        if (!parent.isValid()) {
428
 
                return d->mMetaInfoGroupVector.size();
429
 
        } else if (parent.internalId() == NoGroup) {
430
 
                return d->mMetaInfoGroupVector[parent.row()]->size();
431
 
        } else {
432
 
                return 0;
433
 
        }
434
 
}
435
 
 
436
 
 
437
 
int ImageMetaInfoModel::columnCount(const QModelIndex& /*parent*/) const {
438
 
        return 2;
439
 
}
440
 
 
441
 
 
442
 
QVariant ImageMetaInfoModel::data(const QModelIndex& index, int role) const {
443
 
        if (!index.isValid()) {
444
 
                return QVariant();
445
 
        }
446
 
 
447
 
        switch (role) {
448
 
        case Qt::DisplayRole:
449
 
                return d->displayData(index);
450
 
        default:
451
 
                return QVariant();
452
 
        }
453
 
}
454
 
 
455
 
 
456
 
QVariant ImageMetaInfoModel::headerData(int section, Qt::Orientation orientation, int role) const {
457
 
        if (orientation == Qt::Vertical || role != Qt::DisplayRole) {
458
 
                return QVariant();
459
 
        }
460
 
 
461
 
        QString caption;
462
 
        if (section == 0) {
463
 
                caption = i18nc("@title:column", "Property");
464
 
        } else if (section == 1) {
465
 
                caption = i18nc("@title:column", "Value");
466
 
        } else {
467
 
                kWarning() << "Unknown section" << section;
468
 
        }
469
 
 
470
 
        return QVariant(caption);
471
 
}
472
 
 
 
279
: d(new ImageMetaInfoModelPrivate)
 
280
{
 
281
    d->q = this;
 
282
    d->mMetaInfoGroupVector.resize(4);
 
283
    d->mMetaInfoGroupVector[GeneralGroup] = new MetaInfoGroup(i18nc("@title:group General info about the image", "General"));
 
284
    d->mMetaInfoGroupVector[ExifGroup] = new MetaInfoGroup("EXIF");
 
285
    d->mMetaInfoGroupVector[IptcGroup] = new MetaInfoGroup("IPTC");
 
286
    d->mMetaInfoGroupVector[XmpGroup]  = new MetaInfoGroup("XMP");
 
287
    d->initGeneralGroup();
 
288
}
 
289
 
 
290
ImageMetaInfoModel::~ImageMetaInfoModel()
 
291
{
 
292
    qDeleteAll(d->mMetaInfoGroupVector);
 
293
    delete d;
 
294
}
 
295
 
 
296
void ImageMetaInfoModel::setUrl(const KUrl& url)
 
297
{
 
298
    KFileItem item(KFileItem::Unknown, KFileItem::Unknown, url);
 
299
    QString sizeString = KGlobal::locale()->formatByteSize(item.size());
 
300
 
 
301
    d->setGroupEntryValue(GeneralGroup, "General.Name", item.name());
 
302
    d->setGroupEntryValue(GeneralGroup, "General.Size", sizeString);
 
303
    d->setGroupEntryValue(GeneralGroup, "General.Time", item.timeString());
 
304
}
 
305
 
 
306
void ImageMetaInfoModel::setImageSize(const QSize& size)
 
307
{
 
308
    QString imageSize;
 
309
    if (size.isValid()) {
 
310
        imageSize = i18nc(
 
311
                        "@item:intable %1 is image width, %2 is image height",
 
312
                        "%1x%2", size.width(), size.height());
 
313
 
 
314
        double megaPixels = size.width() * size.height() / 1000000.;
 
315
        if (megaPixels > 0.1) {
 
316
            QString megaPixelsString = QString::number(megaPixels, 'f', 1);
 
317
            imageSize += ' ';
 
318
            imageSize += i18nc(
 
319
                             "@item:intable %1 is number of millions of pixels in image",
 
320
                             "(%1MP)", megaPixelsString);
 
321
        }
 
322
    } else {
 
323
        imageSize = "-";
 
324
    }
 
325
    d->setGroupEntryValue(GeneralGroup, "General.ImageSize", imageSize);
 
326
}
 
327
 
 
328
void ImageMetaInfoModel::setExiv2Image(const Exiv2::Image* image)
 
329
{
 
330
    MetaInfoGroup* exifGroup = d->mMetaInfoGroupVector[ExifGroup];
 
331
    MetaInfoGroup* iptcGroup = d->mMetaInfoGroupVector[IptcGroup];
 
332
    MetaInfoGroup* xmpGroup  = d->mMetaInfoGroupVector[XmpGroup];
 
333
    QModelIndex exifIndex = index(ExifGroup, 0);
 
334
    QModelIndex iptcIndex = index(IptcGroup, 0);
 
335
    QModelIndex xmpIndex  = index(XmpGroup, 0);
 
336
    d->clearGroup(exifGroup, exifIndex);
 
337
    d->clearGroup(iptcGroup, iptcIndex);
 
338
    d->clearGroup(xmpGroup,  xmpIndex);
 
339
 
 
340
    if (!image) {
 
341
        return;
 
342
    }
 
343
 
 
344
    d->setGroupEntryValue(GeneralGroup, "General.Comment", QString::fromUtf8(image->comment().c_str()));
 
345
 
 
346
    if (image->checkMode(Exiv2::mdExif) & Exiv2::amRead) {
 
347
        const Exiv2::ExifData& exifData = image->exifData();
 
348
        d->fillExivGroup<Exiv2::ExifData, Exiv2::ExifData::const_iterator>(exifIndex, exifGroup, exifData);
 
349
    }
 
350
 
 
351
    if (image->checkMode(Exiv2::mdIptc) & Exiv2::amRead) {
 
352
        const Exiv2::IptcData& iptcData = image->iptcData();
 
353
        d->fillExivGroup<Exiv2::IptcData, Exiv2::IptcData::const_iterator>(iptcIndex, iptcGroup, iptcData);
 
354
    }
 
355
 
 
356
    if (image->checkMode(Exiv2::mdXmp) & Exiv2::amRead) {
 
357
        const Exiv2::XmpData& xmpData = image->xmpData();
 
358
        d->fillExivGroup<Exiv2::XmpData, Exiv2::XmpData::const_iterator>(xmpIndex, xmpGroup, xmpData);
 
359
    }
 
360
}
 
361
 
 
362
void ImageMetaInfoModel::getInfoForKey(const QString& key, QString* label, QString* value) const
 
363
{
 
364
    MetaInfoGroup* group;
 
365
    if (key.startsWith(QLatin1String("General"))) {
 
366
        group = d->mMetaInfoGroupVector[GeneralGroup];
 
367
    } else if (key.startsWith(QLatin1String("Exif"))) {
 
368
        group = d->mMetaInfoGroupVector[ExifGroup];
 
369
    } else if (key.startsWith(QLatin1String("Iptc"))) {
 
370
        group = d->mMetaInfoGroupVector[IptcGroup];
 
371
    } else if (key.startsWith(QLatin1String("Xmp"))) {
 
372
        group = d->mMetaInfoGroupVector[XmpGroup];
 
373
    } else {
 
374
        kWarning() << "Unknown metainfo key" << key;
 
375
        return;
 
376
    }
 
377
    group->getInfoForKey(key, label, value);
 
378
}
 
379
 
 
380
QString ImageMetaInfoModel::getValueForKey(const QString& key) const
 
381
{
 
382
    QString label, value;
 
383
    getInfoForKey(key, &label, &value);
 
384
    return value;
 
385
}
 
386
 
 
387
QString ImageMetaInfoModel::keyForIndex(const QModelIndex& index) const
 
388
{
 
389
    if (index.internalId() == NoGroup) {
 
390
        return QString();
 
391
    }
 
392
    MetaInfoGroup* group = d->mMetaInfoGroupVector[index.internalId()];
 
393
    return group->getKeyAt(index.row());
 
394
}
 
395
 
 
396
QModelIndex ImageMetaInfoModel::index(int row, int col, const QModelIndex& parent) const
 
397
{
 
398
    if (col < 0 || col > 1) {
 
399
        return QModelIndex();
 
400
    }
 
401
    if (!parent.isValid()) {
 
402
        // This is a group
 
403
        if (row < 0 || row >= d->mMetaInfoGroupVector.size()) {
 
404
            return QModelIndex();
 
405
        }
 
406
        return createIndex(row, col, col == 0 ? NoGroup : NoGroupSpace);
 
407
    } else {
 
408
        // This is an entry
 
409
        int group = parent.row();
 
410
        if (row < 0 || row >= d->mMetaInfoGroupVector[group]->size()) {
 
411
            return QModelIndex();
 
412
        }
 
413
        return createIndex(row, col, group);
 
414
    }
 
415
}
 
416
 
 
417
QModelIndex ImageMetaInfoModel::parent(const QModelIndex& index) const
 
418
{
 
419
    if (!index.isValid()) {
 
420
        return QModelIndex();
 
421
    }
 
422
    if (index.internalId() == NoGroup || index.internalId() == NoGroupSpace) {
 
423
        return QModelIndex();
 
424
    } else {
 
425
        return createIndex(index.internalId(), 0, NoGroup);
 
426
    }
 
427
}
 
428
 
 
429
int ImageMetaInfoModel::rowCount(const QModelIndex& parent) const
 
430
{
 
431
    if (!parent.isValid()) {
 
432
        return d->mMetaInfoGroupVector.size();
 
433
    } else if (parent.internalId() == NoGroup) {
 
434
        return d->mMetaInfoGroupVector[parent.row()]->size();
 
435
    } else {
 
436
        return 0;
 
437
    }
 
438
}
 
439
 
 
440
int ImageMetaInfoModel::columnCount(const QModelIndex& /*parent*/) const
 
441
{
 
442
    return 2;
 
443
}
 
444
 
 
445
QVariant ImageMetaInfoModel::data(const QModelIndex& index, int role) const
 
446
{
 
447
    if (!index.isValid()) {
 
448
        return QVariant();
 
449
    }
 
450
 
 
451
    switch (role) {
 
452
    case Qt::DisplayRole:
 
453
        return d->displayData(index);
 
454
    default:
 
455
        return QVariant();
 
456
    }
 
457
}
 
458
 
 
459
QVariant ImageMetaInfoModel::headerData(int section, Qt::Orientation orientation, int role) const
 
460
{
 
461
    if (orientation == Qt::Vertical || role != Qt::DisplayRole) {
 
462
        return QVariant();
 
463
    }
 
464
 
 
465
    QString caption;
 
466
    if (section == 0) {
 
467
        caption = i18nc("@title:column", "Property");
 
468
    } else if (section == 1) {
 
469
        caption = i18nc("@title:column", "Value");
 
470
    } else {
 
471
        kWarning() << "Unknown section" << section;
 
472
    }
 
473
 
 
474
    return QVariant(caption);
 
475
}
473
476
 
474
477
} // namespace