Compare commits
	
		
			15 Commits
		
	
	
		
			0.3.1
			...
			wip-proper
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 83246f04ae | |||
| 54c54e2adf | |||
| 6da9c16c4f | |||
| 5ace4e219c | |||
| c78eb1a272 | |||
| 7c39668eb6 | |||
| 4c3e370f70 | |||
| f7aaa76985 | |||
| 5ff49f4885 | |||
| 36c7eb1891 | |||
| 58210691ed | |||
| 0eb9886394 | |||
| 16ccec0d12 | |||
| e2fb1813f1 | |||
| 7245a4e212 | 
@ -22,6 +22,7 @@ set (PPIC_CPP_FILES
 | 
			
		||||
    toolbutton.cpp
 | 
			
		||||
    settings.cpp
 | 
			
		||||
    settingsdialog.cpp
 | 
			
		||||
    aboutdialog.cpp
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
set (PPIC_HEADER_FILES
 | 
			
		||||
@ -34,6 +35,7 @@ set (PPIC_HEADER_FILES
 | 
			
		||||
    toolbutton.h
 | 
			
		||||
    settings.h
 | 
			
		||||
    settingsdialog.h
 | 
			
		||||
    aboutdialog.h
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
set (PPIC_QRC_FILES
 | 
			
		||||
@ -114,6 +116,9 @@ if (EXISTS "${CMAKE_SOURCE_DIR}/.git")
 | 
			
		||||
        )
 | 
			
		||||
        string (REGEX REPLACE "\n" "" _git_describe_long "${_git_describe_long}")
 | 
			
		||||
        ppic_set_version_via_describe(${_git_describe_long})
 | 
			
		||||
        target_compile_definitions(${EXE_NAME} PRIVATE
 | 
			
		||||
            GIT_DESCRIBE_VERSION_STRING="${_git_describe_long}"
 | 
			
		||||
        )
 | 
			
		||||
    endif ()
 | 
			
		||||
endif ()
 | 
			
		||||
 | 
			
		||||
@ -149,9 +154,15 @@ elseif (UNIX)
 | 
			
		||||
 | 
			
		||||
    # install shortcut
 | 
			
		||||
    install (
 | 
			
		||||
        FILES pineapple-pictures.desktop
 | 
			
		||||
        FILES dist/net.blumia.pineapple-pictures.desktop
 | 
			
		||||
        DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/applications"
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    # install app metadata file for appstream (and some other stuff using this metadata like snapcraft)
 | 
			
		||||
    install (
 | 
			
		||||
        FILES dist/appstream/net.blumia.pineapple-pictures.appdata.xml
 | 
			
		||||
        DESTINATION "${CMAKE_INSTALL_DATAROOTDIR}/metainfo"
 | 
			
		||||
    )
 | 
			
		||||
endif()
 | 
			
		||||
 | 
			
		||||
set (INSTALL_TARGETS_DEFAULT_ARGS
 | 
			
		||||
@ -184,7 +195,7 @@ set (CPACK_GENERATOR "TBZ2")
 | 
			
		||||
set (CPACK_PACKAGE_NAME "pineapple-pictures")
 | 
			
		||||
set (CPACK_PACKAGE_DESCRIPTION_SUMMARY "Yet another image viewer")
 | 
			
		||||
set (CPACK_PACKAGE_VENDOR "Gary Wang")
 | 
			
		||||
set (CPACK_PACKAGE_CONTACT "https://github.com/BLumia/PineapplePictures/issues/")
 | 
			
		||||
set (CPACK_PACKAGE_CONTACT "https://github.com/BLumia/pineapple-pictures/issues/")
 | 
			
		||||
if (WIN32)
 | 
			
		||||
    # ...
 | 
			
		||||
elseif (APPLE)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										2
									
								
								LICENSE
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								LICENSE
									
									
									
									
									
								
							@ -1,6 +1,6 @@
 | 
			
		||||
MIT License
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2019 BLumia
 | 
			
		||||
Copyright (c) 2020 BLumia
 | 
			
		||||
 | 
			
		||||
Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										67
									
								
								README.zh_CN.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								README.zh_CN.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,67 @@
 | 
			
		||||
简单轻量的跨平台看图工具。
 | 
			
		||||
 | 
			
		||||
|CI|构建状态|
 | 
			
		||||
|---|---|
 | 
			
		||||
|Windows Build|[](https://ci.appveyor.com/project/BLumia/pineapplepictures/branch/master)|
 | 
			
		||||
|macOS Build||
 | 
			
		||||
|Ubuntu 20.04 Build||
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
## 立即获取!
 | 
			
		||||
 | 
			
		||||
 - [GitHub Release 页面](https://github.com/BLumia/pineapple-pictures/releases) | [gitee 发布页面](https://gitee.com/blumia/pineapple-pictures/releases)
 | 
			
		||||
 - Archlinux AUR: [pineapple-pictures-git](https://aur.archlinux.org/packages/pineapple-pictures-git/)
 | 
			
		||||
 | 
			
		||||
## 手动构建步骤:
 | 
			
		||||
 | 
			
		||||
当前状态,我们需要先确保如下依赖可用:
 | 
			
		||||
 | 
			
		||||
 - `cmake`: 我们所使用的构建系统
 | 
			
		||||
 - 包含 `qt5-svg` 与 `qt5-tools` 组件的 `qt5`: 此应用基于 Qt
 | 
			
		||||
 | 
			
		||||
然后我们就可以使用任何常规的 c++ 编译器如 g++ 或 msvc 来进行构建了
 | 
			
		||||
 | 
			
		||||
构建过程就是常规的 CMake 应用构建过程:
 | 
			
		||||
 | 
			
		||||
``` bash
 | 
			
		||||
$ mkdir build && cd build
 | 
			
		||||
$ cmake ..
 | 
			
		||||
$ cmake --build . # 如果你使用 Makefile 作为 CMake 生成器,也可以直接简单的使用 `make`
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
完毕后,一个名为 `ppic` 的可执行程序即会被生成以供使用。您也可以选择通过使用 CMake 生成的 `install` 目标继续将其安装到您的设备上(假设您使用 Makefile,即可执行 `make install` 来进行安装)。构建步骤完毕后,您也可以使用 `cpack` 来对应用程序进行打包。
 | 
			
		||||
 | 
			
		||||
此应用的图片格式支持依赖于 Qt 的 imageformats 插件,直接从您所用的发行版获取对应的图像格式插件即可。对于 Windows 用户,您可能需要手动构建和使用图像格式插件。下方给出了进一步的说明。
 | 
			
		||||
 | 
			
		||||
### Linux
 | 
			
		||||
 | 
			
		||||
常规的构建步骤即可完成构建,不需要额外的处理步骤 ;)
 | 
			
		||||
 | 
			
		||||
对于 Archlinux 发行版的用户,这里还有一个 [PKGBUILD](https://aur.archlinux.org/cgit/aur.git/tree/PKGBUILD?h=pineapple-pictures-git) 可供使用和参考。
 | 
			
		||||
 | 
			
		||||
对于在基于 debian 的发行版中进行打包的需求, `CMakeLists.txt` 已经提供了一些基本的 cpack 配置以便生成一个有效的 `.deb` 软件包。在构建步骤完毕后,使用 `cpack -G DEB` 即可生成 DEB 软件包。您也可以参考 `.github/workflows/ubuntu.yml` 来查看当前正在使用的 CI 配置是如何进行打包的。
 | 
			
		||||
 | 
			
		||||
目前,`DEB` 是当前唯一受到直接支持的 cpack 生成目标。若希望为此项目添加其它的 cpack 目标支持,欢迎发起合并请求。
 | 
			
		||||
 | 
			
		||||
### Windows
 | 
			
		||||
 | 
			
		||||
上述的构建步骤在 Windows 中也适用,但由于 Windows 中不具备类如大多 Linux 发行版中所提供的方便的软件包管理机制,故如果您需要任何 Qt 官方支持之外的图像格式例如 psd,xcf,kra 等格式的支持,你就可能需要自行获取并构建对应的 imageformats 插件,并在您最终生成的可执行文件中一并提供这些插件。若您不需要这些额外的图像格式支持,这个步骤也可以直接跳过。
 | 
			
		||||
 | 
			
		||||
我们所提供的预编译好的 Windows 程序包含了 kimageformats 插件来提供额外(kra, xcf, psd 等)格式的支持。您可以参考 `appveyor.yml` 来查看我们是如何构建并打包 Windows 可执行程序的。
 | 
			
		||||
 | 
			
		||||
[KDE Craft](https://community.kde.org/Craft) 环境也可以被用来构建此应用程序。我也创建了一个蓝图来进行此项目的构建和打包。但由于暂时并未配置 CI 部署此环境来进行 KDE Craft 环境下的构建,故对应的蓝图仓库也尚未公开提供,或许后续会开放出来。
 | 
			
		||||
 | 
			
		||||
### macOS
 | 
			
		||||
 | 
			
		||||
由于我没有 mac 设备,故 macOS 暂时不受任何支持。不过我们目前有一个 GitHub Action 来执行 macOS 环境下的构建(见 `.github/workflows/macos.yml`)所以至少 macOS 下是可以顺利进行构建的。如果您想完善对 macOS 的支持,也欢迎您创建合并请求 ;P
 | 
			
		||||
 | 
			
		||||
## 帮助翻译!
 | 
			
		||||
 | 
			
		||||
[在 Transifex 上帮助此项目翻译到更多语言!](https://www.transifex.com/blumia/pineapple-pictures/)
 | 
			
		||||
 | 
			
		||||
若 Transifex 上没有您所希望进行翻译的语言,请通过 Issue 的形式告诉我。
 | 
			
		||||
 | 
			
		||||
## 许可协议
 | 
			
		||||
 | 
			
		||||
此项目使用 MIT 协议进行发布。
 | 
			
		||||
							
								
								
									
										157
									
								
								aboutdialog.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										157
									
								
								aboutdialog.cpp
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,157 @@
 | 
			
		||||
#include "aboutdialog.h"
 | 
			
		||||
 | 
			
		||||
#include <QAbstractButton>
 | 
			
		||||
#include <QDialogButtonBox>
 | 
			
		||||
#include <QTextBrowser>
 | 
			
		||||
#include <QTabWidget>
 | 
			
		||||
#include <QVBoxLayout>
 | 
			
		||||
#include <QApplication>
 | 
			
		||||
#include <QLabel>
 | 
			
		||||
#include <QPushButton>
 | 
			
		||||
 | 
			
		||||
AboutDialog::AboutDialog(QWidget *parent)
 | 
			
		||||
    : QDialog(parent)
 | 
			
		||||
    , m_tabWidget(new QTabWidget)
 | 
			
		||||
    , m_buttonBox(new QDialogButtonBox)
 | 
			
		||||
    , m_helpTextEdit(new QTextBrowser)
 | 
			
		||||
    , m_aboutTextEdit(new QTextBrowser)
 | 
			
		||||
    , m_specialThanksTextEdit(new QTextBrowser)
 | 
			
		||||
    , m_licenseTextEdit(new QTextBrowser)
 | 
			
		||||
    , m_3rdPartyLibsTextEdit(new QTextBrowser)
 | 
			
		||||
{
 | 
			
		||||
    this->setWindowTitle(tr("About"));
 | 
			
		||||
 | 
			
		||||
    QStringList helpStr {
 | 
			
		||||
        QStringLiteral("<p>%1</p>").arg(tr("Launch application with image file path as argument to load the file.")),
 | 
			
		||||
        QStringLiteral("<p>%1</p>").arg(tr("Drag and drop image file onto the window is also supported.")),
 | 
			
		||||
        QStringLiteral("<p>%1</p>").arg(tr("Context menu option explanation:")),
 | 
			
		||||
        QStringLiteral("<ul>"),
 | 
			
		||||
        QStringLiteral("<li><b>%1</b>:<br/>%2</li>").arg(
 | 
			
		||||
            QCoreApplication::translate("MainWindow", "Stay on top"),
 | 
			
		||||
            this->tr("Make window stay on top of all other windows.")
 | 
			
		||||
        ),
 | 
			
		||||
        QStringLiteral("<li><b>%1</b>:<br/>%2</li>").arg(
 | 
			
		||||
            QCoreApplication::translate("MainWindow", "Protected mode"),
 | 
			
		||||
            this->tr("Avoid close window accidentally. (eg. by double clicking the window)")
 | 
			
		||||
        ),
 | 
			
		||||
        QStringLiteral("</ul>")
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    QStringList aboutStr {
 | 
			
		||||
        QStringLiteral("<center><img width='128' height='128' src=':/icons/app-icon.svg'/><br/>"),
 | 
			
		||||
        qApp->applicationDisplayName(),
 | 
			
		||||
#ifdef GIT_DESCRIBE_VERSION_STRING
 | 
			
		||||
        (QStringLiteral("<br/>") + tr("Version: %1").arg(GIT_DESCRIBE_VERSION_STRING)),
 | 
			
		||||
#endif // GIT_DESCRIBE_VERSION_STRING
 | 
			
		||||
        QStringLiteral("<hr/>"),
 | 
			
		||||
        tr("Copyright (c) 2020 %1").arg(QStringLiteral("<a href='https://github.com/BLumia'>@BLumia</a>")),
 | 
			
		||||
        QStringLiteral("<br/>"),
 | 
			
		||||
        tr("Logo designed by %1").arg(QStringLiteral("<a href='https://github.com/Lovelyblack'>@Lovelyblack</a>")),
 | 
			
		||||
        QStringLiteral("<hr/>"),
 | 
			
		||||
        tr("Built with Qt %1 (%2)").arg(QT_VERSION_STR, QSysInfo::buildCpuArchitecture()),
 | 
			
		||||
        QStringLiteral("<br/><a href='%1'>%2</a>").arg("https://github.com/BLumia/pineapple-pictures", tr("Source code")),
 | 
			
		||||
        QStringLiteral("</center>")
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    QStringList specialThanksStr {
 | 
			
		||||
        QStringLiteral("<h1 align='center'>%1</h1><a href='%2'>%3</a><p>%4</p>").arg(
 | 
			
		||||
            tr("Contributors"),
 | 
			
		||||
            QStringLiteral("https://github.com/BLumia/pineapple-pictures/graphs/contributors"),
 | 
			
		||||
            tr("List of contributors on GitHub"),
 | 
			
		||||
            tr("Thanks to all people who contributed to this project.")
 | 
			
		||||
        ),
 | 
			
		||||
#if 0
 | 
			
		||||
        QStringLiteral("<h1 align='center'>%1</h1><p>%2</p>").arg(
 | 
			
		||||
            tr("Translators"),
 | 
			
		||||
            tr("I would like to thank the following people who volunteered to translate this application.")
 | 
			
		||||
        ),
 | 
			
		||||
#endif
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    QStringList licenseStr {
 | 
			
		||||
        QStringLiteral("<h1 align='center'><b>%1</b></h1>").arg(tr("Your Rights")),
 | 
			
		||||
        QStringLiteral("<p>%1</p><p>%2</p><ul><li>%3</li><li>%4</li><li>%5</li><li>%6</li></ul>").arg(
 | 
			
		||||
            tr("%1 is released under the MIT License."), // %1
 | 
			
		||||
            tr("This license grants people a number of freedoms:"), // %2
 | 
			
		||||
            tr("You are free to use %1, for any purpose"), // %3
 | 
			
		||||
            tr("You are free to distribute %1"), // %4
 | 
			
		||||
            tr("You can study how %1 works and change it"), // %5
 | 
			
		||||
            tr("You can distribute changed versions of %1") // %6
 | 
			
		||||
        ).arg(QStringLiteral("<i>%1</i>")),
 | 
			
		||||
        QStringLiteral("<p>%1</p>").arg(tr("The MIT license guarantees you this freedom. Nobody is ever permitted to take it away.")),
 | 
			
		||||
        QStringLiteral("<hr/><pre>%2</pre>")
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    QString mitLicense(QStringLiteral(R"(Expat/MIT License
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2020 BLumia
 | 
			
		||||
 | 
			
		||||
Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
in the Software without restriction, including without limitation the rights
 | 
			
		||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
furnished to do so, subject to the following conditions:
 | 
			
		||||
 | 
			
		||||
The above copyright notice and this permission notice shall be included in all
 | 
			
		||||
copies or substantial portions of the Software.
 | 
			
		||||
 | 
			
		||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
			
		||||
SOFTWARE.
 | 
			
		||||
)"));
 | 
			
		||||
 | 
			
		||||
    QStringList thirdPartyLibsStr {
 | 
			
		||||
        QStringLiteral("<h1 align='center'><b>%1</b></h1>").arg(tr("Third-party Libraries used by %1")),
 | 
			
		||||
        tr("%1 is built on the following free software libraries:"),
 | 
			
		||||
        QStringLiteral("<ul>"),
 | 
			
		||||
        QStringLiteral("<li><a href='%1'>%2</a>: %3</li>").arg("https://www.qt.io/", "Qt", "GPLv2 + GPLv3 + LGPLv2.1 + LGPLv3"),
 | 
			
		||||
        QStringLiteral("</ul>")
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    m_helpTextEdit->setText(helpStr.join('\n'));
 | 
			
		||||
 | 
			
		||||
    m_aboutTextEdit->setText(aboutStr.join('\n'));
 | 
			
		||||
    m_aboutTextEdit->setOpenExternalLinks(true);
 | 
			
		||||
 | 
			
		||||
    m_specialThanksTextEdit->setText(specialThanksStr.join('\n'));
 | 
			
		||||
    m_specialThanksTextEdit->setOpenExternalLinks(true);
 | 
			
		||||
 | 
			
		||||
    m_licenseTextEdit->setText(licenseStr.join('\n').arg(qApp->applicationDisplayName(), mitLicense));
 | 
			
		||||
 | 
			
		||||
    m_3rdPartyLibsTextEdit->setText(thirdPartyLibsStr.join('\n').arg(QStringLiteral("<i>%1</i>")).arg(qApp->applicationDisplayName()));
 | 
			
		||||
    m_3rdPartyLibsTextEdit->setOpenExternalLinks(true);
 | 
			
		||||
 | 
			
		||||
    m_tabWidget->addTab(m_helpTextEdit, tr("&Help"));
 | 
			
		||||
    m_tabWidget->addTab(m_aboutTextEdit, tr("&About"));
 | 
			
		||||
    m_tabWidget->addTab(m_specialThanksTextEdit, tr("&Special Thanks"));
 | 
			
		||||
    m_tabWidget->addTab(m_licenseTextEdit, tr("&License"));
 | 
			
		||||
    m_tabWidget->addTab(m_3rdPartyLibsTextEdit, tr("&Third-party Libraries"));
 | 
			
		||||
 | 
			
		||||
    m_buttonBox->setStandardButtons(QDialogButtonBox::Close);
 | 
			
		||||
    connect(m_buttonBox, QOverload<QAbstractButton *>::of(&QDialogButtonBox::clicked), this, [this](){
 | 
			
		||||
        this->close();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    setLayout(new QVBoxLayout);
 | 
			
		||||
 | 
			
		||||
    layout()->addWidget(m_tabWidget);
 | 
			
		||||
    layout()->addWidget(m_buttonBox);
 | 
			
		||||
 | 
			
		||||
    setMinimumSize(361, 161); // not sure why it complain "Unable to set geometry"
 | 
			
		||||
    setWindowFlag(Qt::WindowContextHelpButtonHint, false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
AboutDialog::~AboutDialog()
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
QSize AboutDialog::sizeHint() const
 | 
			
		||||
{
 | 
			
		||||
    return QSize(520, 350);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										32
									
								
								aboutdialog.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								aboutdialog.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,32 @@
 | 
			
		||||
#ifndef ABOUTDIALOG_H
 | 
			
		||||
#define ABOUTDIALOG_H
 | 
			
		||||
 | 
			
		||||
#include <QDialog>
 | 
			
		||||
 | 
			
		||||
QT_BEGIN_NAMESPACE
 | 
			
		||||
class QTextBrowser;
 | 
			
		||||
class QTabWidget;
 | 
			
		||||
class QDialogButtonBox;
 | 
			
		||||
QT_END_NAMESPACE
 | 
			
		||||
 | 
			
		||||
class AboutDialog : public QDialog
 | 
			
		||||
{
 | 
			
		||||
    Q_OBJECT
 | 
			
		||||
public:
 | 
			
		||||
    explicit AboutDialog(QWidget *parent = nullptr);
 | 
			
		||||
    ~AboutDialog() override;
 | 
			
		||||
 | 
			
		||||
    QSize sizeHint() const override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    QTabWidget * m_tabWidget = nullptr;
 | 
			
		||||
    QDialogButtonBox * m_buttonBox = nullptr;
 | 
			
		||||
 | 
			
		||||
    QTextBrowser * m_helpTextEdit = nullptr;
 | 
			
		||||
    QTextBrowser * m_aboutTextEdit = nullptr;
 | 
			
		||||
    QTextBrowser * m_specialThanksTextEdit = nullptr;
 | 
			
		||||
    QTextBrowser * m_licenseTextEdit = nullptr;
 | 
			
		||||
    QTextBrowser * m_3rdPartyLibsTextEdit = nullptr;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // ABOUTDIALOG_H
 | 
			
		||||
							
								
								
									
										19
									
								
								dist/appstream/net.blumia.pineapple-pictures.appdata.xml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								dist/appstream/net.blumia.pineapple-pictures.appdata.xml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,19 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<component type="desktop-application">
 | 
			
		||||
  <id>net.blumia.pineapple-pictures</id>
 | 
			
		||||
  <metadata_license>CC0-1.0</metadata_license>
 | 
			
		||||
  <project_license>GPL-3.0+</project_license>
 | 
			
		||||
  <name>Pineapple Pictures</name>
 | 
			
		||||
  <name xml:lang="zh-CN">菠萝看图</name>
 | 
			
		||||
  <summary>Image Viewer</summary>
 | 
			
		||||
  <summary xml:lang="zh-CN">图像查看器</summary>
 | 
			
		||||
  <description>
 | 
			
		||||
    <p>Pineapple Pictures is a lightweight and easy to use image viewer, comes with a handy navigation thumbnail when zoom-in, and doesn't contains any image management support.</p>
 | 
			
		||||
    <p xml:lang="zh-CN">菠萝看图是一个轻量级易用的图像查看器,在图片放大时提供了方便的鸟瞰导航功能,且不包含任何图片管理功能。</p>
 | 
			
		||||
  </description>
 | 
			
		||||
  <url type="homepage">https://github.com/BLumia/pineapple-pictures</url>
 | 
			
		||||
  <url type="bugtracker">https://github.com/BLumia/pineapple-pictures/issues</url>
 | 
			
		||||
  <provides>
 | 
			
		||||
    <binary>ppic</binary>
 | 
			
		||||
  </provides>
 | 
			
		||||
</component>
 | 
			
		||||
@ -24,7 +24,9 @@ GraphicsScene::~GraphicsScene()
 | 
			
		||||
void GraphicsScene::showImage(const QPixmap &pixmap)
 | 
			
		||||
{
 | 
			
		||||
    this->clear();
 | 
			
		||||
    m_theThing = this->addPixmap(pixmap);
 | 
			
		||||
    QGraphicsPixmapItem * pixmapItem = this->addPixmap(pixmap);
 | 
			
		||||
    pixmapItem->setShapeMode(QGraphicsPixmapItem::BoundingRectShape);
 | 
			
		||||
    m_theThing = pixmapItem;
 | 
			
		||||
    this->setSceneRect(m_theThing->boundingRect());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -35,10 +35,6 @@ void GraphicsView::showFileFromUrl(const QUrl &url, bool doRequestGallery)
 | 
			
		||||
    // TODO: remove this workaround when M$ change the "wsl$" hostname.
 | 
			
		||||
    if (Q_UNLIKELY(url.scheme() == QStringLiteral("qtbug-86277"))) {
 | 
			
		||||
        filePath = url.path();
 | 
			
		||||
        // Qt's QUrl won't work with such hostname anyway so the urls will
 | 
			
		||||
        // still be the wrong one when requesting gallery. So we just don't
 | 
			
		||||
        // request gallery here...
 | 
			
		||||
        doRequestGallery = false;
 | 
			
		||||
    }
 | 
			
		||||
#endif // Q_OS_WIN
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,164 @@
 | 
			
		||||
<?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>
 | 
			
		||||
@ -12,22 +170,22 @@
 | 
			
		||||
<context>
 | 
			
		||||
    <name>GraphicsView</name>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../graphicsview.cpp" line="247"/>
 | 
			
		||||
        <location filename="../graphicsview.cpp" line="254"/>
 | 
			
		||||
        <source>File url list is empty</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../graphicsview.cpp" line="46"/>
 | 
			
		||||
        <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="255"/>
 | 
			
		||||
        <location filename="../graphicsview.cpp" line="262"/>
 | 
			
		||||
        <source>Image data is invalid</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../graphicsview.cpp" line="262"/>
 | 
			
		||||
        <location filename="../graphicsview.cpp" line="269"/>
 | 
			
		||||
        <source>Not supported mimedata: %1</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
@ -35,107 +193,87 @@
 | 
			
		||||
<context>
 | 
			
		||||
    <name>MainWindow</name>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="174"/>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="175"/>
 | 
			
		||||
        <source>File url list is empty</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="396"/>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="408"/>
 | 
			
		||||
        <source>&Copy</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="417"/>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="429"/>
 | 
			
		||||
        <source>Copy P&ixmap</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="422"/>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="434"/>
 | 
			
		||||
        <source>Copy &File Path</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="432"/>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="444"/>
 | 
			
		||||
        <source>&Paste Image</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="438"/>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="450"/>
 | 
			
		||||
        <source>&Paste Image File</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="443"/>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="471"/>
 | 
			
		||||
        <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="../mainwindow.cpp" line="450"/>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="472"/>
 | 
			
		||||
        <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="457"/>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="469"/>
 | 
			
		||||
        <source>Configure...</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="464"/>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="476"/>
 | 
			
		||||
        <source>Help</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="467"/>
 | 
			
		||||
        <source>Launch application with image file path as argument to load the file.</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="468"/>
 | 
			
		||||
        <source>Drag and drop image file onto the window is also supported.</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="470"/>
 | 
			
		||||
        <source>Context menu option explanation:</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="471"/>
 | 
			
		||||
        <source>Make window stay on top of all other windows.</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="472"/>
 | 
			
		||||
        <source>Avoid close window accidentally. (eg. by double clicking the window)</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
</context>
 | 
			
		||||
<context>
 | 
			
		||||
    <name>SettingsDialog</name>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../settingsdialog.cpp" line="18"/>
 | 
			
		||||
        <source>Do nothing</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../settingsdialog.cpp" line="19"/>
 | 
			
		||||
        <source>Close the window</source>
 | 
			
		||||
        <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="28"/>
 | 
			
		||||
        <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="29"/>
 | 
			
		||||
        <location filename="../settingsdialog.cpp" line="31"/>
 | 
			
		||||
        <source>Double-click behavior</source>
 | 
			
		||||
        <translation type="unfinished"></translation>
 | 
			
		||||
    </message>
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,164 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<!DOCTYPE TS>
 | 
			
		||||
<TS version="2.1" language="zh_CN">
 | 
			
		||||
<context>
 | 
			
		||||
    <name>AboutDialog</name>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="22"/>
 | 
			
		||||
        <source>About</source>
 | 
			
		||||
        <translation>关于</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <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="../aboutdialog.cpp" line="26"/>
 | 
			
		||||
        <source>Drag and drop image file onto the window is also supported.</source>
 | 
			
		||||
        <translation>也支持拖放图片文件到窗口内来加载图片。</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="27"/>
 | 
			
		||||
        <source>Context menu option explanation:</source>
 | 
			
		||||
        <translation>菜单项说明:</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="31"/>
 | 
			
		||||
        <source>Make window stay on top of all other windows.</source>
 | 
			
		||||
        <translation>使窗口始终至于其它非置顶窗口上方。</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="35"/>
 | 
			
		||||
        <source>Avoid close window accidentally. (eg. by double clicking the window)</source>
 | 
			
		||||
        <translation>避免窗口意外关闭。(如:不小心双击了窗口触发了关闭窗口行为)</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="44"/>
 | 
			
		||||
        <source>Version: %1</source>
 | 
			
		||||
        <translation>版本: %1</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="47"/>
 | 
			
		||||
        <source>Copyright (c) 2020 %1</source>
 | 
			
		||||
        <translation>版权所有 (c) 2020 %1</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="49"/>
 | 
			
		||||
        <source>Logo designed by %1</source>
 | 
			
		||||
        <translation>Logo 由 %1 设计</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="51"/>
 | 
			
		||||
        <source>Built with Qt %1 (%2)</source>
 | 
			
		||||
        <translation>使用 Qt %1 (%2) 进行构建</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="52"/>
 | 
			
		||||
        <source>Source code</source>
 | 
			
		||||
        <translation>源代码</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="58"/>
 | 
			
		||||
        <source>Contributors</source>
 | 
			
		||||
        <translation>贡献者</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="60"/>
 | 
			
		||||
        <source>List of contributors on GitHub</source>
 | 
			
		||||
        <translation>GitHub 上的贡献者列表</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="61"/>
 | 
			
		||||
        <source>Thanks to all people who contributed to this project.</source>
 | 
			
		||||
        <translation>感谢所有参与此项目的朋友。</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="65"/>
 | 
			
		||||
        <source>Translators</source>
 | 
			
		||||
        <translation>翻译者</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>我想要感谢下列自愿参与翻译此应用程序的朋友。</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="131"/>
 | 
			
		||||
        <source>&Special Thanks</source>
 | 
			
		||||
        <translation>致谢(&S)</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="133"/>
 | 
			
		||||
        <source>&Third-party Libraries</source>
 | 
			
		||||
        <translation>第三方程序库(&T)</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="72"/>
 | 
			
		||||
        <source>Your Rights</source>
 | 
			
		||||
        <translation>用户的权利</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="74"/>
 | 
			
		||||
        <source>%1 is released under the MIT License.</source>
 | 
			
		||||
        <translation>%1 是在 MIT 许可协议下发布的。</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="75"/>
 | 
			
		||||
        <source>This license grants people a number of freedoms:</source>
 | 
			
		||||
        <translation>此许可证赋予人们以下自由的权利:</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="76"/>
 | 
			
		||||
        <source>You are free to use %1, for any purpose</source>
 | 
			
		||||
        <translation>任何人都可以为了任何目的自由地使用 %1</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="77"/>
 | 
			
		||||
        <source>You are free to distribute %1</source>
 | 
			
		||||
        <translation>任何人都可以自由地分发 %1</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="78"/>
 | 
			
		||||
        <source>You can study how %1 works and change it</source>
 | 
			
		||||
        <translation>任何人都可以自由地研究 %1 的工作原理并对其进行修改</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="79"/>
 | 
			
		||||
        <source>You can distribute changed versions of %1</source>
 | 
			
		||||
        <translation>任何人都可以自由地分发修改过的 %1 版本</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>此软件通过 MIT 许可证赋予用户上述自由,任何人无权剥夺。</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="109"/>
 | 
			
		||||
        <source>Third-party Libraries used by %1</source>
 | 
			
		||||
        <translation>%1 使用的第三方程序库</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="110"/>
 | 
			
		||||
        <source>%1 is built on the following free software libraries:</source>
 | 
			
		||||
        <translation>%1 采用了下列自由软件程序库进行构建:</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="129"/>
 | 
			
		||||
        <source>&Help</source>
 | 
			
		||||
        <translation>帮助(&H)</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="130"/>
 | 
			
		||||
        <source>&About</source>
 | 
			
		||||
        <translation>关于(&A)</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="132"/>
 | 
			
		||||
        <source>&License</source>
 | 
			
		||||
        <translation>软件许可证(&L)</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
</context>
 | 
			
		||||
<context>
 | 
			
		||||
    <name>GraphicsScene</name>
 | 
			
		||||
    <message>
 | 
			
		||||
@ -12,22 +170,22 @@
 | 
			
		||||
<context>
 | 
			
		||||
    <name>GraphicsView</name>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../graphicsview.cpp" line="247"/>
 | 
			
		||||
        <location filename="../graphicsview.cpp" line="254"/>
 | 
			
		||||
        <source>File url list is empty</source>
 | 
			
		||||
        <translation>文件 URL 列表为空</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../graphicsview.cpp" line="46"/>
 | 
			
		||||
        <location filename="../graphicsview.cpp" line="53"/>
 | 
			
		||||
        <source>File is not a valid image</source>
 | 
			
		||||
        <translation>文件不是有效的图片文件</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../graphicsview.cpp" line="255"/>
 | 
			
		||||
        <location filename="../graphicsview.cpp" line="262"/>
 | 
			
		||||
        <source>Image data is invalid</source>
 | 
			
		||||
        <translation>图片数据无效</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../graphicsview.cpp" line="262"/>
 | 
			
		||||
        <location filename="../graphicsview.cpp" line="269"/>
 | 
			
		||||
        <source>Not supported mimedata: %1</source>
 | 
			
		||||
        <translation>不受支持的 MimeData 格式:%1</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
@ -35,111 +193,87 @@
 | 
			
		||||
<context>
 | 
			
		||||
    <name>MainWindow</name>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="174"/>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="175"/>
 | 
			
		||||
        <source>File url list is empty</source>
 | 
			
		||||
        <translation>文件 URL 列表为空</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="396"/>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="408"/>
 | 
			
		||||
        <source>&Copy</source>
 | 
			
		||||
        <translation>复制(&C)</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <source>Copy &Pixmap</source>
 | 
			
		||||
        <translation type="vanished">复制位图(&P)</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="417"/>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="429"/>
 | 
			
		||||
        <source>Copy P&ixmap</source>
 | 
			
		||||
        <translation>复制位图(&I)</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="422"/>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="434"/>
 | 
			
		||||
        <source>Copy &File Path</source>
 | 
			
		||||
        <translation>复制文件路径(&F)</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="432"/>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="444"/>
 | 
			
		||||
        <source>&Paste Image</source>
 | 
			
		||||
        <translation>粘贴图像(&P)</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="438"/>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="450"/>
 | 
			
		||||
        <source>&Paste Image File</source>
 | 
			
		||||
        <translation>粘贴图像文件(&P)</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="443"/>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="471"/>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="30"/>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="455"/>
 | 
			
		||||
        <source>Stay on top</source>
 | 
			
		||||
        <translation>总在最前</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="450"/>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="472"/>
 | 
			
		||||
        <location filename="../aboutdialog.cpp" line="34"/>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="462"/>
 | 
			
		||||
        <source>Protected mode</source>
 | 
			
		||||
        <translation>保护模式</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="457"/>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="469"/>
 | 
			
		||||
        <source>Configure...</source>
 | 
			
		||||
        <translation>设置...</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="464"/>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="476"/>
 | 
			
		||||
        <source>Help</source>
 | 
			
		||||
        <translation>帮助</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="467"/>
 | 
			
		||||
        <source>Launch application with image file path as argument to load the file.</source>
 | 
			
		||||
        <translation>以图片文件的路径作为参数运行程序即可直接打开图片文件。</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="468"/>
 | 
			
		||||
        <source>Drag and drop image file onto the window is also supported.</source>
 | 
			
		||||
        <translation>也支持拖放图片文件到窗口内来加载图片。</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="470"/>
 | 
			
		||||
        <source>Context menu option explanation:</source>
 | 
			
		||||
        <translation>菜单项说明:</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="471"/>
 | 
			
		||||
        <source>Make window stay on top of all other windows.</source>
 | 
			
		||||
        <translation>使窗口始终至于其它非置顶窗口上方。</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../mainwindow.cpp" line="472"/>
 | 
			
		||||
        <source>Avoid close window accidentally. (eg. by double clicking the window)</source>
 | 
			
		||||
        <translation>避免窗口意外关闭。(如:不小心双击了窗口触发了关闭窗口行为)</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
</context>
 | 
			
		||||
<context>
 | 
			
		||||
    <name>SettingsDialog</name>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../settingsdialog.cpp" line="18"/>
 | 
			
		||||
        <location filename="../settingsdialog.cpp" line="15"/>
 | 
			
		||||
        <source>Settings</source>
 | 
			
		||||
        <translation>设定</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../settingsdialog.cpp" line="20"/>
 | 
			
		||||
        <source>Do nothing</source>
 | 
			
		||||
        <translation>什么也不做</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../settingsdialog.cpp" line="19"/>
 | 
			
		||||
        <location filename="../settingsdialog.cpp" line="21"/>
 | 
			
		||||
        <source>Close the window</source>
 | 
			
		||||
        <translation>关闭窗口</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../settingsdialog.cpp" line="20"/>
 | 
			
		||||
        <location filename="../settingsdialog.cpp" line="22"/>
 | 
			
		||||
        <source>Toggle maximize</source>
 | 
			
		||||
        <translation>最大化窗口</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../settingsdialog.cpp" line="28"/>
 | 
			
		||||
        <location filename="../settingsdialog.cpp" line="30"/>
 | 
			
		||||
        <source>Stay on top when start-up</source>
 | 
			
		||||
        <translation>启动时保持窗口总在最前</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
    <message>
 | 
			
		||||
        <location filename="../settingsdialog.cpp" line="29"/>
 | 
			
		||||
        <location filename="../settingsdialog.cpp" line="31"/>
 | 
			
		||||
        <source>Double-click behavior</source>
 | 
			
		||||
        <translation>双击时的行为</translation>
 | 
			
		||||
    </message>
 | 
			
		||||
 | 
			
		||||
@ -7,6 +7,9 @@
 | 
			
		||||
#include "navigatorview.h"
 | 
			
		||||
#include "graphicsscene.h"
 | 
			
		||||
#include "settingsdialog.h"
 | 
			
		||||
#include "aboutdialog.h"
 | 
			
		||||
#include "metadatadialog.h"
 | 
			
		||||
#include "metadatamodel.h"
 | 
			
		||||
 | 
			
		||||
#include <QMouseEvent>
 | 
			
		||||
#include <QMovie>
 | 
			
		||||
@ -36,7 +39,7 @@ MainWindow::MainWindow(QWidget *parent) :
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this->setAttribute(Qt::WA_TranslucentBackground, true);
 | 
			
		||||
    this->setMinimumSize(350, 350);
 | 
			
		||||
    this->setMinimumSize(350, 330);
 | 
			
		||||
    this->setWindowIcon(QIcon(":/icons/app-icon.svg"));
 | 
			
		||||
    this->setMouseTracking(true);
 | 
			
		||||
 | 
			
		||||
@ -238,9 +241,20 @@ void MainWindow::loadGalleryBySingleLocalFile(const QString &path)
 | 
			
		||||
    clearGallery();
 | 
			
		||||
 | 
			
		||||
    for (int i = 0; i < entryList.count(); i++) {
 | 
			
		||||
        const QString & oneEntry = entryList.at(i);
 | 
			
		||||
        m_files.append(QUrl::fromLocalFile(dir.absoluteFilePath(oneEntry)));
 | 
			
		||||
        if (oneEntry == currentFileName) {
 | 
			
		||||
        const QString & fileName = entryList.at(i);
 | 
			
		||||
        const QString & oneEntry = dir.absoluteFilePath(fileName);
 | 
			
		||||
        QUrl url = QUrl::fromLocalFile(oneEntry);
 | 
			
		||||
#ifdef Q_OS_WIN
 | 
			
		||||
        // TODO: remove this workaround when M$ change the "wsl$" hostname.
 | 
			
		||||
        // Qt will convert path "\\wsl$\" to "//wsl$/"...
 | 
			
		||||
        if (Q_UNLIKELY(oneEntry.startsWith(R"(//wsl$/)"))) {
 | 
			
		||||
            url.clear();
 | 
			
		||||
            url.setScheme(QStringLiteral("qtbug-86277"));
 | 
			
		||||
            url.setPath(oneEntry);
 | 
			
		||||
        }
 | 
			
		||||
#endif // Q_OS_WIN
 | 
			
		||||
        m_files.append(url);
 | 
			
		||||
        if (fileName == currentFileName) {
 | 
			
		||||
            m_currentFileIndex = i;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@ -463,15 +477,20 @@ void MainWindow::contextMenuEvent(QContextMenuEvent *event)
 | 
			
		||||
 | 
			
		||||
    QAction * helpAction = new QAction(tr("Help"));
 | 
			
		||||
    connect(helpAction, &QAction::triggered, this, [ = ](){
 | 
			
		||||
        QStringList sl {
 | 
			
		||||
            tr("Launch application with image file path as argument to load the file."),
 | 
			
		||||
            tr("Drag and drop image file onto the window is also supported."),
 | 
			
		||||
            "",
 | 
			
		||||
            tr("Context menu option explanation:"),
 | 
			
		||||
            (tr("Stay on top") + " : " + tr("Make window stay on top of all other windows.")),
 | 
			
		||||
            (tr("Protected mode") + " : " + tr("Avoid close window accidentally. (eg. by double clicking the window)"))
 | 
			
		||||
        };
 | 
			
		||||
        m_graphicsView->showText(sl.join('\n'));
 | 
			
		||||
        AboutDialog * ad = new AboutDialog(this);
 | 
			
		||||
        ad->exec();
 | 
			
		||||
        ad->deleteLater();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    QAction * propertiesAction = new QAction(tr("Properties"));
 | 
			
		||||
    connect(propertiesAction, &QAction::triggered, this, [ = ](){
 | 
			
		||||
        MetadataModel * md = new MetadataModel();
 | 
			
		||||
        md->setFile(currentFileUrl.toLocalFile());
 | 
			
		||||
 | 
			
		||||
        MetadataDialog * ad = new MetadataDialog(this);
 | 
			
		||||
        ad->setMetadataModel(md);
 | 
			
		||||
        ad->exec();
 | 
			
		||||
        ad->deleteLater();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    if (copyMenu->actions().count() == 1) {
 | 
			
		||||
@ -490,6 +509,10 @@ void MainWindow::contextMenuEvent(QContextMenuEvent *event)
 | 
			
		||||
    menu->addSeparator();
 | 
			
		||||
    menu->addAction(toggleSettings);
 | 
			
		||||
    menu->addAction(helpAction);
 | 
			
		||||
    if (currentFileUrl.isValid()) {
 | 
			
		||||
        menu->addSeparator();
 | 
			
		||||
        menu->addAction(propertiesAction);
 | 
			
		||||
    }
 | 
			
		||||
    menu->exec(mapToGlobal(event->pos()));
 | 
			
		||||
    menu->deleteLater();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										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);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										26
									
								
								metadatadialog.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								metadatadialog.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,26 @@
 | 
			
		||||
#ifndef METADATADIALOG_H
 | 
			
		||||
#define METADATADIALOG_H
 | 
			
		||||
 | 
			
		||||
#include <QDialog>
 | 
			
		||||
 | 
			
		||||
QT_BEGIN_NAMESPACE
 | 
			
		||||
class QTreeView;
 | 
			
		||||
QT_END_NAMESPACE
 | 
			
		||||
 | 
			
		||||
class MetadataModel;
 | 
			
		||||
class MetadataDialog : public QDialog
 | 
			
		||||
{
 | 
			
		||||
    Q_OBJECT
 | 
			
		||||
public:
 | 
			
		||||
    explicit MetadataDialog(QWidget * parent);
 | 
			
		||||
    ~MetadataDialog() override;
 | 
			
		||||
 | 
			
		||||
    void setMetadataModel(MetadataModel * model);
 | 
			
		||||
 | 
			
		||||
    QSize sizeHint() const override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    QTreeView * m_treeView = nullptr;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif // METADATADIALOG_H
 | 
			
		||||
							
								
								
									
										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
 | 
			
		||||
@ -4,11 +4,9 @@
 | 
			
		||||
#
 | 
			
		||||
#-------------------------------------------------
 | 
			
		||||
 | 
			
		||||
QT       += core gui svg
 | 
			
		||||
QT       += core widgets gui svg
 | 
			
		||||
 | 
			
		||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
 | 
			
		||||
 | 
			
		||||
TARGET = PineapplePictures
 | 
			
		||||
TARGET = ppic
 | 
			
		||||
TEMPLATE = app
 | 
			
		||||
 | 
			
		||||
# The following define makes your compiler emit warnings if you use
 | 
			
		||||
@ -25,11 +23,15 @@ DEFINES += QT_DEPRECATED_WARNINGS
 | 
			
		||||
CONFIG += c++11 lrelease embed_translations
 | 
			
		||||
 | 
			
		||||
SOURCES += \
 | 
			
		||||
    aboutdialog.cpp \
 | 
			
		||||
        main.cpp \
 | 
			
		||||
        mainwindow.cpp \
 | 
			
		||||
    graphicsview.cpp \
 | 
			
		||||
    bottombuttongroup.cpp \
 | 
			
		||||
    graphicsscene.cpp \
 | 
			
		||||
    metadata.cpp \
 | 
			
		||||
    metadatadialog.cpp \
 | 
			
		||||
    metadatamodel.cpp \
 | 
			
		||||
    navigatorview.cpp \
 | 
			
		||||
    opacityhelper.cpp \
 | 
			
		||||
    toolbutton.cpp \
 | 
			
		||||
@ -37,10 +39,14 @@ SOURCES += \
 | 
			
		||||
    settingsdialog.cpp
 | 
			
		||||
 | 
			
		||||
HEADERS += \
 | 
			
		||||
    aboutdialog.h \
 | 
			
		||||
        mainwindow.h \
 | 
			
		||||
    graphicsview.h \
 | 
			
		||||
    bottombuttongroup.h \
 | 
			
		||||
    graphicsscene.h \
 | 
			
		||||
    metadata.h \
 | 
			
		||||
    metadatadialog.h \
 | 
			
		||||
    metadatamodel.h \
 | 
			
		||||
    navigatorview.h \
 | 
			
		||||
    opacityhelper.h \
 | 
			
		||||
    toolbutton.h \
 | 
			
		||||
@ -62,3 +68,8 @@ RESOURCES += \
 | 
			
		||||
# Generate from svg:
 | 
			
		||||
# magick convert -background none app-icon.svg -define icon:auto-resize="16,32,48,64,128,256" app-icon.ico
 | 
			
		||||
RC_ICONS = icons/app-icon.ico
 | 
			
		||||
 | 
			
		||||
# Windows only, for rc file (we're not going to use the .rc file in this repo)
 | 
			
		||||
QMAKE_TARGET_PRODUCT = Pineapple Pictures
 | 
			
		||||
QMAKE_TARGET_DESCRIPTION = Pineapple Pictures - Image Viewer
 | 
			
		||||
QMAKE_TARGET_COPYRIGHT = MIT/Expat License - Copyright (C) 2020 Gary Wang
 | 
			
		||||
@ -12,6 +12,8 @@ SettingsDialog::SettingsDialog(QWidget *parent)
 | 
			
		||||
    , m_stayOnTop(new QCheckBox)
 | 
			
		||||
    , m_doubleClickBehavior(new QComboBox)
 | 
			
		||||
{
 | 
			
		||||
    this->setWindowTitle(tr("Settings"));
 | 
			
		||||
 | 
			
		||||
    QFormLayout * settingsForm = new QFormLayout(this);
 | 
			
		||||
 | 
			
		||||
    static QMap<DoubleClickBehavior, QString> _map {
 | 
			
		||||
 | 
			
		||||
@ -2,7 +2,6 @@
 | 
			
		||||
#define SETTINGSDIALOG_H
 | 
			
		||||
 | 
			
		||||
#include <QObject>
 | 
			
		||||
#include <QWidget>
 | 
			
		||||
#include <QDialog>
 | 
			
		||||
 | 
			
		||||
class QCheckBox;
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user