Compare commits
	
		
			1 Commits
		
	
	
		
			0.3.4
			...
			wip-proper
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 83246f04ae | 
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@ -1,6 +1,5 @@
 | 
			
		||||
# User files
 | 
			
		||||
*.user
 | 
			
		||||
*.user.*
 | 
			
		||||
 | 
			
		||||
# Translation files
 | 
			
		||||
*.qm
 | 
			
		||||
 | 
			
		||||
@ -12,34 +12,30 @@ set (QT_MINIMUM_VERSION "5.10")
 | 
			
		||||
find_package(Qt5 ${QT_MINIMUM_VERSION} CONFIG REQUIRED Widgets Svg LinguistTools)
 | 
			
		||||
 | 
			
		||||
set (PPIC_CPP_FILES
 | 
			
		||||
    app/main.cpp
 | 
			
		||||
    app/mainwindow.cpp
 | 
			
		||||
    app/graphicsview.cpp
 | 
			
		||||
    app/graphicsscene.cpp
 | 
			
		||||
    app/bottombuttongroup.cpp
 | 
			
		||||
    app/navigatorview.cpp
 | 
			
		||||
    app/opacityhelper.cpp
 | 
			
		||||
    app/toolbutton.cpp
 | 
			
		||||
    app/settings.cpp
 | 
			
		||||
    app/settingsdialog.cpp
 | 
			
		||||
    app/aboutdialog.cpp
 | 
			
		||||
    app/metadatamodel.cpp
 | 
			
		||||
    app/metadatadialog.cpp
 | 
			
		||||
    main.cpp
 | 
			
		||||
    mainwindow.cpp
 | 
			
		||||
    graphicsview.cpp
 | 
			
		||||
    graphicsscene.cpp
 | 
			
		||||
    bottombuttongroup.cpp
 | 
			
		||||
    navigatorview.cpp
 | 
			
		||||
    opacityhelper.cpp
 | 
			
		||||
    toolbutton.cpp
 | 
			
		||||
    settings.cpp
 | 
			
		||||
    settingsdialog.cpp
 | 
			
		||||
    aboutdialog.cpp
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
set (PPIC_HEADER_FILES
 | 
			
		||||
    app/mainwindow.h
 | 
			
		||||
    app/graphicsview.h
 | 
			
		||||
    app/graphicsscene.h
 | 
			
		||||
    app/bottombuttongroup.h
 | 
			
		||||
    app/navigatorview.h
 | 
			
		||||
    app/opacityhelper.h
 | 
			
		||||
    app/toolbutton.h
 | 
			
		||||
    app/settings.h
 | 
			
		||||
    app/settingsdialog.h
 | 
			
		||||
    app/aboutdialog.h
 | 
			
		||||
    app/metadatamodel.h
 | 
			
		||||
    app/metadatadialog.h
 | 
			
		||||
    mainwindow.h
 | 
			
		||||
    graphicsview.h
 | 
			
		||||
    graphicsscene.h
 | 
			
		||||
    bottombuttongroup.h
 | 
			
		||||
    navigatorview.h
 | 
			
		||||
    opacityhelper.h
 | 
			
		||||
    toolbutton.h
 | 
			
		||||
    settings.h
 | 
			
		||||
    settingsdialog.h
 | 
			
		||||
    aboutdialog.h
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
set (PPIC_QRC_FILES
 | 
			
		||||
@ -53,7 +49,7 @@ set (PPIC_RC_FILES
 | 
			
		||||
set (EXE_NAME ppic)
 | 
			
		||||
 | 
			
		||||
# Translation
 | 
			
		||||
file (GLOB PPIC_TS_FILES translations/*.ts)
 | 
			
		||||
file (GLOB PPIC_TS_FILES languages/*.ts)
 | 
			
		||||
set (PPIC_CPP_FILES_FOR_I18N ${PPIC_CPP_FILES})
 | 
			
		||||
 | 
			
		||||
qt5_create_translation(PPIC_QM_FILES ${PPIC_CPP_FILES_FOR_I18N} ${PPIC_TS_FILES})
 | 
			
		||||
 | 
			
		||||
@ -1,101 +0,0 @@
 | 
			
		||||
#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);
 | 
			
		||||
}
 | 
			
		||||
@ -1,205 +0,0 @@
 | 
			
		||||
#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);
 | 
			
		||||
    imgReader.setAutoTransform(true);
 | 
			
		||||
    imgReader.setDecideFormatFromContent(true);
 | 
			
		||||
 | 
			
		||||
    const QString & itemTypeString = tr("%1 File").arg(QString(imgReader.format().toUpper()));
 | 
			
		||||
    const QString & sizeString = QLocale().formattedDataSize(fileInfo.size());
 | 
			
		||||
    const QString & birthTimeString = QLocale().toString(fileInfo.birthTime(), QLocale::LongFormat);
 | 
			
		||||
    const QString & lastModifiedTimeString = QLocale().toString(fileInfo.lastModified(), QLocale::LongFormat);
 | 
			
		||||
    const QString & imageDimensionsString = imageSize(imgReader.size());
 | 
			
		||||
    const QString & imageRatioString = imageSizeRatio(imgReader.size());
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
    appendSection(QStringLiteral("Description"), tr("Description", "Section name."));
 | 
			
		||||
    appendSection(QStringLiteral("Origin"), tr("Origin", "Section name."));
 | 
			
		||||
#endif // 0
 | 
			
		||||
    appendSection(QStringLiteral("Image"), tr("Image", "Section name."));
 | 
			
		||||
#if 0
 | 
			
		||||
    appendSection(QStringLiteral("Camera"), tr("Camera", "Section name."));
 | 
			
		||||
    appendSection(QStringLiteral("AdvancedPhoto"), tr("Advanced photo", "Section name."));
 | 
			
		||||
    appendSection(QStringLiteral("GPS"), tr("GPS", "Section name."));
 | 
			
		||||
#endif // 0
 | 
			
		||||
    appendSection(QStringLiteral("File"), tr("File", "Section name."));
 | 
			
		||||
 | 
			
		||||
    appendProperty(QStringLiteral("Image"), QStringLiteral("Image.Dimensions"),
 | 
			
		||||
                   tr("Dimensions"), imageDimensionsString);
 | 
			
		||||
    appendProperty(QStringLiteral("Image"), QStringLiteral("Image.SizeRatio"),
 | 
			
		||||
                   tr("Aspect Ratio"), imageRatioString);
 | 
			
		||||
 | 
			
		||||
    appendProperty(QStringLiteral("File"), QStringLiteral("File.Name"),
 | 
			
		||||
                   tr("Name"), fileInfo.fileName());
 | 
			
		||||
    appendProperty(QStringLiteral("File"), QStringLiteral("File.ItemType"),
 | 
			
		||||
                   tr("Item type"), itemTypeString);
 | 
			
		||||
    appendProperty(QStringLiteral("File"), QStringLiteral("File.Path"),
 | 
			
		||||
                   tr("Folder path"), fileInfo.path());
 | 
			
		||||
    appendProperty(QStringLiteral("File"), QStringLiteral("File.Size"),
 | 
			
		||||
                   tr("Size"), sizeString);
 | 
			
		||||
    appendProperty(QStringLiteral("File"), QStringLiteral("File.CreatedTime"),
 | 
			
		||||
                   tr("Date Created"), birthTimeString);
 | 
			
		||||
    appendProperty(QStringLiteral("File"), QStringLiteral("File.LastModified"),
 | 
			
		||||
                   tr("Date Modified"), lastModifiedTimeString);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int simplegcd(int a, int b) {
 | 
			
		||||
    return b == 0 ? a : simplegcd(b, a % b);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString MetadataModel::imageSizeRatio(const QSize &size)
 | 
			
		||||
{
 | 
			
		||||
    if (!size.isValid()) {
 | 
			
		||||
        return QStringLiteral("-");
 | 
			
		||||
    }
 | 
			
		||||
    int gcd = simplegcd(size.width(), size.height());
 | 
			
		||||
    return tr("%1 : %2").arg(QString::number(size.width() / gcd), QString::number(size.height() / gcd));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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");
 | 
			
		||||
}
 | 
			
		||||
@ -1,43 +0,0 @@
 | 
			
		||||
#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);
 | 
			
		||||
    static QString imageSizeRatio(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
 | 
			
		||||
@ -33,7 +33,7 @@ BottomButtonGroup::BottomButtonGroup(QWidget *parent)
 | 
			
		||||
        QPushButton * btn = new QPushButton(QIcon(QStringLiteral(":/icons/") + text), "");
 | 
			
		||||
        btn->setIconSize(QSize(40, 40));
 | 
			
		||||
        btn->setFixedSize(40, 40);
 | 
			
		||||
        QObject::connect(btn, &QAbstractButton::clicked, btn, func);
 | 
			
		||||
        connect(btn, &QAbstractButton::clicked, btn, func);
 | 
			
		||||
        return btn;
 | 
			
		||||
    };
 | 
			
		||||
    addButton(newBtn("zoom-original", [this]() {
 | 
			
		||||
@ -2,7 +2,7 @@
 | 
			
		||||
<component type="desktop-application">
 | 
			
		||||
  <id>net.blumia.pineapple-pictures</id>
 | 
			
		||||
  <metadata_license>CC0-1.0</metadata_license>
 | 
			
		||||
  <project_license>MIT</project_license>
 | 
			
		||||
  <project_license>GPL-3.0+</project_license>
 | 
			
		||||
  <name>Pineapple Pictures</name>
 | 
			
		||||
  <name xml:lang="zh-CN">菠萝看图</name>
 | 
			
		||||
  <summary>Image Viewer</summary>
 | 
			
		||||
 | 
			
		||||
@ -51,15 +51,8 @@ void GraphicsView::showFileFromUrl(const QUrl &url, bool doRequestGallery)
 | 
			
		||||
        // QImage::Format imageFormat = imageReader.imageFormat();
 | 
			
		||||
        if (imageReader.format().isEmpty()) {
 | 
			
		||||
            showText(tr("File is not a valid image"));
 | 
			
		||||
        } else if (!imageReader.supportsAnimation() && !imageReader.canRead()) {
 | 
			
		||||
            showText(tr("Image data is invalid or currently unsupported"));
 | 
			
		||||
        } else {
 | 
			
		||||
            const QPixmap & pixmap = QPixmap::fromImageReader(&imageReader);
 | 
			
		||||
            if (pixmap.isNull()) {
 | 
			
		||||
                showText(tr("Image data is invalid or currently unsupported"));
 | 
			
		||||
            } else {
 | 
			
		||||
                showImage(pixmap);
 | 
			
		||||
            }
 | 
			
		||||
            showImage(QPixmap::fromImageReader(&imageReader));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										1680
									
								
								icons/app-icon.svg
									
									
									
									
									
								
							
							
						
						
									
										1680
									
								
								icons/app-icon.svg
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
		 Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 40 KiB  | 
							
								
								
									
										294
									
								
								languages/PineapplePictures.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										294
									
								
								languages/PineapplePictures.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,294 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<!DOCTYPE TS>
 | 
			
		||||
<TS version="2.1">
 | 
			
		||||
<context>
 | 
			
		||||
    <name>AboutDialog</name>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="22"/>
 | 
			
		||||
        <source>About</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="25"/>
 | 
			
		||||
        <source>Launch application with image file path as argument to load the file.</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="26"/>
 | 
			
		||||
        <source>Drag and drop image file onto the window is also supported.</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="27"/>
 | 
			
		||||
        <source>Context menu option explanation:</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="31"/>
 | 
			
		||||
        <source>Make window stay on top of all other windows.</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="35"/>
 | 
			
		||||
        <source>Avoid close window accidentally. (eg. by double clicking the window)</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="44"/>
 | 
			
		||||
        <source>Version: %1</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="47"/>
 | 
			
		||||
        <source>Copyright (c) 2020 %1</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="49"/>
 | 
			
		||||
        <source>Logo designed by %1</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="51"/>
 | 
			
		||||
        <source>Built with Qt %1 (%2)</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="52"/>
 | 
			
		||||
        <source>Source code</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="58"/>
 | 
			
		||||
        <source>Contributors</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="60"/>
 | 
			
		||||
        <source>List of contributors on GitHub</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="61"/>
 | 
			
		||||
        <source>Thanks to all people who contributed to this project.</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="65"/>
 | 
			
		||||
        <source>Translators</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="66"/>
 | 
			
		||||
        <source>I would like to thank the following people who volunteered to translate this application.</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="131"/>
 | 
			
		||||
        <source>&Special Thanks</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="133"/>
 | 
			
		||||
        <source>&Third-party Libraries</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="72"/>
 | 
			
		||||
        <source>Your Rights</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="74"/>
 | 
			
		||||
        <source>%1 is released under the MIT License.</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="75"/>
 | 
			
		||||
        <source>This license grants people a number of freedoms:</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="76"/>
 | 
			
		||||
        <source>You are free to use %1, for any purpose</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="77"/>
 | 
			
		||||
        <source>You are free to distribute %1</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="78"/>
 | 
			
		||||
        <source>You can study how %1 works and change it</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="79"/>
 | 
			
		||||
        <source>You can distribute changed versions of %1</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="81"/>
 | 
			
		||||
        <source>The MIT license guarantees you this freedom. Nobody is ever permitted to take it away.</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="109"/>
 | 
			
		||||
        <source>Third-party Libraries used by %1</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="110"/>
 | 
			
		||||
        <source>%1 is built on the following free software libraries:</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="129"/>
 | 
			
		||||
        <source>&Help</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="130"/>
 | 
			
		||||
        <source>&About</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="132"/>
 | 
			
		||||
        <source>&License</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
</context>
 | 
			
		||||
<context>
 | 
			
		||||
    <name>GraphicsScene</name>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../graphicsscene.cpp" line="16"/>
 | 
			
		||||
        <source>Drag image here</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
</context>
 | 
			
		||||
<context>
 | 
			
		||||
    <name>GraphicsView</name>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../graphicsview.cpp" line="254"/>
 | 
			
		||||
        <source>File url list is empty</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../graphicsview.cpp" line="53"/>
 | 
			
		||||
        <source>File is not a valid image</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../graphicsview.cpp" line="262"/>
 | 
			
		||||
        <source>Image data is invalid</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../graphicsview.cpp" line="269"/>
 | 
			
		||||
        <source>Not supported mimedata: %1</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
</context>
 | 
			
		||||
<context>
 | 
			
		||||
    <name>MainWindow</name>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="175"/>
 | 
			
		||||
        <source>File url list is empty</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="408"/>
 | 
			
		||||
        <source>&Copy</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="429"/>
 | 
			
		||||
        <source>Copy P&ixmap</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="434"/>
 | 
			
		||||
        <source>Copy &File Path</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="444"/>
 | 
			
		||||
        <source>&Paste Image</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="450"/>
 | 
			
		||||
        <source>&Paste Image File</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="30"/>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="455"/>
 | 
			
		||||
        <source>Stay on top</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="34"/>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="462"/>
 | 
			
		||||
        <source>Protected mode</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="469"/>
 | 
			
		||||
        <source>Configure...</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="476"/>
 | 
			
		||||
        <source>Help</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
</context>
 | 
			
		||||
<context>
 | 
			
		||||
    <name>SettingsDialog</name>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../settingsdialog.cpp" line="15"/>
 | 
			
		||||
        <source>Settings</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../settingsdialog.cpp" line="20"/>
 | 
			
		||||
        <source>Do nothing</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../settingsdialog.cpp" line="21"/>
 | 
			
		||||
        <source>Close the window</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../settingsdialog.cpp" line="22"/>
 | 
			
		||||
        <source>Toggle maximize</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../settingsdialog.cpp" line="30"/>
 | 
			
		||||
        <source>Stay on top when start-up</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../settingsdialog.cpp" line="31"/>
 | 
			
		||||
        <source>Double-click behavior</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
</context>
 | 
			
		||||
<context>
 | 
			
		||||
    <name>main</name>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../main.cpp" line="27"/>
 | 
			
		||||
        <source>Pineapple Pictures</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../main.cpp" line="31"/>
 | 
			
		||||
        <source>File list.</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
</context>
 | 
			
		||||
</TS>
 | 
			
		||||
@ -4,157 +4,157 @@
 | 
			
		||||
<context>
 | 
			
		||||
    <name>AboutDialog</name>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="22"/>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="22"/>
 | 
			
		||||
        <source>About</source>
 | 
			
		||||
        <translation>关于</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="25"/>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="25"/>
 | 
			
		||||
        <source>Launch application with image file path as argument to load the file.</source>
 | 
			
		||||
        <translation>以图片文件的路径作为参数运行程序即可直接打开图片文件。</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="26"/>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="26"/>
 | 
			
		||||
        <source>Drag and drop image file onto the window is also supported.</source>
 | 
			
		||||
        <translation>也支持拖放图片文件到窗口内来加载图片。</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="27"/>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="27"/>
 | 
			
		||||
        <source>Context menu option explanation:</source>
 | 
			
		||||
        <translation>菜单项说明:</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="31"/>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="31"/>
 | 
			
		||||
        <source>Make window stay on top of all other windows.</source>
 | 
			
		||||
        <translation>使窗口始终至于其它非置顶窗口上方。</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="35"/>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="35"/>
 | 
			
		||||
        <source>Avoid close window accidentally. (eg. by double clicking the window)</source>
 | 
			
		||||
        <translation>避免窗口意外关闭。(如:不小心双击了窗口触发了关闭窗口行为)</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="44"/>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="44"/>
 | 
			
		||||
        <source>Version: %1</source>
 | 
			
		||||
        <translation>版本: %1</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="47"/>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="47"/>
 | 
			
		||||
        <source>Copyright (c) 2020 %1</source>
 | 
			
		||||
        <translation>版权所有 (c) 2020 %1</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="49"/>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="49"/>
 | 
			
		||||
        <source>Logo designed by %1</source>
 | 
			
		||||
        <translation>Logo 由 %1 设计</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="51"/>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="51"/>
 | 
			
		||||
        <source>Built with Qt %1 (%2)</source>
 | 
			
		||||
        <translation>使用 Qt %1 (%2) 进行构建</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="52"/>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="52"/>
 | 
			
		||||
        <source>Source code</source>
 | 
			
		||||
        <translation>源代码</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="58"/>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="58"/>
 | 
			
		||||
        <source>Contributors</source>
 | 
			
		||||
        <translation>贡献者</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="60"/>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="60"/>
 | 
			
		||||
        <source>List of contributors on GitHub</source>
 | 
			
		||||
        <translation>GitHub 上的贡献者列表</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="61"/>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="61"/>
 | 
			
		||||
        <source>Thanks to all people who contributed to this project.</source>
 | 
			
		||||
        <translation>感谢所有参与此项目的朋友。</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="65"/>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="65"/>
 | 
			
		||||
        <source>Translators</source>
 | 
			
		||||
        <translation>翻译者</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="66"/>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="66"/>
 | 
			
		||||
        <source>I would like to thank the following people who volunteered to translate this application.</source>
 | 
			
		||||
        <translation>我想要感谢下列自愿参与翻译此应用程序的朋友。</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="131"/>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="131"/>
 | 
			
		||||
        <source>&Special Thanks</source>
 | 
			
		||||
        <translation>致谢(&S)</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="133"/>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="133"/>
 | 
			
		||||
        <source>&Third-party Libraries</source>
 | 
			
		||||
        <translation>第三方程序库(&T)</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="72"/>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="72"/>
 | 
			
		||||
        <source>Your Rights</source>
 | 
			
		||||
        <translation>用户的权利</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="74"/>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="74"/>
 | 
			
		||||
        <source>%1 is released under the MIT License.</source>
 | 
			
		||||
        <translation>%1 是在 MIT 许可协议下发布的。</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="75"/>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="75"/>
 | 
			
		||||
        <source>This license grants people a number of freedoms:</source>
 | 
			
		||||
        <translation>此许可证赋予人们以下自由的权利:</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="76"/>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="76"/>
 | 
			
		||||
        <source>You are free to use %1, for any purpose</source>
 | 
			
		||||
        <translation>任何人都可以为了任何目的自由地使用 %1</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="77"/>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="77"/>
 | 
			
		||||
        <source>You are free to distribute %1</source>
 | 
			
		||||
        <translation>任何人都可以自由地分发 %1</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="78"/>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="78"/>
 | 
			
		||||
        <source>You can study how %1 works and change it</source>
 | 
			
		||||
        <translation>任何人都可以自由地研究 %1 的工作原理并对其进行修改</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="79"/>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="79"/>
 | 
			
		||||
        <source>You can distribute changed versions of %1</source>
 | 
			
		||||
        <translation>任何人都可以自由地分发修改过的 %1 版本</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="81"/>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="81"/>
 | 
			
		||||
        <source>The MIT license guarantees you this freedom. Nobody is ever permitted to take it away.</source>
 | 
			
		||||
        <translation>此软件通过 MIT 许可证赋予用户上述自由,任何人无权剥夺。</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="109"/>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="109"/>
 | 
			
		||||
        <source>Third-party Libraries used by %1</source>
 | 
			
		||||
        <translation>%1 使用的第三方程序库</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="110"/>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="110"/>
 | 
			
		||||
        <source>%1 is built on the following free software libraries:</source>
 | 
			
		||||
        <translation>%1 采用了下列自由软件程序库进行构建:</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="129"/>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="129"/>
 | 
			
		||||
        <source>&Help</source>
 | 
			
		||||
        <translation>帮助(&H)</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="130"/>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="130"/>
 | 
			
		||||
        <source>&About</source>
 | 
			
		||||
        <translation>关于(&A)</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="132"/>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="132"/>
 | 
			
		||||
        <source>&License</source>
 | 
			
		||||
        <translation>软件许可证(&L)</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
@ -162,7 +162,7 @@
 | 
			
		||||
<context>
 | 
			
		||||
    <name>GraphicsScene</name>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/graphicsscene.cpp" line="16"/>
 | 
			
		||||
        <location filename="../graphicsscene.cpp" line="16"/>
 | 
			
		||||
        <source>Drag image here</source>
 | 
			
		||||
        <translation>拖放图片至此</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
@ -170,28 +170,22 @@
 | 
			
		||||
<context>
 | 
			
		||||
    <name>GraphicsView</name>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/graphicsview.cpp" line="261"/>
 | 
			
		||||
        <location filename="../graphicsview.cpp" line="254"/>
 | 
			
		||||
        <source>File url list is empty</source>
 | 
			
		||||
        <translation>文件 URL 列表为空</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/graphicsview.cpp" line="53"/>
 | 
			
		||||
        <location filename="../graphicsview.cpp" line="53"/>
 | 
			
		||||
        <source>File is not a valid image</source>
 | 
			
		||||
        <translation>文件不是有效的图片文件</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/graphicsview.cpp" line="55"/>
 | 
			
		||||
        <location filename="../app/graphicsview.cpp" line="59"/>
 | 
			
		||||
        <source>Image data is invalid or currently unsupported</source>
 | 
			
		||||
        <translation>图像数据无效或暂未支持</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/graphicsview.cpp" line="269"/>
 | 
			
		||||
        <location filename="../graphicsview.cpp" line="262"/>
 | 
			
		||||
        <source>Image data is invalid</source>
 | 
			
		||||
        <translation>图片数据无效</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/graphicsview.cpp" line="276"/>
 | 
			
		||||
        <location filename="../graphicsview.cpp" line="269"/>
 | 
			
		||||
        <source>Not supported mimedata: %1</source>
 | 
			
		||||
        <translation>不受支持的 MimeData 格式:%1</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
@ -199,210 +193,87 @@
 | 
			
		||||
<context>
 | 
			
		||||
    <name>MainWindow</name>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/mainwindow.cpp" line="178"/>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="175"/>
 | 
			
		||||
        <source>File url list is empty</source>
 | 
			
		||||
        <translation>文件 URL 列表为空</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/mainwindow.cpp" line="417"/>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="408"/>
 | 
			
		||||
        <source>&Copy</source>
 | 
			
		||||
        <translation>复制(&C)</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/mainwindow.cpp" line="438"/>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="429"/>
 | 
			
		||||
        <source>Copy P&ixmap</source>
 | 
			
		||||
        <translation>复制位图(&I)</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/mainwindow.cpp" line="443"/>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="434"/>
 | 
			
		||||
        <source>Copy &File Path</source>
 | 
			
		||||
        <translation>复制文件路径(&F)</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/mainwindow.cpp" line="453"/>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="444"/>
 | 
			
		||||
        <source>&Paste Image</source>
 | 
			
		||||
        <translation>粘贴图像(&P)</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/mainwindow.cpp" line="459"/>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="450"/>
 | 
			
		||||
        <source>&Paste Image File</source>
 | 
			
		||||
        <translation>粘贴图像文件(&P)</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/mainwindow.cpp" line="492"/>
 | 
			
		||||
        <source>Properties</source>
 | 
			
		||||
        <translation>属性</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="30"/>
 | 
			
		||||
        <location filename="../app/mainwindow.cpp" line="464"/>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="30"/>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="455"/>
 | 
			
		||||
        <source>Stay on top</source>
 | 
			
		||||
        <translation>总在最前</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="34"/>
 | 
			
		||||
        <location filename="../app/mainwindow.cpp" line="471"/>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="34"/>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="462"/>
 | 
			
		||||
        <source>Protected mode</source>
 | 
			
		||||
        <translation>保护模式</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/mainwindow.cpp" line="478"/>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="469"/>
 | 
			
		||||
        <source>Configure...</source>
 | 
			
		||||
        <translation>设置...</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/mainwindow.cpp" line="485"/>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="476"/>
 | 
			
		||||
        <source>Help</source>
 | 
			
		||||
        <translation>帮助</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
</context>
 | 
			
		||||
<context>
 | 
			
		||||
    <name>MetadataDialog</name>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/metadatadialog.cpp" line="75"/>
 | 
			
		||||
        <source>Image Metadata</source>
 | 
			
		||||
        <translation>图像元信息</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
</context>
 | 
			
		||||
<context>
 | 
			
		||||
    <name>MetadataModel</name>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/metadatamodel.cpp" line="36"/>
 | 
			
		||||
        <source>Origin</source>
 | 
			
		||||
        <comment>Section name.</comment>
 | 
			
		||||
        <translation>来源</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/metadatamodel.cpp" line="38"/>
 | 
			
		||||
        <source>Image</source>
 | 
			
		||||
        <comment>Section name.</comment>
 | 
			
		||||
        <translation>图像</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/metadatamodel.cpp" line="44"/>
 | 
			
		||||
        <source>File</source>
 | 
			
		||||
        <comment>Section name.</comment>
 | 
			
		||||
        <translation>文件</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/metadatamodel.cpp" line="40"/>
 | 
			
		||||
        <source>Camera</source>
 | 
			
		||||
        <comment>Section name.</comment>
 | 
			
		||||
        <translation>照相机</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/metadatamodel.cpp" line="27"/>
 | 
			
		||||
        <source>%1 File</source>
 | 
			
		||||
        <translation>%1 文件</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/metadatamodel.cpp" line="35"/>
 | 
			
		||||
        <source>Description</source>
 | 
			
		||||
        <comment>Section name.</comment>
 | 
			
		||||
        <translation>说明</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/metadatamodel.cpp" line="41"/>
 | 
			
		||||
        <source>Advanced photo</source>
 | 
			
		||||
        <comment>Section name.</comment>
 | 
			
		||||
        <translation>高级照片</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/metadatamodel.cpp" line="42"/>
 | 
			
		||||
        <source>GPS</source>
 | 
			
		||||
        <comment>Section name.</comment>
 | 
			
		||||
        <translation>GPS</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/metadatamodel.cpp" line="47"/>
 | 
			
		||||
        <source>Dimensions</source>
 | 
			
		||||
        <translation>分辨率</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/metadatamodel.cpp" line="49"/>
 | 
			
		||||
        <source>Aspect Ratio</source>
 | 
			
		||||
        <translation>纵横比</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/metadatamodel.cpp" line="52"/>
 | 
			
		||||
        <source>Name</source>
 | 
			
		||||
        <translation>名称</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/metadatamodel.cpp" line="54"/>
 | 
			
		||||
        <source>Item type</source>
 | 
			
		||||
        <translation>项目类型</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/metadatamodel.cpp" line="56"/>
 | 
			
		||||
        <source>Folder path</source>
 | 
			
		||||
        <translation>文件夹路径</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/metadatamodel.cpp" line="58"/>
 | 
			
		||||
        <source>Size</source>
 | 
			
		||||
        <translation>大小</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/metadatamodel.cpp" line="60"/>
 | 
			
		||||
        <source>Date Created</source>
 | 
			
		||||
        <translation>创建日期</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/metadatamodel.cpp" line="62"/>
 | 
			
		||||
        <source>Date Modified</source>
 | 
			
		||||
        <translation>修改日期</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/metadatamodel.cpp" line="70"/>
 | 
			
		||||
        <source>%1 x %2</source>
 | 
			
		||||
        <translation>%1 x %2</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/metadatamodel.cpp" line="88"/>
 | 
			
		||||
        <source>%1 : %2</source>
 | 
			
		||||
        <translation>%1 : %2</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/metadatamodel.cpp" line="204"/>
 | 
			
		||||
        <source>Property</source>
 | 
			
		||||
        <translation>属性</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/metadatamodel.cpp" line="204"/>
 | 
			
		||||
        <source>Value</source>
 | 
			
		||||
        <translation>值</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
</context>
 | 
			
		||||
<context>
 | 
			
		||||
    <name>SettingsDialog</name>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/settingsdialog.cpp" line="15"/>
 | 
			
		||||
        <location filename="../settingsdialog.cpp" line="15"/>
 | 
			
		||||
        <source>Settings</source>
 | 
			
		||||
        <translation>设定</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/settingsdialog.cpp" line="20"/>
 | 
			
		||||
        <location filename="../settingsdialog.cpp" line="20"/>
 | 
			
		||||
        <source>Do nothing</source>
 | 
			
		||||
        <translation>什么也不做</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/settingsdialog.cpp" line="21"/>
 | 
			
		||||
        <location filename="../settingsdialog.cpp" line="21"/>
 | 
			
		||||
        <source>Close the window</source>
 | 
			
		||||
        <translation>关闭窗口</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/settingsdialog.cpp" line="22"/>
 | 
			
		||||
        <location filename="../settingsdialog.cpp" line="22"/>
 | 
			
		||||
        <source>Toggle maximize</source>
 | 
			
		||||
        <translation>最大化窗口</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/settingsdialog.cpp" line="30"/>
 | 
			
		||||
        <location filename="../settingsdialog.cpp" line="30"/>
 | 
			
		||||
        <source>Stay on top when start-up</source>
 | 
			
		||||
        <translation>启动时保持窗口总在最前</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/settingsdialog.cpp" line="31"/>
 | 
			
		||||
        <location filename="../settingsdialog.cpp" line="31"/>
 | 
			
		||||
        <source>Double-click behavior</source>
 | 
			
		||||
        <translation>双击时的行为</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
@ -410,12 +281,12 @@
 | 
			
		||||
<context>
 | 
			
		||||
    <name>main</name>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/main.cpp" line="27"/>
 | 
			
		||||
        <location filename="../main.cpp" line="27"/>
 | 
			
		||||
        <source>Pineapple Pictures</source>
 | 
			
		||||
        <translation>菠萝看图</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/main.cpp" line="31"/>
 | 
			
		||||
        <location filename="../main.cpp" line="31"/>
 | 
			
		||||
        <source>File list.</source>
 | 
			
		||||
        <translation>文件列表。</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
@ -8,8 +8,8 @@
 | 
			
		||||
#include "graphicsscene.h"
 | 
			
		||||
#include "settingsdialog.h"
 | 
			
		||||
#include "aboutdialog.h"
 | 
			
		||||
#include "metadatamodel.h"
 | 
			
		||||
#include "metadatadialog.h"
 | 
			
		||||
#include "metadatamodel.h"
 | 
			
		||||
 | 
			
		||||
#include <QMouseEvent>
 | 
			
		||||
#include <QMovie>
 | 
			
		||||
@ -24,7 +24,6 @@
 | 
			
		||||
#include <QCollator>
 | 
			
		||||
#include <QClipboard>
 | 
			
		||||
#include <QMimeData>
 | 
			
		||||
#include <QWindow>
 | 
			
		||||
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
#include <windows.h>
 | 
			
		||||
@ -342,13 +341,7 @@ void MainWindow::mousePressEvent(QMouseEvent *event)
 | 
			
		||||
void MainWindow::mouseMoveEvent(QMouseEvent *event)
 | 
			
		||||
{
 | 
			
		||||
    if (event->buttons() & Qt::LeftButton && m_clickedOnWindow && !isMaximized()) {
 | 
			
		||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
 | 
			
		||||
        if (!window()->windowHandle()->startSystemMove()) {
 | 
			
		||||
            move(event->globalPos() - m_oldMousePos);
 | 
			
		||||
        }
 | 
			
		||||
#else
 | 
			
		||||
        move(event->globalPos() - m_oldMousePos);
 | 
			
		||||
#endif // QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
 | 
			
		||||
        event->accept();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										81
									
								
								metadata.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								metadata.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,81 @@
 | 
			
		||||
#include "metadata.h"
 | 
			
		||||
 | 
			
		||||
Section::Section()
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Section::~Section()
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Warning! this method won't copy anything from the given argument!
 | 
			
		||||
// we actually doesn't care about this, but since QList and QMap are not movable
 | 
			
		||||
// so there won't be a (not ill-formed) default ctor to use and we won't get a
 | 
			
		||||
// proper copy ctor, thus the operator= will be deleted.
 | 
			
		||||
// When accessing QMap value if not exist, we just use this to create a new Section.
 | 
			
		||||
Section & Section::operator=(const Section &)
 | 
			
		||||
{
 | 
			
		||||
    return *this;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int Section::count() const
 | 
			
		||||
{
 | 
			
		||||
    return m_propertiesValueMap.count();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Section::setSectionName(const QString &displayName)
 | 
			
		||||
{
 | 
			
		||||
    m_displayName = displayName;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Section::setValue(PropertyType type, const QString &value)
 | 
			
		||||
{
 | 
			
		||||
    if (!m_propertiesValueMap.contains(type)) {
 | 
			
		||||
        m_propertyIndexes.append(type);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    m_propertiesValueMap[type] = value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString Section::valueAt(int index) const
 | 
			
		||||
{
 | 
			
		||||
    Q_ASSERT(index >= 0 && index < m_propertyIndexes.count());
 | 
			
		||||
 | 
			
		||||
    return m_propertiesValueMap[m_propertyIndexes[index]];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString Section::value(Section::PropertyType type) const
 | 
			
		||||
{
 | 
			
		||||
    return m_propertiesValueMap.value(type, tr("Unknown"));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QString Section::propertyName(PropertyType type) const
 | 
			
		||||
{
 | 
			
		||||
    return m_propertiesOverrideDisplayNameMap.value(
 | 
			
		||||
                type,
 | 
			
		||||
                m_builtinPropDisplayNameMap.value(type, tr("Unknown"))
 | 
			
		||||
           );
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Metadata::Metadata()
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Metadata::~Metadata()
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Metadata::setSectionName(SectionType type, const QString &displayName)
 | 
			
		||||
{
 | 
			
		||||
    m_sections[type].setSectionName(displayName);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Metadata::setPropertyValue(Metadata::SectionType type, Section::PropertyType propType, QString value)
 | 
			
		||||
{
 | 
			
		||||
    m_sections[type].setValue(propType, value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										66
									
								
								metadata.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								metadata.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,66 @@
 | 
			
		||||
#ifndef METADATA_H
 | 
			
		||||
#define METADATA_H
 | 
			
		||||
 | 
			
		||||
#include <QMap>
 | 
			
		||||
#include <QPair>
 | 
			
		||||
#include <QCoreApplication>
 | 
			
		||||
 | 
			
		||||
class Section
 | 
			
		||||
{
 | 
			
		||||
    Q_DECLARE_TR_FUNCTIONS(Section)
 | 
			
		||||
public:
 | 
			
		||||
    Section();
 | 
			
		||||
    ~Section();
 | 
			
		||||
    Section & operator=(const Section& other);
 | 
			
		||||
 | 
			
		||||
    // TODO: maybe use QString instead of a enum? different section won't share a same
 | 
			
		||||
    //       enum value in any way...
 | 
			
		||||
    enum PropertyType : int {
 | 
			
		||||
        NameProp,
 | 
			
		||||
        FileSizeProp,
 | 
			
		||||
        LastModifiedProp,
 | 
			
		||||
        ImageSizeProp,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    int count() const;
 | 
			
		||||
    void setSectionName(const QString & displayName);
 | 
			
		||||
    void setValue(PropertyType type, const QString & value);
 | 
			
		||||
    QString value(PropertyType type) const;
 | 
			
		||||
    QString valueAt(int index) const;
 | 
			
		||||
    QString propertyName(PropertyType type) const;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    QString m_displayName;
 | 
			
		||||
    QList<PropertyType> m_propertyIndexes;
 | 
			
		||||
    QMap<PropertyType, QString> m_propertiesValueMap;
 | 
			
		||||
    QMap<PropertyType, QString> m_propertiesOverrideDisplayNameMap;
 | 
			
		||||
 | 
			
		||||
    const QMap<PropertyType, QString> m_builtinPropDisplayNameMap {
 | 
			
		||||
        {NameProp, tr("Name")},
 | 
			
		||||
        {FileSizeProp, tr("File Size")},
 | 
			
		||||
        {LastModifiedProp, tr("Last Modified")},
 | 
			
		||||
        {ImageSizeProp, tr("Image Size")},
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class Metadata
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    enum SectionType : int {
 | 
			
		||||
        GeneralSection,
 | 
			
		||||
        ExifSection,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    Metadata();
 | 
			
		||||
    ~Metadata();
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    QList<SectionType> m_sectionIndexes;
 | 
			
		||||
    QMap<SectionType, Section> m_sections;
 | 
			
		||||
 | 
			
		||||
    void setSectionName(SectionType type, const QString & displayName);
 | 
			
		||||
    void setPropertyValue(SectionType type, Section::PropertyType propType, QString value);
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // METADATA_H
 | 
			
		||||
							
								
								
									
										41
									
								
								metadatadialog.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								metadatadialog.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,41 @@
 | 
			
		||||
#include "metadatadialog.h"
 | 
			
		||||
 | 
			
		||||
#include <QDialogButtonBox>
 | 
			
		||||
#include <QTreeView>
 | 
			
		||||
#include <QVBoxLayout>
 | 
			
		||||
 | 
			
		||||
#include "metadatamodel.h"
 | 
			
		||||
 | 
			
		||||
MetadataDialog::MetadataDialog(QWidget *parent)
 | 
			
		||||
    : QDialog(parent)
 | 
			
		||||
    , m_treeView(new QTreeView(this))
 | 
			
		||||
{
 | 
			
		||||
//    m_treeView->setRootIsDecorated(false);
 | 
			
		||||
    m_treeView->setIndentation(0);
 | 
			
		||||
 | 
			
		||||
    setWindowTitle(tr("Image Metadata"));
 | 
			
		||||
 | 
			
		||||
    QDialogButtonBox * buttonBox = new QDialogButtonBox(QDialogButtonBox::Close);
 | 
			
		||||
 | 
			
		||||
    setLayout(new QVBoxLayout);
 | 
			
		||||
    layout()->addWidget(m_treeView);
 | 
			
		||||
    layout()->addWidget(buttonBox);
 | 
			
		||||
 | 
			
		||||
    connect(buttonBox, &QDialogButtonBox::close, this, &QDialog::close);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
MetadataDialog::~MetadataDialog()
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void MetadataDialog::setMetadataModel(MetadataModel * model)
 | 
			
		||||
{
 | 
			
		||||
    m_treeView->setModel(model);
 | 
			
		||||
    m_treeView->expandAll();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QSize MetadataDialog::sizeHint() const
 | 
			
		||||
{
 | 
			
		||||
    return QSize(520, 350);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										267
									
								
								metadatamodel.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										267
									
								
								metadatamodel.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,267 @@
 | 
			
		||||
#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());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										36
									
								
								metadatamodel.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								metadatamodel.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,36 @@
 | 
			
		||||
#ifndef METADATAMODEL_H
 | 
			
		||||
#define METADATAMODEL_H
 | 
			
		||||
 | 
			
		||||
#include <QVector>
 | 
			
		||||
#include <QAbstractItemModel>
 | 
			
		||||
 | 
			
		||||
enum Sections : int;
 | 
			
		||||
class MetadataSection;
 | 
			
		||||
class MetadataModel : public QAbstractItemModel
 | 
			
		||||
{
 | 
			
		||||
    Q_OBJECT
 | 
			
		||||
public:
 | 
			
		||||
    MetadataModel();
 | 
			
		||||
    ~MetadataModel() override;
 | 
			
		||||
 | 
			
		||||
    void setFile(const QString & url);
 | 
			
		||||
    void setImageSize(const QSize & size);
 | 
			
		||||
 | 
			
		||||
    QModelIndex index(int row, int col, const QModelIndex& parent = QModelIndex()) const override;
 | 
			
		||||
    QModelIndex parent(const QModelIndex & index) 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;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    QList<MetadataSection *> m_sections; // associated pointers free at destructor function.
 | 
			
		||||
    QMap<Sections, MetadataSection *> m_sectionEnumIndexMap; // pointer shared with m_sections
 | 
			
		||||
 | 
			
		||||
    void initGeneralSection();
 | 
			
		||||
    bool sectionRegister(Sections sectionType, MetadataSection * section);
 | 
			
		||||
    void setSectionEntryValue(Sections sectionType, const QString & key, const QString & value);
 | 
			
		||||
    MetadataSection * section(Sections sectionType);
 | 
			
		||||
    QVariant displayData(const QModelIndex & index) const;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // METADATAMODEL_H
 | 
			
		||||
@ -1,3 +1,9 @@
 | 
			
		||||
#-------------------------------------------------
 | 
			
		||||
#
 | 
			
		||||
# Project created by QtCreator 2019-09-26T23:36:07
 | 
			
		||||
#
 | 
			
		||||
#-------------------------------------------------
 | 
			
		||||
 | 
			
		||||
QT       += core widgets gui svg
 | 
			
		||||
 | 
			
		||||
TARGET = ppic
 | 
			
		||||
@ -17,37 +23,39 @@ DEFINES += QT_DEPRECATED_WARNINGS
 | 
			
		||||
CONFIG += c++11 lrelease embed_translations
 | 
			
		||||
 | 
			
		||||
SOURCES += \
 | 
			
		||||
    app/aboutdialog.cpp \
 | 
			
		||||
    app/main.cpp \
 | 
			
		||||
    app/mainwindow.cpp \
 | 
			
		||||
    app/graphicsview.cpp \
 | 
			
		||||
    app/bottombuttongroup.cpp \
 | 
			
		||||
    app/graphicsscene.cpp \
 | 
			
		||||
    app/navigatorview.cpp \
 | 
			
		||||
    app/opacityhelper.cpp \
 | 
			
		||||
    app/toolbutton.cpp \
 | 
			
		||||
    app/settings.cpp \
 | 
			
		||||
    app/settingsdialog.cpp \
 | 
			
		||||
    app/metadatamodel.cpp \
 | 
			
		||||
    app/metadatadialog.cpp
 | 
			
		||||
    aboutdialog.cpp \
 | 
			
		||||
        main.cpp \
 | 
			
		||||
        mainwindow.cpp \
 | 
			
		||||
    graphicsview.cpp \
 | 
			
		||||
    bottombuttongroup.cpp \
 | 
			
		||||
    graphicsscene.cpp \
 | 
			
		||||
    metadata.cpp \
 | 
			
		||||
    metadatadialog.cpp \
 | 
			
		||||
    metadatamodel.cpp \
 | 
			
		||||
    navigatorview.cpp \
 | 
			
		||||
    opacityhelper.cpp \
 | 
			
		||||
    toolbutton.cpp \
 | 
			
		||||
    settings.cpp \
 | 
			
		||||
    settingsdialog.cpp
 | 
			
		||||
 | 
			
		||||
HEADERS += \
 | 
			
		||||
    app/aboutdialog.h \
 | 
			
		||||
    app/mainwindow.h \
 | 
			
		||||
    app/graphicsview.h \
 | 
			
		||||
    app/bottombuttongroup.h \
 | 
			
		||||
    app/graphicsscene.h \
 | 
			
		||||
    app/navigatorview.h \
 | 
			
		||||
    app/opacityhelper.h \
 | 
			
		||||
    app/toolbutton.h \
 | 
			
		||||
    app/settings.h \
 | 
			
		||||
    app/settingsdialog.h \
 | 
			
		||||
    app/metadatamodel.h \
 | 
			
		||||
    app/metadatadialog.h
 | 
			
		||||
    aboutdialog.h \
 | 
			
		||||
        mainwindow.h \
 | 
			
		||||
    graphicsview.h \
 | 
			
		||||
    bottombuttongroup.h \
 | 
			
		||||
    graphicsscene.h \
 | 
			
		||||
    metadata.h \
 | 
			
		||||
    metadatadialog.h \
 | 
			
		||||
    metadatamodel.h \
 | 
			
		||||
    navigatorview.h \
 | 
			
		||||
    opacityhelper.h \
 | 
			
		||||
    toolbutton.h \
 | 
			
		||||
    settings.h \
 | 
			
		||||
    settingsdialog.h
 | 
			
		||||
 | 
			
		||||
TRANSLATIONS = \
 | 
			
		||||
    translations/PineapplePictures.ts \
 | 
			
		||||
    translations/PineapplePictures_zh_CN.ts
 | 
			
		||||
    languages/PineapplePictures.ts \
 | 
			
		||||
    languages/PineapplePictures_zh_CN.ts
 | 
			
		||||
 | 
			
		||||
# Default rules for deployment.
 | 
			
		||||
qnx: target.path = /tmp/$${TARGET}/bin
 | 
			
		||||
 | 
			
		||||
@ -1,423 +0,0 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<!DOCTYPE TS>
 | 
			
		||||
<TS version="2.1">
 | 
			
		||||
<context>
 | 
			
		||||
    <name>AboutDialog</name>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="22"/>
 | 
			
		||||
        <source>About</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="25"/>
 | 
			
		||||
        <source>Launch application with image file path as argument to load the file.</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="26"/>
 | 
			
		||||
        <source>Drag and drop image file onto the window is also supported.</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="27"/>
 | 
			
		||||
        <source>Context menu option explanation:</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="31"/>
 | 
			
		||||
        <source>Make window stay on top of all other windows.</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="35"/>
 | 
			
		||||
        <source>Avoid close window accidentally. (eg. by double clicking the window)</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="44"/>
 | 
			
		||||
        <source>Version: %1</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="47"/>
 | 
			
		||||
        <source>Copyright (c) 2020 %1</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="49"/>
 | 
			
		||||
        <source>Logo designed by %1</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="51"/>
 | 
			
		||||
        <source>Built with Qt %1 (%2)</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="52"/>
 | 
			
		||||
        <source>Source code</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="58"/>
 | 
			
		||||
        <source>Contributors</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="60"/>
 | 
			
		||||
        <source>List of contributors on GitHub</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="61"/>
 | 
			
		||||
        <source>Thanks to all people who contributed to this project.</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="65"/>
 | 
			
		||||
        <source>Translators</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="66"/>
 | 
			
		||||
        <source>I would like to thank the following people who volunteered to translate this application.</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="131"/>
 | 
			
		||||
        <source>&Special Thanks</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="133"/>
 | 
			
		||||
        <source>&Third-party Libraries</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="72"/>
 | 
			
		||||
        <source>Your Rights</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="74"/>
 | 
			
		||||
        <source>%1 is released under the MIT License.</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="75"/>
 | 
			
		||||
        <source>This license grants people a number of freedoms:</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="76"/>
 | 
			
		||||
        <source>You are free to use %1, for any purpose</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="77"/>
 | 
			
		||||
        <source>You are free to distribute %1</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="78"/>
 | 
			
		||||
        <source>You can study how %1 works and change it</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="79"/>
 | 
			
		||||
        <source>You can distribute changed versions of %1</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="81"/>
 | 
			
		||||
        <source>The MIT license guarantees you this freedom. Nobody is ever permitted to take it away.</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="109"/>
 | 
			
		||||
        <source>Third-party Libraries used by %1</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="110"/>
 | 
			
		||||
        <source>%1 is built on the following free software libraries:</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="129"/>
 | 
			
		||||
        <source>&Help</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="130"/>
 | 
			
		||||
        <source>&About</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="132"/>
 | 
			
		||||
        <source>&License</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
</context>
 | 
			
		||||
<context>
 | 
			
		||||
    <name>GraphicsScene</name>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/graphicsscene.cpp" line="16"/>
 | 
			
		||||
        <source>Drag image here</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
</context>
 | 
			
		||||
<context>
 | 
			
		||||
    <name>GraphicsView</name>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/graphicsview.cpp" line="261"/>
 | 
			
		||||
        <source>File url list is empty</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/graphicsview.cpp" line="53"/>
 | 
			
		||||
        <source>File is not a valid image</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/graphicsview.cpp" line="55"/>
 | 
			
		||||
        <location filename="../app/graphicsview.cpp" line="59"/>
 | 
			
		||||
        <source>Image data is invalid or currently unsupported</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/graphicsview.cpp" line="269"/>
 | 
			
		||||
        <source>Image data is invalid</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/graphicsview.cpp" line="276"/>
 | 
			
		||||
        <source>Not supported mimedata: %1</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
</context>
 | 
			
		||||
<context>
 | 
			
		||||
    <name>MainWindow</name>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/mainwindow.cpp" line="178"/>
 | 
			
		||||
        <source>File url list is empty</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/mainwindow.cpp" line="417"/>
 | 
			
		||||
        <source>&Copy</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/mainwindow.cpp" line="438"/>
 | 
			
		||||
        <source>Copy P&ixmap</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/mainwindow.cpp" line="443"/>
 | 
			
		||||
        <source>Copy &File Path</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/mainwindow.cpp" line="453"/>
 | 
			
		||||
        <source>&Paste Image</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/mainwindow.cpp" line="459"/>
 | 
			
		||||
        <source>&Paste Image File</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/mainwindow.cpp" line="492"/>
 | 
			
		||||
        <source>Properties</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="30"/>
 | 
			
		||||
        <location filename="../app/mainwindow.cpp" line="464"/>
 | 
			
		||||
        <source>Stay on top</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/aboutdialog.cpp" line="34"/>
 | 
			
		||||
        <location filename="../app/mainwindow.cpp" line="471"/>
 | 
			
		||||
        <source>Protected mode</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/mainwindow.cpp" line="478"/>
 | 
			
		||||
        <source>Configure...</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/mainwindow.cpp" line="485"/>
 | 
			
		||||
        <source>Help</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
</context>
 | 
			
		||||
<context>
 | 
			
		||||
    <name>MetadataDialog</name>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/metadatadialog.cpp" line="75"/>
 | 
			
		||||
        <source>Image Metadata</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
</context>
 | 
			
		||||
<context>
 | 
			
		||||
    <name>MetadataModel</name>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/metadatamodel.cpp" line="36"/>
 | 
			
		||||
        <source>Origin</source>
 | 
			
		||||
        <comment>Section name.</comment>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/metadatamodel.cpp" line="38"/>
 | 
			
		||||
        <source>Image</source>
 | 
			
		||||
        <comment>Section name.</comment>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/metadatamodel.cpp" line="44"/>
 | 
			
		||||
        <source>File</source>
 | 
			
		||||
        <comment>Section name.</comment>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/metadatamodel.cpp" line="40"/>
 | 
			
		||||
        <source>Camera</source>
 | 
			
		||||
        <comment>Section name.</comment>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/metadatamodel.cpp" line="27"/>
 | 
			
		||||
        <source>%1 File</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/metadatamodel.cpp" line="35"/>
 | 
			
		||||
        <source>Description</source>
 | 
			
		||||
        <comment>Section name.</comment>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/metadatamodel.cpp" line="41"/>
 | 
			
		||||
        <source>Advanced photo</source>
 | 
			
		||||
        <comment>Section name.</comment>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/metadatamodel.cpp" line="42"/>
 | 
			
		||||
        <source>GPS</source>
 | 
			
		||||
        <comment>Section name.</comment>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/metadatamodel.cpp" line="47"/>
 | 
			
		||||
        <source>Dimensions</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/metadatamodel.cpp" line="49"/>
 | 
			
		||||
        <source>Aspect Ratio</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/metadatamodel.cpp" line="52"/>
 | 
			
		||||
        <source>Name</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/metadatamodel.cpp" line="54"/>
 | 
			
		||||
        <source>Item type</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/metadatamodel.cpp" line="56"/>
 | 
			
		||||
        <source>Folder path</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/metadatamodel.cpp" line="58"/>
 | 
			
		||||
        <source>Size</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/metadatamodel.cpp" line="60"/>
 | 
			
		||||
        <source>Date Created</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/metadatamodel.cpp" line="62"/>
 | 
			
		||||
        <source>Date Modified</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/metadatamodel.cpp" line="70"/>
 | 
			
		||||
        <source>%1 x %2</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/metadatamodel.cpp" line="88"/>
 | 
			
		||||
        <source>%1 : %2</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/metadatamodel.cpp" line="204"/>
 | 
			
		||||
        <source>Property</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/metadatamodel.cpp" line="204"/>
 | 
			
		||||
        <source>Value</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
</context>
 | 
			
		||||
<context>
 | 
			
		||||
    <name>SettingsDialog</name>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/settingsdialog.cpp" line="15"/>
 | 
			
		||||
        <source>Settings</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/settingsdialog.cpp" line="20"/>
 | 
			
		||||
        <source>Do nothing</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/settingsdialog.cpp" line="21"/>
 | 
			
		||||
        <source>Close the window</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/settingsdialog.cpp" line="22"/>
 | 
			
		||||
        <source>Toggle maximize</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/settingsdialog.cpp" line="30"/>
 | 
			
		||||
        <source>Stay on top when start-up</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/settingsdialog.cpp" line="31"/>
 | 
			
		||||
        <source>Double-click behavior</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
</context>
 | 
			
		||||
<context>
 | 
			
		||||
    <name>main</name>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/main.cpp" line="27"/>
 | 
			
		||||
        <source>Pineapple Pictures</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../app/main.cpp" line="31"/>
 | 
			
		||||
        <source>File list.</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
</context>
 | 
			
		||||
</TS>
 | 
			
		||||
		Reference in New Issue
	
	Block a user