#include "metadatamodel.h" #include #include #include #include #include // This model is very similar to imagemetainfomodel.cpp in // Gwenview, since We don't care about ABI here and we won't // have any KDE lib as dept (KIO is a tier 3 framework from // KDE for example) which might cause this project no longer // tiny and easy to maintain, I'll just create a simpler // implementation than do a simple copy-paste... enum Sections : int { GeneralSection, ExifSection, CustomSection = 61, }; class MetadataSection { public: class Entry { public: // key: for internal indexing. // label: display name of the key. Entry(const QString & key, const QString & label, const QString & value) : m_key(key) , m_label(label.trimmed()) , m_value(value.trimmed()) {} QString m_key; QString m_label; QString m_value; }; MetadataSection(const QString & sectionName) : m_sectionName(sectionName) {} ~MetadataSection() { qDeleteAll(m_entries); } void clear() { qDeleteAll(m_entries); m_entries.clear(); } void addEnrty(const QString & key, const QString & label, const QString & value = QString()) { Entry * e = new Entry(key, label, value); m_entries << e; m_keyEntryMap[e->m_key] = m_entries.size() - 1; } QString keyAt(int index) const { Q_ASSERT(index < m_entries.size()); return m_entries[index]->m_key; } QString valueAt(int index) const { Q_ASSERT(index < m_entries.size()); return m_entries[index]->m_value; } void setValueAt(int index, const QString & value) { Q_ASSERT(index < m_entries.size()); m_entries[index]->m_value = value; } QString labelAt(int index) const { Q_ASSERT(index < m_entries.size()); return m_entries[index]->m_label; } int keyIndex(const QString & key) { return m_keyEntryMap.value(key, -1); } QString sectionName() const { return m_sectionName; } int size() const { return m_entries.size(); } private: QList m_entries; QHash m_keyEntryMap; QString m_sectionName; }; MetadataModel::MetadataModel() { sectionRegister(GeneralSection, new MetadataSection(tr("General", "General info about the image, section name in metadata dialog"))); initGeneralSection(); } MetadataModel::~MetadataModel() { qDeleteAll(m_sections); } void MetadataModel::setFile(const QString &path) { QFileInfo fileInfo(path); const QString sizeString = QLocale().formattedDataSize(fileInfo.size()); const QString timeString = QLocale().toString(fileInfo.lastModified(), QLocale::LongFormat); // FIXME: this implementation is very dirty! QImageReader imgReader(path); setImageSize(imgReader.size()); setSectionEntryValue(GeneralSection, QStringLiteral("General.Name"), fileInfo.fileName()); setSectionEntryValue(GeneralSection, QStringLiteral("General.Size"), sizeString); setSectionEntryValue(GeneralSection, QStringLiteral("General.Time"), timeString); } void MetadataModel::setImageSize(const QSize &size) { QString imageSize; if (size.isValid()) { imageSize = tr("%1 x %2").arg(QString::number(size.width()), QString::number(size.height())); } else { imageSize = QLatin1Char('-'); } setSectionEntryValue(GeneralSection, QStringLiteral("General.ImageSize"), imageSize); } QModelIndex MetadataModel::index(int row, int col, const QModelIndex &parent) const { if (col < 0 || col > 1) { return QModelIndex(); } if (!parent.isValid()) { // This is a group if (row < 0 || row >= m_sections.size()) { return QModelIndex(); } return createIndex(row, col, col == 0 ? 2 : 3); // ???????? } else { // This is an entry int group = parent.row(); if (row < 0 || row >= m_sections[group]->size()) { return QModelIndex(); } return createIndex(row, col, static_cast(group)); } } QModelIndex MetadataModel::parent(const QModelIndex & index) const { if (!index.isValid()) { return QModelIndex(); } if (index.internalId() == 2 || index.internalId() == 3) { return QModelIndex(); } else { return createIndex(static_cast(index.internalId()), 0, 2); } } int MetadataModel::rowCount(const QModelIndex & parent) const { if (!parent.isValid()) { return m_sections.size(); } else if (parent.internalId() == 2) { return m_sections[parent.row()]->size(); } else { return 0; } } int MetadataModel::columnCount(const QModelIndex &) const { return 2; } QVariant MetadataModel::data(const QModelIndex &index, int role) const { if (!index.isValid()) { return QVariant(); } switch (role) { case Qt::DisplayRole: return displayData(index); default: return QVariant(); } } void MetadataModel::initGeneralSection() { MetadataSection * s = section(GeneralSection); s->addEnrty(QStringLiteral("General.Name"), tr("File Name")); s->addEnrty(QStringLiteral("General.Size"), tr("File Size")); s->addEnrty(QStringLiteral("General.Time"), tr("Last Modified")); s->addEnrty(QStringLiteral("General.ImageSize"), tr("Image Size")); } bool MetadataModel::sectionRegister(Sections sectionType, MetadataSection *section) { if (m_sectionEnumIndexMap.contains(sectionType)) { return false; } m_sections.append(section); m_sectionEnumIndexMap[sectionType] = section; return true; } void MetadataModel::setSectionEntryValue(Sections sectionType, const QString &key, const QString &value) { MetadataSection * s = section(sectionType); int entryIndex = s->keyIndex(key); if (entryIndex < 0) { // no such entry return; } s->setValueAt(entryIndex, value); } MetadataSection *MetadataModel::section(Sections sectionType) { return m_sectionEnumIndexMap[sectionType]; } QVariant MetadataModel::displayData(const QModelIndex &index) const { if (index.internalId() == 2) { if (index.column() != 0) { return QVariant(); } QString label = m_sections[index.row()]->sectionName(); return QVariant(label); } if (index.internalId() == 3) { return QString(); } MetadataSection* group = m_sections[index.internalId()]; if (index.column() == 0) { return group->labelAt(index.row()); } else { return group->valueAt(index.row()); } }