268 lines
6.9 KiB
C++
268 lines
6.9 KiB
C++
|
#include "metadatamodel.h"
|
||
|
|
||
|
#include <QFileInfo>
|
||
|
#include <QDateTime>
|
||
|
#include <QLocale>
|
||
|
#include <QSize>
|
||
|
#include <QImageReader>
|
||
|
|
||
|
// 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<Entry*> m_entries;
|
||
|
QHash<QString, int> 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<quintptr>(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<int>(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());
|
||
|
}
|
||
|
}
|