feat: simple property dialog
This commit is contained in:
parent
95fd0f881c
commit
71c38c8e96
|
@ -23,6 +23,8 @@ set (PPIC_CPP_FILES
|
||||||
settings.cpp
|
settings.cpp
|
||||||
settingsdialog.cpp
|
settingsdialog.cpp
|
||||||
aboutdialog.cpp
|
aboutdialog.cpp
|
||||||
|
metadatamodel.cpp
|
||||||
|
metadatadialog.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set (PPIC_HEADER_FILES
|
set (PPIC_HEADER_FILES
|
||||||
|
@ -36,6 +38,8 @@ set (PPIC_HEADER_FILES
|
||||||
settings.h
|
settings.h
|
||||||
settingsdialog.h
|
settingsdialog.h
|
||||||
aboutdialog.h
|
aboutdialog.h
|
||||||
|
metadatamodel.h
|
||||||
|
metadatadialog.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set (PPIC_QRC_FILES
|
set (PPIC_QRC_FILES
|
||||||
|
|
|
@ -193,58 +193,105 @@
|
||||||
<context>
|
<context>
|
||||||
<name>MainWindow</name>
|
<name>MainWindow</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../mainwindow.cpp" line="175"/>
|
<location filename="../mainwindow.cpp" line="178"/>
|
||||||
<source>File url list is empty</source>
|
<source>File url list is empty</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../mainwindow.cpp" line="408"/>
|
<location filename="../mainwindow.cpp" line="417"/>
|
||||||
<source>&Copy</source>
|
<source>&Copy</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../mainwindow.cpp" line="429"/>
|
<location filename="../mainwindow.cpp" line="438"/>
|
||||||
<source>Copy P&ixmap</source>
|
<source>Copy P&ixmap</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../mainwindow.cpp" line="434"/>
|
<location filename="../mainwindow.cpp" line="443"/>
|
||||||
<source>Copy &File Path</source>
|
<source>Copy &File Path</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../mainwindow.cpp" line="444"/>
|
<location filename="../mainwindow.cpp" line="453"/>
|
||||||
<source>&Paste Image</source>
|
<source>&Paste Image</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../mainwindow.cpp" line="450"/>
|
<location filename="../mainwindow.cpp" line="459"/>
|
||||||
<source>&Paste Image File</source>
|
<source>&Paste Image File</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../mainwindow.cpp" line="492"/>
|
||||||
|
<source>Properties</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../aboutdialog.cpp" line="30"/>
|
<location filename="../aboutdialog.cpp" line="30"/>
|
||||||
<location filename="../mainwindow.cpp" line="455"/>
|
<location filename="../mainwindow.cpp" line="464"/>
|
||||||
<source>Stay on top</source>
|
<source>Stay on top</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../aboutdialog.cpp" line="34"/>
|
<location filename="../aboutdialog.cpp" line="34"/>
|
||||||
<location filename="../mainwindow.cpp" line="462"/>
|
<location filename="../mainwindow.cpp" line="471"/>
|
||||||
<source>Protected mode</source>
|
<source>Protected mode</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../mainwindow.cpp" line="469"/>
|
<location filename="../mainwindow.cpp" line="478"/>
|
||||||
<source>Configure...</source>
|
<source>Configure...</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../mainwindow.cpp" line="476"/>
|
<location filename="../mainwindow.cpp" line="485"/>
|
||||||
<source>Help</source>
|
<source>Help</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
|
<context>
|
||||||
|
<name>MetadataDialog</name>
|
||||||
|
<message>
|
||||||
|
<location filename="../metadatadialog.cpp" line="16"/>
|
||||||
|
<source>Image Metadata</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
</context>
|
||||||
|
<context>
|
||||||
|
<name>MetadataModel</name>
|
||||||
|
<message>
|
||||||
|
<location filename="../metadatamodel.cpp" line="29"/>
|
||||||
|
<source>General</source>
|
||||||
|
<comment>General info about the image, section name.</comment>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../metadatamodel.cpp" line="32"/>
|
||||||
|
<source>File Name</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../metadatamodel.cpp" line="34"/>
|
||||||
|
<source>File Size</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../metadatamodel.cpp" line="36"/>
|
||||||
|
<source>Last Modified</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../metadatamodel.cpp" line="38"/>
|
||||||
|
<source>Image Size</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../metadatamodel.cpp" line="46"/>
|
||||||
|
<source>%1 x %2</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>SettingsDialog</name>
|
<name>SettingsDialog</name>
|
||||||
<message>
|
<message>
|
||||||
|
|
|
@ -193,58 +193,105 @@
|
||||||
<context>
|
<context>
|
||||||
<name>MainWindow</name>
|
<name>MainWindow</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../mainwindow.cpp" line="175"/>
|
<location filename="../mainwindow.cpp" line="178"/>
|
||||||
<source>File url list is empty</source>
|
<source>File url list is empty</source>
|
||||||
<translation>文件 URL 列表为空</translation>
|
<translation>文件 URL 列表为空</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../mainwindow.cpp" line="408"/>
|
<location filename="../mainwindow.cpp" line="417"/>
|
||||||
<source>&Copy</source>
|
<source>&Copy</source>
|
||||||
<translation>复制(&C)</translation>
|
<translation>复制(&C)</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../mainwindow.cpp" line="429"/>
|
<location filename="../mainwindow.cpp" line="438"/>
|
||||||
<source>Copy P&ixmap</source>
|
<source>Copy P&ixmap</source>
|
||||||
<translation>复制位图(&I)</translation>
|
<translation>复制位图(&I)</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../mainwindow.cpp" line="434"/>
|
<location filename="../mainwindow.cpp" line="443"/>
|
||||||
<source>Copy &File Path</source>
|
<source>Copy &File Path</source>
|
||||||
<translation>复制文件路径(&F)</translation>
|
<translation>复制文件路径(&F)</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../mainwindow.cpp" line="444"/>
|
<location filename="../mainwindow.cpp" line="453"/>
|
||||||
<source>&Paste Image</source>
|
<source>&Paste Image</source>
|
||||||
<translation>粘贴图像(&P)</translation>
|
<translation>粘贴图像(&P)</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../mainwindow.cpp" line="450"/>
|
<location filename="../mainwindow.cpp" line="459"/>
|
||||||
<source>&Paste Image File</source>
|
<source>&Paste Image File</source>
|
||||||
<translation>粘贴图像文件(&P)</translation>
|
<translation>粘贴图像文件(&P)</translation>
|
||||||
</message>
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../mainwindow.cpp" line="492"/>
|
||||||
|
<source>Properties</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../aboutdialog.cpp" line="30"/>
|
<location filename="../aboutdialog.cpp" line="30"/>
|
||||||
<location filename="../mainwindow.cpp" line="455"/>
|
<location filename="../mainwindow.cpp" line="464"/>
|
||||||
<source>Stay on top</source>
|
<source>Stay on top</source>
|
||||||
<translation>总在最前</translation>
|
<translation>总在最前</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../aboutdialog.cpp" line="34"/>
|
<location filename="../aboutdialog.cpp" line="34"/>
|
||||||
<location filename="../mainwindow.cpp" line="462"/>
|
<location filename="../mainwindow.cpp" line="471"/>
|
||||||
<source>Protected mode</source>
|
<source>Protected mode</source>
|
||||||
<translation>保护模式</translation>
|
<translation>保护模式</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../mainwindow.cpp" line="469"/>
|
<location filename="../mainwindow.cpp" line="478"/>
|
||||||
<source>Configure...</source>
|
<source>Configure...</source>
|
||||||
<translation>设置...</translation>
|
<translation>设置...</translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../mainwindow.cpp" line="476"/>
|
<location filename="../mainwindow.cpp" line="485"/>
|
||||||
<source>Help</source>
|
<source>Help</source>
|
||||||
<translation>帮助</translation>
|
<translation>帮助</translation>
|
||||||
</message>
|
</message>
|
||||||
</context>
|
</context>
|
||||||
|
<context>
|
||||||
|
<name>MetadataDialog</name>
|
||||||
|
<message>
|
||||||
|
<location filename="../metadatadialog.cpp" line="16"/>
|
||||||
|
<source>Image Metadata</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
</context>
|
||||||
|
<context>
|
||||||
|
<name>MetadataModel</name>
|
||||||
|
<message>
|
||||||
|
<location filename="../metadatamodel.cpp" line="29"/>
|
||||||
|
<source>General</source>
|
||||||
|
<comment>General info about the image, section name.</comment>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../metadatamodel.cpp" line="32"/>
|
||||||
|
<source>File Name</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../metadatamodel.cpp" line="34"/>
|
||||||
|
<source>File Size</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../metadatamodel.cpp" line="36"/>
|
||||||
|
<source>Last Modified</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../metadatamodel.cpp" line="38"/>
|
||||||
|
<source>Image Size</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
<message>
|
||||||
|
<location filename="../metadatamodel.cpp" line="46"/>
|
||||||
|
<source>%1 x %2</source>
|
||||||
|
<translation type="unfinished"></translation>
|
||||||
|
</message>
|
||||||
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>SettingsDialog</name>
|
<name>SettingsDialog</name>
|
||||||
<message>
|
<message>
|
||||||
|
|
|
@ -8,6 +8,8 @@
|
||||||
#include "graphicsscene.h"
|
#include "graphicsscene.h"
|
||||||
#include "settingsdialog.h"
|
#include "settingsdialog.h"
|
||||||
#include "aboutdialog.h"
|
#include "aboutdialog.h"
|
||||||
|
#include "metadatamodel.h"
|
||||||
|
#include "metadatadialog.h"
|
||||||
|
|
||||||
#include <QMouseEvent>
|
#include <QMouseEvent>
|
||||||
#include <QMovie>
|
#include <QMovie>
|
||||||
|
@ -487,6 +489,17 @@ void MainWindow::contextMenuEvent(QContextMenuEvent *event)
|
||||||
ad->deleteLater();
|
ad->deleteLater();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
QAction * propertiesAction = new QAction(tr("Properties"));
|
||||||
|
connect(propertiesAction, &QAction::triggered, this, [ = ](){
|
||||||
|
MetadataModel * md = new MetadataModel();
|
||||||
|
md->setFile(currentFileUrl.toLocalFile());
|
||||||
|
|
||||||
|
MetadataDialog * ad = new MetadataDialog(this);
|
||||||
|
ad->setMetadataModel(md);
|
||||||
|
ad->exec();
|
||||||
|
ad->deleteLater();
|
||||||
|
});
|
||||||
|
|
||||||
if (copyMenu->actions().count() == 1) {
|
if (copyMenu->actions().count() == 1) {
|
||||||
menu->addActions(copyMenu->actions());
|
menu->addActions(copyMenu->actions());
|
||||||
} else {
|
} else {
|
||||||
|
@ -503,6 +516,10 @@ void MainWindow::contextMenuEvent(QContextMenuEvent *event)
|
||||||
menu->addSeparator();
|
menu->addSeparator();
|
||||||
menu->addAction(toggleSettings);
|
menu->addAction(toggleSettings);
|
||||||
menu->addAction(helpAction);
|
menu->addAction(helpAction);
|
||||||
|
if (currentFileUrl.isValid()) {
|
||||||
|
menu->addSeparator();
|
||||||
|
menu->addAction(propertiesAction);
|
||||||
|
}
|
||||||
menu->exec(mapToGlobal(event->pos()));
|
menu->exec(mapToGlobal(event->pos()));
|
||||||
menu->deleteLater();
|
menu->deleteLater();
|
||||||
|
|
||||||
|
|
101
metadatadialog.cpp
Normal file
101
metadatadialog.cpp
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
#include "metadatadialog.h"
|
||||||
|
|
||||||
|
#include <QDialogButtonBox>
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QStyledItemDelegate>
|
||||||
|
#include <QTreeView>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <QHeaderView>
|
||||||
|
|
||||||
|
#include "metadatamodel.h"
|
||||||
|
|
||||||
|
class PropertyTreeView : public QTreeView
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit PropertyTreeView(QWidget* parent) : QTreeView(parent) {}
|
||||||
|
~PropertyTreeView() {}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void rowsInserted(const QModelIndex& parent, int start, int end) override
|
||||||
|
{
|
||||||
|
QTreeView::rowsInserted(parent, start, end);
|
||||||
|
if (!parent.isValid()) {
|
||||||
|
for (int row = start; row <= end; ++row) {
|
||||||
|
setupSection(row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset() override
|
||||||
|
{
|
||||||
|
QTreeView::reset();
|
||||||
|
if (model()) {
|
||||||
|
for (int row = 0; row < model()->rowCount(); ++row) {
|
||||||
|
setupSection(row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void setupSection(int row)
|
||||||
|
{
|
||||||
|
expand(model()->index(row, 0));
|
||||||
|
setFirstColumnSpanned(row, QModelIndex(), true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class PropertyTreeItemDelegate : public QStyledItemDelegate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PropertyTreeItemDelegate(QObject* parent)
|
||||||
|
: QStyledItemDelegate(parent)
|
||||||
|
{}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override
|
||||||
|
{
|
||||||
|
QStyleOptionViewItem opt = option;
|
||||||
|
if (!index.parent().isValid()) {
|
||||||
|
opt.font.setBold(true);
|
||||||
|
opt.features.setFlag(QStyleOptionViewItem::Alternate);
|
||||||
|
}
|
||||||
|
QStyledItemDelegate::paint(painter, opt, index);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
MetadataDialog::MetadataDialog(QWidget *parent)
|
||||||
|
: QDialog(parent)
|
||||||
|
, m_treeView(new PropertyTreeView(this))
|
||||||
|
{
|
||||||
|
m_treeView->setRootIsDecorated(false);
|
||||||
|
m_treeView->setIndentation(0);
|
||||||
|
m_treeView->setItemDelegate(new PropertyTreeItemDelegate(m_treeView));
|
||||||
|
m_treeView->header()->resizeSection(0, sizeHint().width() / 2);
|
||||||
|
|
||||||
|
setWindowTitle(tr("Image Metadata"));
|
||||||
|
|
||||||
|
QDialogButtonBox * buttonBox = new QDialogButtonBox(QDialogButtonBox::Close);
|
||||||
|
|
||||||
|
setLayout(new QVBoxLayout);
|
||||||
|
layout()->addWidget(m_treeView);
|
||||||
|
layout()->addWidget(buttonBox);
|
||||||
|
|
||||||
|
connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::close);
|
||||||
|
|
||||||
|
setWindowFlag(Qt::WindowContextHelpButtonHint, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
MetadataDialog::~MetadataDialog()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void MetadataDialog::setMetadataModel(MetadataModel * model)
|
||||||
|
{
|
||||||
|
m_treeView->setModel(model);
|
||||||
|
}
|
||||||
|
|
||||||
|
QSize MetadataDialog::sizeHint() const
|
||||||
|
{
|
||||||
|
return QSize(520, 350);
|
||||||
|
}
|
26
metadatadialog.h
Normal file
26
metadatadialog.h
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
#ifndef METADATADIALOG_H
|
||||||
|
#define METADATADIALOG_H
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
class QTreeView;
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
class MetadataModel;
|
||||||
|
class MetadataDialog : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit MetadataDialog(QWidget * parent);
|
||||||
|
~MetadataDialog() override;
|
||||||
|
|
||||||
|
void setMetadataModel(MetadataModel * model);
|
||||||
|
|
||||||
|
QSize sizeHint() const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QTreeView * m_treeView = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // METADATADIALOG_H
|
168
metadatamodel.cpp
Normal file
168
metadatamodel.cpp
Normal file
|
@ -0,0 +1,168 @@
|
||||||
|
#include "metadatamodel.h"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QDateTime>
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include <QImageReader>
|
||||||
|
|
||||||
|
MetadataModel::MetadataModel(QObject *parent)
|
||||||
|
: QAbstractItemModel(parent)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
MetadataModel::~MetadataModel()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void MetadataModel::setFile(const QString &imageFilePath)
|
||||||
|
{
|
||||||
|
QFileInfo fileInfo(imageFilePath);
|
||||||
|
// It'll be fine if we don't re-use the image reader we pass to the graphics scene for now.
|
||||||
|
QImageReader imgReader(imageFilePath);
|
||||||
|
|
||||||
|
const QString & sizeString = QLocale().formattedDataSize(fileInfo.size());
|
||||||
|
const QString & timeString = QLocale().toString(fileInfo.lastModified(), QLocale::LongFormat);
|
||||||
|
const QString & imageSizeString = imageSize(imgReader.size());
|
||||||
|
|
||||||
|
appendSection(QStringLiteral("General"), tr("General", "General info about the image, section name."));
|
||||||
|
|
||||||
|
appendProperty(QStringLiteral("General"), QStringLiteral("General.Name"),
|
||||||
|
tr("File Name"), fileInfo.fileName());
|
||||||
|
appendProperty(QStringLiteral("General"), QStringLiteral("General.Size"),
|
||||||
|
tr("File Size"), sizeString);
|
||||||
|
appendProperty(QStringLiteral("General"), QStringLiteral("General.Time"),
|
||||||
|
tr("Last Modified"), timeString);
|
||||||
|
appendProperty(QStringLiteral("General"), QStringLiteral("General.ImageSize"),
|
||||||
|
tr("Image Size"), imageSizeString);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString MetadataModel::imageSize(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('-');
|
||||||
|
}
|
||||||
|
|
||||||
|
return imageSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MetadataModel::appendSection(const QString §ionKey, const QString §ionDisplayName)
|
||||||
|
{
|
||||||
|
if (m_sections.contains(sectionKey)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_sections.append(sectionKey);
|
||||||
|
m_sectionProperties[sectionKey] = qMakePair<QString, QList<QString> >(sectionDisplayName, {});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MetadataModel::appendProperty(const QString §ionKey, const QString &propertyKey, const QString &propertyDisplayName, const QString &propertyValue)
|
||||||
|
{
|
||||||
|
if (!m_sections.contains(sectionKey)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<QString> & propertyList = m_sectionProperties[sectionKey].second;
|
||||||
|
if (!propertyList.contains(propertyKey)) {
|
||||||
|
propertyList.append(propertyKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_properties[propertyKey] = qMakePair<QString, QString>(propertyDisplayName, propertyValue);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MetadataModel::updateProperty(const QString &propertyKey, const QString &propertyValue)
|
||||||
|
{
|
||||||
|
if (m_properties.contains(propertyKey)) {
|
||||||
|
m_properties[propertyKey].second = propertyValue;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex MetadataModel::index(int row, int column, const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
if (!hasIndex(row, column, parent)) {
|
||||||
|
return QModelIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!parent.isValid()) {
|
||||||
|
return createIndex(row, column, RowType::SectionRow);
|
||||||
|
} else {
|
||||||
|
// internalid param: row means nth section it belongs to.
|
||||||
|
return createIndex(row, column, RowType::PropertyRow + parent.row());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex MetadataModel::parent(const QModelIndex &child) const
|
||||||
|
{
|
||||||
|
if (!child.isValid()) {
|
||||||
|
return QModelIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (child.internalId() == RowType::SectionRow) {
|
||||||
|
return QModelIndex();
|
||||||
|
} else {
|
||||||
|
return createIndex(child.internalId() - RowType::PropertyRow, 0, SectionRow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int MetadataModel::rowCount(const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
if (!parent.isValid()) {
|
||||||
|
return m_sections.count();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parent.internalId() == RowType::SectionRow) {
|
||||||
|
const QString & sectionKey = m_sections[parent.row()];
|
||||||
|
return m_sectionProperties[sectionKey].second.count();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int MetadataModel::columnCount(const QModelIndex &) const
|
||||||
|
{
|
||||||
|
// Always key(display name) and value.
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant MetadataModel::data(const QModelIndex &index, int role) const
|
||||||
|
{
|
||||||
|
if (!index.isValid()) {
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (role != Qt::DisplayRole) {
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index.internalId() == RowType::SectionRow) {
|
||||||
|
return (index.column() == 0) ? m_sectionProperties[m_sections[index.row()]].first
|
||||||
|
: QVariant();
|
||||||
|
} else {
|
||||||
|
int sectionIndex = index.internalId() - RowType::PropertyRow;
|
||||||
|
const QString & sectionKey = m_sections[sectionIndex];
|
||||||
|
const QList<QString> & propertyList = m_sectionProperties[sectionKey].second;
|
||||||
|
return (index.column() == 0) ? m_properties[propertyList[index.row()]].first
|
||||||
|
: m_properties[propertyList[index.row()]].second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant MetadataModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||||
|
{
|
||||||
|
if (orientation == Qt::Vertical || role != Qt::DisplayRole) {
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
return section == 0 ? tr("Property") : tr("Value");
|
||||||
|
}
|
42
metadatamodel.h
Normal file
42
metadatamodel.h
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
#ifndef METADATAMODEL_H
|
||||||
|
#define METADATAMODEL_H
|
||||||
|
|
||||||
|
#include <QAbstractItemModel>
|
||||||
|
|
||||||
|
class MetadataModel : public QAbstractItemModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit MetadataModel(QObject *parent = nullptr);
|
||||||
|
~MetadataModel();
|
||||||
|
|
||||||
|
void setFile(const QString & imageFilePath);
|
||||||
|
static QString imageSize(const QSize &size);
|
||||||
|
bool appendSection(const QString & sectionKey, const QString & sectionDisplayName);
|
||||||
|
bool appendProperty(const QString & sectionKey, const QString & propertyKey,
|
||||||
|
const QString & propertyDisplayName, const QString & propertyValue = QString());
|
||||||
|
bool updateProperty(const QString & propertyKey, const QString & propertyValue);
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum RowType : quintptr {
|
||||||
|
SectionRow,
|
||||||
|
PropertyRow,
|
||||||
|
};
|
||||||
|
|
||||||
|
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
QModelIndex parent(const QModelIndex &child) const override;
|
||||||
|
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
int columnCount(const QModelIndex & = QModelIndex()) const override;
|
||||||
|
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||||
|
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
|
||||||
|
|
||||||
|
// [SECTION_KEY]
|
||||||
|
QList<QString> m_sections;
|
||||||
|
// {SECTION_KEY: (SECTION_DISPLAY_NAME, [PROPERTY_KEY])}
|
||||||
|
QMap<QString, QPair<QString, QList<QString> > > m_sectionProperties;
|
||||||
|
// {PROPERTY_KEY: (PROPERTY_DISPLAY_NAME, PROPERTY_VALUE)}
|
||||||
|
QMap<QString, QPair<QString, QString> > m_properties;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // METADATAMODEL_H
|
|
@ -1,9 +1,3 @@
|
||||||
#-------------------------------------------------
|
|
||||||
#
|
|
||||||
# Project created by QtCreator 2019-09-26T23:36:07
|
|
||||||
#
|
|
||||||
#-------------------------------------------------
|
|
||||||
|
|
||||||
QT += core widgets gui svg
|
QT += core widgets gui svg
|
||||||
|
|
||||||
TARGET = ppic
|
TARGET = ppic
|
||||||
|
@ -24,8 +18,8 @@ CONFIG += c++11 lrelease embed_translations
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
aboutdialog.cpp \
|
aboutdialog.cpp \
|
||||||
main.cpp \
|
main.cpp \
|
||||||
mainwindow.cpp \
|
mainwindow.cpp \
|
||||||
graphicsview.cpp \
|
graphicsview.cpp \
|
||||||
bottombuttongroup.cpp \
|
bottombuttongroup.cpp \
|
||||||
graphicsscene.cpp \
|
graphicsscene.cpp \
|
||||||
|
@ -33,11 +27,13 @@ SOURCES += \
|
||||||
opacityhelper.cpp \
|
opacityhelper.cpp \
|
||||||
toolbutton.cpp \
|
toolbutton.cpp \
|
||||||
settings.cpp \
|
settings.cpp \
|
||||||
settingsdialog.cpp
|
settingsdialog.cpp \
|
||||||
|
metadatamodel.cpp \
|
||||||
|
metadatadialog.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
aboutdialog.h \
|
aboutdialog.h \
|
||||||
mainwindow.h \
|
mainwindow.h \
|
||||||
graphicsview.h \
|
graphicsview.h \
|
||||||
bottombuttongroup.h \
|
bottombuttongroup.h \
|
||||||
graphicsscene.h \
|
graphicsscene.h \
|
||||||
|
@ -45,7 +41,9 @@ HEADERS += \
|
||||||
opacityhelper.h \
|
opacityhelper.h \
|
||||||
toolbutton.h \
|
toolbutton.h \
|
||||||
settings.h \
|
settings.h \
|
||||||
settingsdialog.h
|
settingsdialog.h \
|
||||||
|
metadatamodel.h \
|
||||||
|
metadatadialog.h
|
||||||
|
|
||||||
TRANSLATIONS = \
|
TRANSLATIONS = \
|
||||||
languages/PineapplePictures.ts \
|
languages/PineapplePictures.ts \
|
||||||
|
|
Loading…
Reference in New Issue
Block a user