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