17 Commits

Author SHA1 Message Date
919a672c17 chore(CI): bump Qt version to 6.9.2 2025-08-28 00:28:05 +08:00
e52a6d8eed feat: new action for fit long image 2025-08-25 12:48:35 +08:00
8b0c8ec194 i18n: update ts files 2025-08-25 12:47:42 +08:00
1da7fff518 i18n: Translations update from Hosted Weblate (#159)
* Translated using Weblate (Italian)

Currently translated at 100.0% (167 of 167 strings)

Translation: pineapple-pictures/Application
Translate-URL: https://hosted.weblate.org/projects/pineapple-pictures/application/it/

* Translated using Weblate (Dutch)

Currently translated at 100.0% (167 of 167 strings)

Translation: pineapple-pictures/Application
Translate-URL: https://hosted.weblate.org/projects/pineapple-pictures/application/nl/

---------

Co-authored-by: albanobattistella <albano_battistella@hotmail.com>
Co-authored-by: Heimen Stoffels <vistausss@fastmail.com>
2025-08-25 12:44:28 +08:00
e216592205 fix(CI): reuse lint 2025-08-24 14:08:00 +08:00
8fc9d06937 chore: add product version to windows build rc file 2025-08-24 13:53:14 +08:00
73b15da182 chore: remove gitee release page link from README.zh_CN.md 2025-08-23 15:24:00 +08:00
f4f7d93e38 chore: simplified long image mode code 2025-08-05 00:06:05 +08:00
591b01a83a i18n: update ts files 2025-08-04 21:56:58 +08:00
f8d3dcc899 feat: auto long image mode 2025-08-04 20:41:49 +08:00
f0ed9d0ca1 chore: update release info to 1.1.1 2025-08-02 13:30:14 +08:00
13227cfac9 i18n: Translations update from Hosted Weblate (#157)
* Translated using Weblate (Korean)

Currently translated at 100.0% (166 of 166 strings)

Translation: pineapple-pictures/Application
Translate-URL: https://hosted.weblate.org/projects/pineapple-pictures/application/ko/

* Translated using Weblate (Dutch)

Currently translated at 100.0% (166 of 166 strings)

Translation: pineapple-pictures/Application
Translate-URL: https://hosted.weblate.org/projects/pineapple-pictures/application/nl/

---------

Co-authored-by: VenusGirl <VenusGirl@outlook.com>
Co-authored-by: Heimen Stoffels <vistausss@fastmail.com>
2025-08-01 23:44:43 +08:00
b73df5ea1a refactor: make fitByOrientation() more sane 2025-07-27 15:53:23 +08:00
4375fe1c2d chore: avoid use screenAt(QCursor::pos()) 2025-07-26 16:03:13 +08:00
4654cb21a0 fix: REUSE compliance 2025-07-23 21:29:18 +08:00
ba23208a7a chore: add config file for CRLF to LF change 2025-07-23 21:22:41 +08:00
ed5a602332 chore: let's use LF all the time 2025-07-23 21:20:34 +08:00
62 changed files with 5215 additions and 4823 deletions

3
.git-blame-ignore-revs Normal file
View File

@ -0,0 +1,3 @@
# .git-blame-ignore-revs
# CR LF to LF
ed5a6023326fd2ab420ded76976501be33e0b389

5
.gitattributes vendored Normal file
View File

@ -0,0 +1,5 @@
*.txt text eol=lf
*.cpp text eol=lf
*.h text eol=lf
*.ui text eol=lf
*.qml text eol=lf

View File

@ -12,7 +12,7 @@ jobs:
- name: Install Qt
uses: jurplel/install-qt-action@v4
with:
version: '6.9.1'
version: '6.9.2'
modules: 'qtimageformats'
- name: Install Conan and Dependencies
id: conan

View File

@ -8,7 +8,7 @@ jobs:
strategy:
matrix:
include:
- qt_ver: '6.9.1'
- qt_ver: '6.9.2'
vs: '2022'
aqt_arch: 'win64_msvc2022_64'
msvc_arch: 'x64'
@ -44,7 +44,7 @@ jobs:
strategy:
matrix:
include:
- qt_ver: '6.9.1'
- qt_ver: '6.9.2'
vs: '2022'
aqt_arch: 'win64_msvc2022_64'
msvc_arch: 'x64'

View File

@ -4,7 +4,7 @@
cmake_minimum_required(VERSION 3.16)
project(pineapple-pictures VERSION 1.1.0) # don't forget to update NEWS file and AppStream metadata.
project(pineapple-pictures VERSION 1.1.1) # don't forget to update NEWS file and AppStream metadata.
include(GNUInstallDirs)
include(FeatureSummary)
@ -94,7 +94,8 @@ file (GLOB PPIC_TS_FILES app/translations/*.ts)
set (PPIC_CPP_FILES_FOR_I18N ${PPIC_CPP_FILES})
if (WIN32)
list(APPEND PPIC_RC_FILES assets/pineapple-pictures.rc)
configure_file(assets/pineapple-pictures.rc.in pineapple-pictures.rc @ONLY)
list(APPEND PPIC_RC_FILES ${CMAKE_CURRENT_BINARY_DIR}/pineapple-pictures.rc)
endif ()
add_executable (${EXE_NAME}

42
LICENSE
View File

@ -1,21 +1,21 @@
MIT License
Copyright (c) 2025 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.
MIT License
Copyright (c) 2025 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.

17
NEWS
View File

@ -1,3 +1,20 @@
Version 1.1.1
~~~~~~~~~~~~~
Released: 2025-08-02
Features:
* Click dock icon should show window when it's hidden on macOS
Bugfixes:
* Ensure "Fit by Width" position the view to the beginning of the image
Miscellaneous:
* Update translations
* Update Exiv2 version for Windows binary build
Contributors:
Heimen Stoffels, VenusGirl, தமிழ்நேரம்
Version 1.1.0
~~~~~~~~~~~~~
Released: 2025-07-06

View File

@ -16,7 +16,7 @@
### 由原作者维护
- [GitHub Release 页面](https://github.com/BLumia/pineapple-pictures/releases) | [gitee 发布页面](https://gitee.com/blumia/pineapple-pictures/releases)
- [GitHub Release 页面](https://github.com/BLumia/pineapple-pictures/releases)
- [SourceForge](https://sourceforge.net/projects/pineapple-pictures/)
- Archlinux AUR: [pineapple-pictures](https://aur.archlinux.org/packages/pineapple-pictures/) | [pineapple-pictures-git](https://aur.archlinux.org/packages/pineapple-pictures-git/)
- [Itch.io 商店](https://blumia.itch.io/pineapple-pictures)

View File

@ -1,33 +1,33 @@
version = 1
SPDX-PackageName = "Pineapple Pictures"
SPDX-PackageDownloadLocation = "https://github.com/BLumia/pineapple-pictures"
[[annotations]]
path = [".gitignore", "appveyor.yml", ".github/**"]
precedence = "aggregate"
SPDX-FileCopyrightText = "None"
SPDX-License-Identifier = "CC0-1.0"
[[annotations]]
path = ["README**.md", "NEWS", "assets/**.rc", "assets/**.qrc", "dist/**"]
precedence = "aggregate"
SPDX-FileCopyrightText = "None"
SPDX-License-Identifier = "CC0-1.0"
[[annotations]]
path = ["app/translations/**.ts", "assets/plain/translators.html"]
precedence = "aggregate"
SPDX-FileCopyrightText = "Translators from hosted.weblate.org"
SPDX-License-Identifier = "MIT"
[[annotations]]
path = "assets/icons/**.svg"
precedence = "aggregate"
SPDX-FileCopyrightText = "2022 Gary Wang"
SPDX-License-Identifier = "MIT"
[[annotations]]
path = "assets/icons/app-icon.**"
precedence = "aggregate"
SPDX-FileCopyrightText = "2020 Lovelyblack"
SPDX-License-Identifier = "MIT"
version = 1
SPDX-PackageName = "Pineapple Pictures"
SPDX-PackageDownloadLocation = "https://github.com/BLumia/pineapple-pictures"
[[annotations]]
path = [".gitattributes", ".git-blame-ignore-revs", ".gitignore", "appveyor.yml", ".github/**"]
precedence = "aggregate"
SPDX-FileCopyrightText = "None"
SPDX-License-Identifier = "CC0-1.0"
[[annotations]]
path = ["README**.md", "NEWS", "assets/**.rc.in", "assets/**.qrc", "dist/**"]
precedence = "aggregate"
SPDX-FileCopyrightText = "None"
SPDX-License-Identifier = "CC0-1.0"
[[annotations]]
path = ["app/translations/**.ts", "assets/plain/translators.html"]
precedence = "aggregate"
SPDX-FileCopyrightText = "Translators from hosted.weblate.org"
SPDX-License-Identifier = "MIT"
[[annotations]]
path = "assets/icons/**.svg"
precedence = "aggregate"
SPDX-FileCopyrightText = "2022 Gary Wang"
SPDX-License-Identifier = "MIT"
[[annotations]]
path = "assets/icons/app-icon.**"
precedence = "aggregate"
SPDX-FileCopyrightText = "2020 Lovelyblack"
SPDX-License-Identifier = "MIT"

View File

@ -1,181 +1,181 @@
// SPDX-FileCopyrightText: 2022 Gary Wang <wzc782970009@gmail.com>
//
// SPDX-License-Identifier: MIT
#include "aboutdialog.h"
#include <QAbstractButton>
#include <QDialogButtonBox>
#include <QTextBrowser>
#include <QTabWidget>
#include <QVBoxLayout>
#include <QApplication>
#include <QLabel>
#include <QPushButton>
#include <QFile>
using namespace Qt::Literals::StringLiterals;
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"));
const QStringList helpStr {
u"<p>%1</p>"_s.arg(tr("Launch application with image file path as argument to load the file.")),
u"<p>%1</p>"_s.arg(tr("Drag and drop image file onto the window is also supported.")),
u"<p>%1</p>"_s.arg(tr("None of the operations in this application will alter the pictures on disk.")),
u"<p>%1</p>"_s.arg(tr("Context menu option explanation:")),
u"<ul>"_s,
// blumia: Chain two arg() here since it seems lupdate will remove one of them if we use
// the old `arg(QCoreApp::translate(), tr())` way, but it's worth to mention
// `arg(QCoreApp::translate(), this->tr())` works, but lupdate will complain about the usage.
u"<li><b>%1</b>:<br/>%2</li>"_s
.arg(QCoreApplication::translate("MainWindow", "Stay on top"))
.arg(tr("Make window stay on top of all other windows.")),
u"<li><b>%1</b>:<br/>%2</li>"_s
.arg(QCoreApplication::translate("MainWindow", "Protected mode"))
.arg(tr("Avoid close window accidentally. (eg. by double clicking the window)")),
u"<li><b>%1</b>:<br/>%2</li>"_s
.arg(QCoreApplication::translate("MainWindow", "Keep transformation", "The 'transformation' means the flip/rotation status that currently applied to the image view"))
.arg(tr("Avoid resetting the zoom/rotation/flip state that was applied to the image view when switching between images.")),
u"</ul>"_s
};
const QStringList aboutStr {
u"<center><img width='128' height='128' src=':/icons/app-icon.svg'/><br/>"_s,
qApp->applicationDisplayName(),
(u"<br/>"_s + tr("Version: %1").arg(
#ifdef GIT_DESCRIBE_VERSION_STRING
GIT_DESCRIBE_VERSION_STRING
#else
qApp->applicationVersion()
#endif // GIT_DESCRIBE_VERSION_STRING
)),
u"<hr/>"_s,
tr("Copyright (c) %1 %2", "%1 is year, %2 is the name of copyright holder(s)")
.arg(u"2025"_s, u"<a href='https://github.com/BLumia'>@BLumia</a>"_s),
u"<br/>"_s,
tr("Logo designed by %1").arg(u"<a href='https://github.com/Lovelyblack'>@Lovelyblack</a>"_s),
u"<hr/>"_s,
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")),
u"</center>"_s
};
QFile translaterHtml(u":/plain/translators.html"_s);
bool canOpenFile = translaterHtml.open(QIODevice::ReadOnly);
const QByteArray & translatorList = canOpenFile ? translaterHtml.readAll() : QByteArrayLiteral("");
const QStringList specialThanksStr {
u"<h1 align='center'>%1</h1><a href='%2'>%3</a><p>%4</p>"_s.arg(
tr("Contributors"),
u"https://github.com/BLumia/pineapple-pictures/graphs/contributors"_s,
tr("List of contributors on GitHub"),
tr("Thanks to all people who contributed to this project.")
),
u"<h1 align='center'>%1</h1><p>%2</p>%3"_s.arg(
tr("Translators"),
tr("I would like to thank the following people who volunteered to translate this application."),
translatorList
)
};
const QStringList licenseStr {
u"<h1 align='center'><b>%1</b></h1>"_s.arg(tr("Your Rights")),
u"<p>%1</p><p>%2</p><ul><li>%3</li><li>%4</li><li>%5</li><li>%6</li></ul>"_s.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(u"<i>%1</i>"_s),
u"<p>%1</p>"_s.arg(tr("The MIT license guarantees you this freedom. Nobody is ever permitted to take it away.")),
u"<hr/><pre>%2</pre>"_s
};
const QString mitLicense(QStringLiteral(R"(Expat/MIT License
Copyright (c) 2025 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.
)"));
const QStringList thirdPartyLibsStr {
u"<h1 align='center'><b>%1</b></h1>"_s.arg(tr("Third-party Libraries used by %1")),
tr("%1 is built on the following free software libraries:", "Free as in freedom"),
u"<ul>"_s,
#ifdef HAVE_EXIV2_VERSION
u"<li><a href='%1'>%2</a>: %3</li>"_s.arg("https://www.exiv2.org/", "Exiv2", "GPLv2"),
#endif // EXIV2_VERSION
u"<li><a href='%1'>%2</a>: %3</li>"_s.arg("https://www.qt.io/", "Qt", "GPLv2 + GPLv3 + LGPLv2.1 + LGPLv3"),
u"</ul>"_s
};
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(u"<i>%1</i>"_s).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);
}
// SPDX-FileCopyrightText: 2022 Gary Wang <wzc782970009@gmail.com>
//
// SPDX-License-Identifier: MIT
#include "aboutdialog.h"
#include <QAbstractButton>
#include <QDialogButtonBox>
#include <QTextBrowser>
#include <QTabWidget>
#include <QVBoxLayout>
#include <QApplication>
#include <QLabel>
#include <QPushButton>
#include <QFile>
using namespace Qt::Literals::StringLiterals;
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"));
const QStringList helpStr {
u"<p>%1</p>"_s.arg(tr("Launch application with image file path as argument to load the file.")),
u"<p>%1</p>"_s.arg(tr("Drag and drop image file onto the window is also supported.")),
u"<p>%1</p>"_s.arg(tr("None of the operations in this application will alter the pictures on disk.")),
u"<p>%1</p>"_s.arg(tr("Context menu option explanation:")),
u"<ul>"_s,
// blumia: Chain two arg() here since it seems lupdate will remove one of them if we use
// the old `arg(QCoreApp::translate(), tr())` way, but it's worth to mention
// `arg(QCoreApp::translate(), this->tr())` works, but lupdate will complain about the usage.
u"<li><b>%1</b>:<br/>%2</li>"_s
.arg(QCoreApplication::translate("MainWindow", "Stay on top"))
.arg(tr("Make window stay on top of all other windows.")),
u"<li><b>%1</b>:<br/>%2</li>"_s
.arg(QCoreApplication::translate("MainWindow", "Protected mode"))
.arg(tr("Avoid close window accidentally. (eg. by double clicking the window)")),
u"<li><b>%1</b>:<br/>%2</li>"_s
.arg(QCoreApplication::translate("MainWindow", "Keep transformation", "The 'transformation' means the flip/rotation status that currently applied to the image view"))
.arg(tr("Avoid resetting the zoom/rotation/flip state that was applied to the image view when switching between images.")),
u"</ul>"_s
};
const QStringList aboutStr {
u"<center><img width='128' height='128' src=':/icons/app-icon.svg'/><br/>"_s,
qApp->applicationDisplayName(),
(u"<br/>"_s + tr("Version: %1").arg(
#ifdef GIT_DESCRIBE_VERSION_STRING
GIT_DESCRIBE_VERSION_STRING
#else
qApp->applicationVersion()
#endif // GIT_DESCRIBE_VERSION_STRING
)),
u"<hr/>"_s,
tr("Copyright (c) %1 %2", "%1 is year, %2 is the name of copyright holder(s)")
.arg(u"2025"_s, u"<a href='https://github.com/BLumia'>@BLumia</a>"_s),
u"<br/>"_s,
tr("Logo designed by %1").arg(u"<a href='https://github.com/Lovelyblack'>@Lovelyblack</a>"_s),
u"<hr/>"_s,
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")),
u"</center>"_s
};
QFile translaterHtml(u":/plain/translators.html"_s);
bool canOpenFile = translaterHtml.open(QIODevice::ReadOnly);
const QByteArray & translatorList = canOpenFile ? translaterHtml.readAll() : QByteArrayLiteral("");
const QStringList specialThanksStr {
u"<h1 align='center'>%1</h1><a href='%2'>%3</a><p>%4</p>"_s.arg(
tr("Contributors"),
u"https://github.com/BLumia/pineapple-pictures/graphs/contributors"_s,
tr("List of contributors on GitHub"),
tr("Thanks to all people who contributed to this project.")
),
u"<h1 align='center'>%1</h1><p>%2</p>%3"_s.arg(
tr("Translators"),
tr("I would like to thank the following people who volunteered to translate this application."),
translatorList
)
};
const QStringList licenseStr {
u"<h1 align='center'><b>%1</b></h1>"_s.arg(tr("Your Rights")),
u"<p>%1</p><p>%2</p><ul><li>%3</li><li>%4</li><li>%5</li><li>%6</li></ul>"_s.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(u"<i>%1</i>"_s),
u"<p>%1</p>"_s.arg(tr("The MIT license guarantees you this freedom. Nobody is ever permitted to take it away.")),
u"<hr/><pre>%2</pre>"_s
};
const QString mitLicense(QStringLiteral(R"(Expat/MIT License
Copyright (c) 2025 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.
)"));
const QStringList thirdPartyLibsStr {
u"<h1 align='center'><b>%1</b></h1>"_s.arg(tr("Third-party Libraries used by %1")),
tr("%1 is built on the following free software libraries:", "Free as in freedom"),
u"<ul>"_s,
#ifdef HAVE_EXIV2_VERSION
u"<li><a href='%1'>%2</a>: %3</li>"_s.arg("https://www.exiv2.org/", "Exiv2", "GPLv2"),
#endif // EXIV2_VERSION
u"<li><a href='%1'>%2</a>: %3</li>"_s.arg("https://www.qt.io/", "Qt", "GPLv2 + GPLv3 + LGPLv2.1 + LGPLv3"),
u"</ul>"_s
};
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(u"<i>%1</i>"_s).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);
}

View File

@ -1,36 +1,36 @@
// SPDX-FileCopyrightText: 2022 Gary Wang <wzc782970009@gmail.com>
//
// SPDX-License-Identifier: MIT
#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
// SPDX-FileCopyrightText: 2022 Gary Wang <wzc782970009@gmail.com>
//
// SPDX-License-Identifier: MIT
#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

View File

@ -1,153 +1,155 @@
// SPDX-FileCopyrightText: 2022 Gary Wang <wzc782970009@gmail.com>
//
// SPDX-License-Identifier: MIT
#include "actionmanager.h"
#include "mainwindow.h"
#include <QGuiApplication>
#include <QSvgRenderer>
#include <QPainter>
#define ICON_NAME(name)\
QStringLiteral(":/icons/" #name ".svg")
#define ACTION_NAME(s) QStringLiteral(STRIFY(s))
#define STRIFY(s) #s
QIcon ActionManager::loadHidpiIcon(const QString &resp, QSize sz)
{
QSvgRenderer r(resp);
QPixmap pm = QPixmap(sz * qApp->devicePixelRatio());
pm.fill(Qt::transparent);
QPainter p(&pm);
r.render(&p);
pm.setDevicePixelRatio(qApp->devicePixelRatio());
return QIcon(pm);
}
void ActionManager::setupAction(MainWindow *mainWindow)
{
auto create_action = [] (QWidget *w, QAction **a, QString i, QString an, bool iconFromTheme = false) {
*a = new QAction(w);
if (!i.isNull())
(*a)->setIcon(iconFromTheme ? QIcon::fromTheme(i) : ActionManager::loadHidpiIcon(i));
(*a)->setObjectName(an);
w->addAction(*a);
};
#define CREATE_NEW_ICON_ACTION(w, a, i) create_action(w, &a, ICON_NAME(i), ACTION_NAME(a))
CREATE_NEW_ICON_ACTION(mainWindow, actionActualSize, zoom-original);
CREATE_NEW_ICON_ACTION(mainWindow, actionToggleMaximize, view-fullscreen);
CREATE_NEW_ICON_ACTION(mainWindow, actionZoomIn, zoom-in);
CREATE_NEW_ICON_ACTION(mainWindow, actionZoomOut, zoom-out);
CREATE_NEW_ICON_ACTION(mainWindow, actionToggleCheckerboard, view-background-checkerboard);
CREATE_NEW_ICON_ACTION(mainWindow, actionRotateClockwise, object-rotate-right);
#undef CREATE_NEW_ICON_ACTION
#define CREATE_NEW_ACTION(w, a) create_action(w, &a, QString(), ACTION_NAME(a))
#define CREATE_NEW_THEMEICON_ACTION(w, a, i) create_action(w, &a, QLatin1String(STRIFY(i)), ACTION_NAME(a), true)
CREATE_NEW_ACTION(mainWindow, actionRotateCounterClockwise);
CREATE_NEW_ACTION(mainWindow, actionPrevPicture);
CREATE_NEW_ACTION(mainWindow, actionNextPicture);
CREATE_NEW_ACTION(mainWindow, actionTogglePauseAnimation);
CREATE_NEW_ACTION(mainWindow, actionAnimationNextFrame);
CREATE_NEW_THEMEICON_ACTION(mainWindow, actionOpen, document-open);
CREATE_NEW_ACTION(mainWindow, actionHorizontalFlip);
CREATE_NEW_ACTION(mainWindow, actionFitInView);
CREATE_NEW_ACTION(mainWindow, actionFitByWidth);
CREATE_NEW_THEMEICON_ACTION(mainWindow, actionCopyPixmap, edit-copy);
CREATE_NEW_ACTION(mainWindow, actionCopyFilePath);
CREATE_NEW_THEMEICON_ACTION(mainWindow, actionPaste, edit-paste);
CREATE_NEW_THEMEICON_ACTION(mainWindow, actionTrash, edit-delete);
CREATE_NEW_ACTION(mainWindow, actionToggleStayOnTop);
CREATE_NEW_ACTION(mainWindow, actionToggleProtectMode);
CREATE_NEW_ACTION(mainWindow, actionToggleAvoidResetTransform);
CREATE_NEW_ACTION(mainWindow, actionSettings);
CREATE_NEW_THEMEICON_ACTION(mainWindow, actionHelp, system-help);
CREATE_NEW_THEMEICON_ACTION(mainWindow, actionLocateInFileManager, system-file-manager);
CREATE_NEW_THEMEICON_ACTION(mainWindow, actionProperties, document-properties);
CREATE_NEW_ACTION(mainWindow, actionQuitApp);
#undef CREATE_NEW_ACTION
#undef CREATE_NEW_THEMEICON_ACTION
retranslateUi(mainWindow);
QMetaObject::connectSlotsByName(mainWindow);
}
void ActionManager::retranslateUi(MainWindow *mainWindow)
{
Q_UNUSED(mainWindow);
actionOpen->setText(QCoreApplication::translate("MainWindow", "&Open...", nullptr));
actionActualSize->setText(QCoreApplication::translate("MainWindow", "Actual size", nullptr));
actionToggleMaximize->setText(QCoreApplication::translate("MainWindow", "Toggle maximize", nullptr));
actionZoomIn->setText(QCoreApplication::translate("MainWindow", "Zoom in", nullptr));
actionZoomOut->setText(QCoreApplication::translate("MainWindow", "Zoom out", nullptr));
actionToggleCheckerboard->setText(QCoreApplication::translate("MainWindow", "Toggle Checkerboard", nullptr));
actionRotateClockwise->setText(QCoreApplication::translate("MainWindow", "Rotate right", nullptr));
actionRotateCounterClockwise->setText(QCoreApplication::translate("MainWindow", "Rotate left", nullptr));
actionPrevPicture->setText(QCoreApplication::translate("MainWindow", "Previous image", nullptr));
actionNextPicture->setText(QCoreApplication::translate("MainWindow", "Next image", nullptr));
actionTogglePauseAnimation->setText(QCoreApplication::translate("MainWindow", "Pause/Resume Animation", nullptr));
actionAnimationNextFrame->setText(QCoreApplication::translate("MainWindow", "Animation Go to Next Frame", nullptr));
actionHorizontalFlip->setText(QCoreApplication::translate("MainWindow", "Flip &Horizontally", nullptr));
actionFitInView->setText(QCoreApplication::translate("MainWindow", "Fit to view", nullptr));
actionFitByWidth->setText(QCoreApplication::translate("MainWindow", "Fit to width", nullptr));
actionCopyPixmap->setText(QCoreApplication::translate("MainWindow", "Copy P&ixmap", nullptr));
actionCopyFilePath->setText(QCoreApplication::translate("MainWindow", "Copy &File Path", nullptr));
actionPaste->setText(QCoreApplication::translate("MainWindow", "&Paste", nullptr));
actionTrash->setText(QCoreApplication::translate("MainWindow", "Move to Trash", nullptr));
actionToggleStayOnTop->setText(QCoreApplication::translate("MainWindow", "Stay on top", nullptr));
actionToggleProtectMode->setText(QCoreApplication::translate("MainWindow", "Protected mode", nullptr));
actionToggleAvoidResetTransform->setText(QCoreApplication::translate("MainWindow", "Keep transformation", "The 'transformation' means the flip/rotation status that currently applied to the image view"));
actionSettings->setText(QCoreApplication::translate("MainWindow", "Configure...", nullptr));
actionHelp->setText(QCoreApplication::translate("MainWindow", "Help", nullptr));
#ifdef Q_OS_WIN
actionLocateInFileManager->setText(
QCoreApplication::translate(
"MainWindow", "Show in File Explorer",
"File Explorer is the name of explorer.exe under Windows"
)
);
#else
actionLocateInFileManager->setText(QCoreApplication::translate("MainWindow", "Show in directory", nullptr));
#endif // Q_OS_WIN
actionProperties->setText(QCoreApplication::translate("MainWindow", "Properties", nullptr));
actionQuitApp->setText(QCoreApplication::translate("MainWindow", "Quit", nullptr));
}
void ActionManager::setupShortcuts()
{
actionOpen->setShortcut(QKeySequence::Open);
actionActualSize->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_0));
actionZoomIn->setShortcut(QKeySequence::ZoomIn);
actionZoomOut->setShortcut(QKeySequence::ZoomOut);
actionPrevPicture->setShortcuts({
QKeySequence(Qt::Key_PageUp),
QKeySequence(Qt::Key_Left),
});
actionNextPicture->setShortcuts({
QKeySequence(Qt::Key_PageDown),
QKeySequence(Qt::Key_Right),
});
actionHorizontalFlip->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_R));
actionCopyPixmap->setShortcut(QKeySequence::Copy);
actionPaste->setShortcut(QKeySequence::Paste);
actionTrash->setShortcut(QKeySequence::Delete);
actionHelp->setShortcut(QKeySequence::HelpContents);
actionSettings->setShortcut(QKeySequence::Preferences);
actionProperties->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_I));
actionQuitApp->setShortcuts({
QKeySequence(Qt::Key_Space),
QKeySequence(Qt::Key_Escape)
});
}
// SPDX-FileCopyrightText: 2022 Gary Wang <wzc782970009@gmail.com>
//
// SPDX-License-Identifier: MIT
#include "actionmanager.h"
#include "mainwindow.h"
#include <QGuiApplication>
#include <QSvgRenderer>
#include <QPainter>
#define ICON_NAME(name)\
QStringLiteral(":/icons/" #name ".svg")
#define ACTION_NAME(s) QStringLiteral(STRIFY(s))
#define STRIFY(s) #s
QIcon ActionManager::loadHidpiIcon(const QString &resp, QSize sz)
{
QSvgRenderer r(resp);
QPixmap pm = QPixmap(sz * qApp->devicePixelRatio());
pm.fill(Qt::transparent);
QPainter p(&pm);
r.render(&p);
pm.setDevicePixelRatio(qApp->devicePixelRatio());
return QIcon(pm);
}
void ActionManager::setupAction(MainWindow *mainWindow)
{
auto create_action = [] (QWidget *w, QAction **a, QString i, QString an, bool iconFromTheme = false) {
*a = new QAction(w);
if (!i.isNull())
(*a)->setIcon(iconFromTheme ? QIcon::fromTheme(i) : ActionManager::loadHidpiIcon(i));
(*a)->setObjectName(an);
w->addAction(*a);
};
#define CREATE_NEW_ICON_ACTION(w, a, i) create_action(w, &a, ICON_NAME(i), ACTION_NAME(a))
CREATE_NEW_ICON_ACTION(mainWindow, actionActualSize, zoom-original);
CREATE_NEW_ICON_ACTION(mainWindow, actionToggleMaximize, view-fullscreen);
CREATE_NEW_ICON_ACTION(mainWindow, actionZoomIn, zoom-in);
CREATE_NEW_ICON_ACTION(mainWindow, actionZoomOut, zoom-out);
CREATE_NEW_ICON_ACTION(mainWindow, actionToggleCheckerboard, view-background-checkerboard);
CREATE_NEW_ICON_ACTION(mainWindow, actionRotateClockwise, object-rotate-right);
#undef CREATE_NEW_ICON_ACTION
#define CREATE_NEW_ACTION(w, a) create_action(w, &a, QString(), ACTION_NAME(a))
#define CREATE_NEW_THEMEICON_ACTION(w, a, i) create_action(w, &a, QLatin1String(STRIFY(i)), ACTION_NAME(a), true)
CREATE_NEW_ACTION(mainWindow, actionRotateCounterClockwise);
CREATE_NEW_ACTION(mainWindow, actionPrevPicture);
CREATE_NEW_ACTION(mainWindow, actionNextPicture);
CREATE_NEW_ACTION(mainWindow, actionTogglePauseAnimation);
CREATE_NEW_ACTION(mainWindow, actionAnimationNextFrame);
CREATE_NEW_THEMEICON_ACTION(mainWindow, actionOpen, document-open);
CREATE_NEW_ACTION(mainWindow, actionHorizontalFlip);
CREATE_NEW_ACTION(mainWindow, actionFitInView);
CREATE_NEW_ACTION(mainWindow, actionFitByWidth);
CREATE_NEW_ACTION(mainWindow, actionFitLongImage);
CREATE_NEW_THEMEICON_ACTION(mainWindow, actionCopyPixmap, edit-copy);
CREATE_NEW_ACTION(mainWindow, actionCopyFilePath);
CREATE_NEW_THEMEICON_ACTION(mainWindow, actionPaste, edit-paste);
CREATE_NEW_THEMEICON_ACTION(mainWindow, actionTrash, edit-delete);
CREATE_NEW_ACTION(mainWindow, actionToggleStayOnTop);
CREATE_NEW_ACTION(mainWindow, actionToggleProtectMode);
CREATE_NEW_ACTION(mainWindow, actionToggleAvoidResetTransform);
CREATE_NEW_ACTION(mainWindow, actionSettings);
CREATE_NEW_THEMEICON_ACTION(mainWindow, actionHelp, system-help);
CREATE_NEW_THEMEICON_ACTION(mainWindow, actionLocateInFileManager, system-file-manager);
CREATE_NEW_THEMEICON_ACTION(mainWindow, actionProperties, document-properties);
CREATE_NEW_ACTION(mainWindow, actionQuitApp);
#undef CREATE_NEW_ACTION
#undef CREATE_NEW_THEMEICON_ACTION
retranslateUi(mainWindow);
QMetaObject::connectSlotsByName(mainWindow);
}
void ActionManager::retranslateUi(MainWindow *mainWindow)
{
Q_UNUSED(mainWindow);
actionOpen->setText(QCoreApplication::translate("MainWindow", "&Open...", nullptr));
actionActualSize->setText(QCoreApplication::translate("MainWindow", "Actual size", nullptr));
actionToggleMaximize->setText(QCoreApplication::translate("MainWindow", "Toggle maximize", nullptr));
actionZoomIn->setText(QCoreApplication::translate("MainWindow", "Zoom in", nullptr));
actionZoomOut->setText(QCoreApplication::translate("MainWindow", "Zoom out", nullptr));
actionToggleCheckerboard->setText(QCoreApplication::translate("MainWindow", "Toggle Checkerboard", nullptr));
actionRotateClockwise->setText(QCoreApplication::translate("MainWindow", "Rotate right", nullptr));
actionRotateCounterClockwise->setText(QCoreApplication::translate("MainWindow", "Rotate left", nullptr));
actionPrevPicture->setText(QCoreApplication::translate("MainWindow", "Previous image", nullptr));
actionNextPicture->setText(QCoreApplication::translate("MainWindow", "Next image", nullptr));
actionTogglePauseAnimation->setText(QCoreApplication::translate("MainWindow", "Pause/Resume Animation", nullptr));
actionAnimationNextFrame->setText(QCoreApplication::translate("MainWindow", "Animation Go to Next Frame", nullptr));
actionHorizontalFlip->setText(QCoreApplication::translate("MainWindow", "Flip &Horizontally", nullptr));
actionFitInView->setText(QCoreApplication::translate("MainWindow", "Fit to view", nullptr));
actionFitByWidth->setText(QCoreApplication::translate("MainWindow", "Fit to width", nullptr));
actionFitLongImage->setText(QCoreApplication::translate("MainWindow", "Fit long image", nullptr));
actionCopyPixmap->setText(QCoreApplication::translate("MainWindow", "Copy P&ixmap", nullptr));
actionCopyFilePath->setText(QCoreApplication::translate("MainWindow", "Copy &File Path", nullptr));
actionPaste->setText(QCoreApplication::translate("MainWindow", "&Paste", nullptr));
actionTrash->setText(QCoreApplication::translate("MainWindow", "Move to Trash", nullptr));
actionToggleStayOnTop->setText(QCoreApplication::translate("MainWindow", "Stay on top", nullptr));
actionToggleProtectMode->setText(QCoreApplication::translate("MainWindow", "Protected mode", nullptr));
actionToggleAvoidResetTransform->setText(QCoreApplication::translate("MainWindow", "Keep transformation", "The 'transformation' means the flip/rotation status that currently applied to the image view"));
actionSettings->setText(QCoreApplication::translate("MainWindow", "Configure...", nullptr));
actionHelp->setText(QCoreApplication::translate("MainWindow", "Help", nullptr));
#ifdef Q_OS_WIN
actionLocateInFileManager->setText(
QCoreApplication::translate(
"MainWindow", "Show in File Explorer",
"File Explorer is the name of explorer.exe under Windows"
)
);
#else
actionLocateInFileManager->setText(QCoreApplication::translate("MainWindow", "Show in directory", nullptr));
#endif // Q_OS_WIN
actionProperties->setText(QCoreApplication::translate("MainWindow", "Properties", nullptr));
actionQuitApp->setText(QCoreApplication::translate("MainWindow", "Quit", nullptr));
}
void ActionManager::setupShortcuts()
{
actionOpen->setShortcut(QKeySequence::Open);
actionActualSize->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_0));
actionZoomIn->setShortcut(QKeySequence::ZoomIn);
actionZoomOut->setShortcut(QKeySequence::ZoomOut);
actionPrevPicture->setShortcuts({
QKeySequence(Qt::Key_PageUp),
QKeySequence(Qt::Key_Left),
});
actionNextPicture->setShortcuts({
QKeySequence(Qt::Key_PageDown),
QKeySequence(Qt::Key_Right),
});
actionHorizontalFlip->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_R));
actionCopyPixmap->setShortcut(QKeySequence::Copy);
actionPaste->setShortcut(QKeySequence::Paste);
actionTrash->setShortcut(QKeySequence::Delete);
actionHelp->setShortcut(QKeySequence::HelpContents);
actionSettings->setShortcut(QKeySequence::Preferences);
actionProperties->setShortcut(QKeySequence(Qt::CTRL | Qt::Key_I));
actionQuitApp->setShortcuts({
QKeySequence(Qt::Key_Space),
QKeySequence(Qt::Key_Escape)
});
}

View File

@ -1,58 +1,59 @@
// SPDX-FileCopyrightText: 2025 Gary Wang <git@blumia.net>
//
// SPDX-License-Identifier: MIT
#ifndef ACTIONMANAGER_H
#define ACTIONMANAGER_H
#include <QAction>
class MainWindow;
class ActionManager
{
public:
explicit ActionManager() = default;
~ActionManager() = default;
void setupAction(MainWindow * mainWindow);
void retranslateUi(MainWindow *MainWindow);
void setupShortcuts();
static QIcon loadHidpiIcon(const QString &resp, QSize sz = QSize(32, 32));
public:
QAction *actionOpen;
QAction *actionActualSize;
QAction *actionToggleMaximize;
QAction *actionZoomIn;
QAction *actionZoomOut;
QAction *actionToggleCheckerboard;
QAction *actionRotateClockwise;
QAction *actionRotateCounterClockwise;
QAction *actionPrevPicture;
QAction *actionNextPicture;
QAction *actionTogglePauseAnimation;
QAction *actionAnimationNextFrame;
QAction *actionHorizontalFlip;
QAction *actionFitInView;
QAction *actionFitByWidth;
QAction *actionCopyPixmap;
QAction *actionCopyFilePath;
QAction *actionPaste;
QAction *actionTrash;
QAction *actionToggleStayOnTop;
QAction *actionToggleProtectMode;
QAction *actionToggleAvoidResetTransform;
QAction *actionSettings;
QAction *actionHelp;
QAction *actionLocateInFileManager;
QAction *actionProperties;
QAction *actionQuitApp;
};
#endif // ACTIONMANAGER_H
// SPDX-FileCopyrightText: 2025 Gary Wang <git@blumia.net>
//
// SPDX-License-Identifier: MIT
#ifndef ACTIONMANAGER_H
#define ACTIONMANAGER_H
#include <QAction>
class MainWindow;
class ActionManager
{
public:
explicit ActionManager() = default;
~ActionManager() = default;
void setupAction(MainWindow * mainWindow);
void retranslateUi(MainWindow *MainWindow);
void setupShortcuts();
static QIcon loadHidpiIcon(const QString &resp, QSize sz = QSize(32, 32));
public:
QAction *actionOpen;
QAction *actionActualSize;
QAction *actionToggleMaximize;
QAction *actionZoomIn;
QAction *actionZoomOut;
QAction *actionToggleCheckerboard;
QAction *actionRotateClockwise;
QAction *actionRotateCounterClockwise;
QAction *actionPrevPicture;
QAction *actionNextPicture;
QAction *actionTogglePauseAnimation;
QAction *actionAnimationNextFrame;
QAction *actionHorizontalFlip;
QAction *actionFitInView;
QAction *actionFitByWidth;
QAction *actionFitLongImage;
QAction *actionCopyPixmap;
QAction *actionCopyFilePath;
QAction *actionPaste;
QAction *actionTrash;
QAction *actionToggleStayOnTop;
QAction *actionToggleProtectMode;
QAction *actionToggleAvoidResetTransform;
QAction *actionSettings;
QAction *actionHelp;
QAction *actionLocateInFileManager;
QAction *actionProperties;
QAction *actionQuitApp;
};
#endif // ACTIONMANAGER_H

View File

@ -1,57 +1,57 @@
// SPDX-FileCopyrightText: 2022 Gary Wang <wzc782970009@gmail.com>
//
// SPDX-License-Identifier: MIT
#include "bottombuttongroup.h"
#include "opacityhelper.h"
#include <QToolButton>
#include <QVBoxLayout>
#include <QDebug>
BottomButtonGroup::BottomButtonGroup(const std::vector<QAction *> &actionList, QWidget *parent)
: QGroupBox (parent)
, m_opacityHelper(new OpacityHelper(this))
{
QHBoxLayout * mainLayout = new QHBoxLayout(this);
mainLayout->setSizeConstraint(QLayout::SetFixedSize);
this->setLayout(mainLayout);
this->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
this->setStyleSheet("BottomButtonGroup {"
"border: 1px solid gray;"
"border-top-left-radius: 10px;"
"border-top-right-radius: 10px;"
"border-style: none;"
"background-color:rgba(0,0,0,120)"
"}"
"QToolButton {"
"background:transparent;"
"}"
"QToolButton:!focus {"
"border-style: none;"
"}");
auto newActionBtn = [this](QAction * action) -> QToolButton * {
QToolButton * btn = new QToolButton(this);
btn->setDefaultAction(action);
btn->setIconSize(QSize(32, 32));
btn->setFixedSize(40, 40);
return btn;
};
for (QAction * action : actionList) {
addButton(newActionBtn(action));
}
}
void BottomButtonGroup::setOpacity(qreal opacity, bool animated)
{
m_opacityHelper->setOpacity(opacity, animated);
}
void BottomButtonGroup::addButton(QAbstractButton *button)
{
layout()->addWidget(button);
updateGeometry();
}
// SPDX-FileCopyrightText: 2022 Gary Wang <wzc782970009@gmail.com>
//
// SPDX-License-Identifier: MIT
#include "bottombuttongroup.h"
#include "opacityhelper.h"
#include <QToolButton>
#include <QVBoxLayout>
#include <QDebug>
BottomButtonGroup::BottomButtonGroup(const std::vector<QAction *> &actionList, QWidget *parent)
: QGroupBox (parent)
, m_opacityHelper(new OpacityHelper(this))
{
QHBoxLayout * mainLayout = new QHBoxLayout(this);
mainLayout->setSizeConstraint(QLayout::SetFixedSize);
this->setLayout(mainLayout);
this->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
this->setStyleSheet("BottomButtonGroup {"
"border: 1px solid gray;"
"border-top-left-radius: 10px;"
"border-top-right-radius: 10px;"
"border-style: none;"
"background-color:rgba(0,0,0,120)"
"}"
"QToolButton {"
"background:transparent;"
"}"
"QToolButton:!focus {"
"border-style: none;"
"}");
auto newActionBtn = [this](QAction * action) -> QToolButton * {
QToolButton * btn = new QToolButton(this);
btn->setDefaultAction(action);
btn->setIconSize(QSize(32, 32));
btn->setFixedSize(40, 40);
return btn;
};
for (QAction * action : actionList) {
addButton(newActionBtn(action));
}
}
void BottomButtonGroup::setOpacity(qreal opacity, bool animated)
{
m_opacityHelper->setOpacity(opacity, animated);
}
void BottomButtonGroup::addButton(QAbstractButton *button)
{
layout()->addWidget(button);
updateGeometry();
}

View File

@ -1,27 +1,27 @@
// SPDX-FileCopyrightText: 2022 Gary Wang <wzc782970009@gmail.com>
//
// SPDX-License-Identifier: MIT
#ifndef BOTTOMBUTTONGROUP_H
#define BOTTOMBUTTONGROUP_H
#include <vector>
#include <QAbstractButton>
#include <QGroupBox>
class OpacityHelper;
class BottomButtonGroup : public QGroupBox
{
Q_OBJECT
public:
explicit BottomButtonGroup(const std::vector<QAction *> & actionList, QWidget *parent = nullptr);
void setOpacity(qreal opacity, bool animated = true);
void addButton(QAbstractButton *button);
private:
OpacityHelper * m_opacityHelper;
};
#endif // BOTTOMBUTTONGROUP_H
// SPDX-FileCopyrightText: 2022 Gary Wang <wzc782970009@gmail.com>
//
// SPDX-License-Identifier: MIT
#ifndef BOTTOMBUTTONGROUP_H
#define BOTTOMBUTTONGROUP_H
#include <vector>
#include <QAbstractButton>
#include <QGroupBox>
class OpacityHelper;
class BottomButtonGroup : public QGroupBox
{
Q_OBJECT
public:
explicit BottomButtonGroup(const std::vector<QAction *> & actionList, QWidget *parent = nullptr);
void setOpacity(qreal opacity, bool animated = true);
void addButton(QAbstractButton *button);
private:
OpacityHelper * m_opacityHelper;
};
#endif // BOTTOMBUTTONGROUP_H

View File

@ -1,138 +1,138 @@
// SPDX-FileCopyrightText: 2022 Gary Wang <wzc782970009@gmail.com>
//
// SPDX-License-Identifier: MIT
#include "exiv2wrapper.h"
#ifdef HAVE_EXIV2_VERSION
#include <exiv2/exiv2.hpp>
#else // HAVE_EXIV2_VERSION
namespace Exiv2 {
class Image {};
}
#endif // HAVE_EXIV2_VERSION
#include <sstream>
#include <QFile>
#include <QDebug>
Exiv2Wrapper::Exiv2Wrapper()
{
}
Exiv2Wrapper::~Exiv2Wrapper()
{
}
#ifdef HAVE_EXIV2_VERSION // stupid AppleClang...
template<typename Collection, typename Iterator>
void Exiv2Wrapper::cacheSection(Collection collection)
{
const Collection& exifData = collection;
Iterator it = exifData.begin(), end = exifData.end();
for (; it != end; ++it) {
QString key = QString::fromUtf8(it->key().c_str());
if (it->tagName().substr(0, 2) == "0x") continue;
// We might get exceptions like "No namespace info available for XMP prefix `Item'"
// when trying to get tagLabel() data from a Xmpdatum if the tag is not common-used.
// We don't care for those rare tags so let's just use a try-cache...
try {
QString label = QString::fromLocal8Bit(it->tagLabel().c_str());
std::ostringstream stream;
stream << *it;
QString value = QString::fromUtf8(stream.str().c_str());
m_metadataValue.insert(key, value);
m_metadataLabel.insert(key, label);
qDebug() << key << label << value;
#if EXIV2_TEST_VERSION(0, 28, 0)
} catch (Exiv2::Error & err) {
#else // 0.27.x
} catch (Exiv2::AnyError & err) {
#endif // EXIV2_TEST_VERSION(0, 28, 0)
qWarning() << "Error loading key" << key << ":" << err.what();
}
}
}
#endif // HAVE_EXIV2_VERSION
bool Exiv2Wrapper::load(const QString &filePath)
{
#ifdef HAVE_EXIV2_VERSION
QByteArray filePathByteArray = QFile::encodeName(filePath);
try {
m_exivImage.reset(Exiv2::ImageFactory::open(filePathByteArray.constData()).release());
m_exivImage->readMetadata();
} catch (const Exiv2::Error& error) {
m_errMsg = QString::fromUtf8(error.what());
return false;
}
return true;
#else // HAVE_EXIV2_VERSION
Q_UNUSED(filePath);
return false;
#endif // HAVE_EXIV2_VERSION
}
void Exiv2Wrapper::cacheSections()
{
#ifdef HAVE_EXIV2_VERSION
if (m_exivImage->checkMode(Exiv2::mdExif) & Exiv2::amRead) {
cacheSection<Exiv2::ExifData, Exiv2::ExifData::const_iterator>(m_exivImage->exifData());
}
if (m_exivImage->checkMode(Exiv2::mdIptc) & Exiv2::amRead) {
cacheSection<Exiv2::IptcData, Exiv2::IptcData::const_iterator>(m_exivImage->iptcData());
}
if (m_exivImage->checkMode(Exiv2::mdXmp) & Exiv2::amRead) {
cacheSection<Exiv2::XmpData, Exiv2::XmpData::const_iterator>(m_exivImage->xmpData());
}
// qDebug() << m_metadataValue;
// qDebug() << m_metadataLabel;
#endif // HAVE_EXIV2_VERSION
}
QString Exiv2Wrapper::comment() const
{
#ifdef HAVE_EXIV2_VERSION
return m_exivImage->comment().c_str();
#else // HAVE_EXIV2_VERSION
return QString();
#endif // HAVE_EXIV2_VERSION
}
QString Exiv2Wrapper::label(const QString &key) const
{
return m_metadataLabel.value(key);
}
QString Exiv2Wrapper::value(const QString &key) const
{
return m_metadataValue.value(key);
}
QString Exiv2Wrapper::XmpValue(const QString &rawValue)
{
QString ignored;
return Exiv2Wrapper::XmpValue(rawValue, ignored);
}
QString Exiv2Wrapper::XmpValue(const QString &rawValue, QString &language)
{
if (rawValue.size() > 6 && rawValue.startsWith(QLatin1String("lang=\""))) {
int pos = rawValue.indexOf('"', 6);
if (pos != -1) {
language = rawValue.mid(6, pos - 6);
return (rawValue.mid(pos + 2));
}
}
language.clear();
return rawValue;
}
// SPDX-FileCopyrightText: 2022 Gary Wang <wzc782970009@gmail.com>
//
// SPDX-License-Identifier: MIT
#include "exiv2wrapper.h"
#ifdef HAVE_EXIV2_VERSION
#include <exiv2/exiv2.hpp>
#else // HAVE_EXIV2_VERSION
namespace Exiv2 {
class Image {};
}
#endif // HAVE_EXIV2_VERSION
#include <sstream>
#include <QFile>
#include <QDebug>
Exiv2Wrapper::Exiv2Wrapper()
{
}
Exiv2Wrapper::~Exiv2Wrapper()
{
}
#ifdef HAVE_EXIV2_VERSION // stupid AppleClang...
template<typename Collection, typename Iterator>
void Exiv2Wrapper::cacheSection(Collection collection)
{
const Collection& exifData = collection;
Iterator it = exifData.begin(), end = exifData.end();
for (; it != end; ++it) {
QString key = QString::fromUtf8(it->key().c_str());
if (it->tagName().substr(0, 2) == "0x") continue;
// We might get exceptions like "No namespace info available for XMP prefix `Item'"
// when trying to get tagLabel() data from a Xmpdatum if the tag is not common-used.
// We don't care for those rare tags so let's just use a try-cache...
try {
QString label = QString::fromLocal8Bit(it->tagLabel().c_str());
std::ostringstream stream;
stream << *it;
QString value = QString::fromUtf8(stream.str().c_str());
m_metadataValue.insert(key, value);
m_metadataLabel.insert(key, label);
qDebug() << key << label << value;
#if EXIV2_TEST_VERSION(0, 28, 0)
} catch (Exiv2::Error & err) {
#else // 0.27.x
} catch (Exiv2::AnyError & err) {
#endif // EXIV2_TEST_VERSION(0, 28, 0)
qWarning() << "Error loading key" << key << ":" << err.what();
}
}
}
#endif // HAVE_EXIV2_VERSION
bool Exiv2Wrapper::load(const QString &filePath)
{
#ifdef HAVE_EXIV2_VERSION
QByteArray filePathByteArray = QFile::encodeName(filePath);
try {
m_exivImage.reset(Exiv2::ImageFactory::open(filePathByteArray.constData()).release());
m_exivImage->readMetadata();
} catch (const Exiv2::Error& error) {
m_errMsg = QString::fromUtf8(error.what());
return false;
}
return true;
#else // HAVE_EXIV2_VERSION
Q_UNUSED(filePath);
return false;
#endif // HAVE_EXIV2_VERSION
}
void Exiv2Wrapper::cacheSections()
{
#ifdef HAVE_EXIV2_VERSION
if (m_exivImage->checkMode(Exiv2::mdExif) & Exiv2::amRead) {
cacheSection<Exiv2::ExifData, Exiv2::ExifData::const_iterator>(m_exivImage->exifData());
}
if (m_exivImage->checkMode(Exiv2::mdIptc) & Exiv2::amRead) {
cacheSection<Exiv2::IptcData, Exiv2::IptcData::const_iterator>(m_exivImage->iptcData());
}
if (m_exivImage->checkMode(Exiv2::mdXmp) & Exiv2::amRead) {
cacheSection<Exiv2::XmpData, Exiv2::XmpData::const_iterator>(m_exivImage->xmpData());
}
// qDebug() << m_metadataValue;
// qDebug() << m_metadataLabel;
#endif // HAVE_EXIV2_VERSION
}
QString Exiv2Wrapper::comment() const
{
#ifdef HAVE_EXIV2_VERSION
return m_exivImage->comment().c_str();
#else // HAVE_EXIV2_VERSION
return QString();
#endif // HAVE_EXIV2_VERSION
}
QString Exiv2Wrapper::label(const QString &key) const
{
return m_metadataLabel.value(key);
}
QString Exiv2Wrapper::value(const QString &key) const
{
return m_metadataValue.value(key);
}
QString Exiv2Wrapper::XmpValue(const QString &rawValue)
{
QString ignored;
return Exiv2Wrapper::XmpValue(rawValue, ignored);
}
QString Exiv2Wrapper::XmpValue(const QString &rawValue, QString &language)
{
if (rawValue.size() > 6 && rawValue.startsWith(QLatin1String("lang=\""))) {
int pos = rawValue.indexOf('"', 6);
if (pos != -1) {
language = rawValue.mid(6, pos - 6);
return (rawValue.mid(pos + 2));
}
}
language.clear();
return rawValue;
}

View File

@ -1,43 +1,43 @@
// SPDX-FileCopyrightText: 2022 Gary Wang <wzc782970009@gmail.com>
//
// SPDX-License-Identifier: MIT
#ifndef EXIV2WRAPPER_H
#define EXIV2WRAPPER_H
#include <memory>
#include <QString>
#include <QMap>
namespace Exiv2 {
class Image;
}
class Exiv2Wrapper
{
public:
Exiv2Wrapper();
~Exiv2Wrapper();
bool load(const QString& filePath);
void cacheSections();
QString comment() const;
QString label(const QString & key) const;
QString value(const QString & key) const;
static QString XmpValue(const QString &rawValue);
static QString XmpValue(const QString &rawValue, QString & language);
private:
std::unique_ptr<Exiv2::Image> m_exivImage;
QMap<QString, QString> m_metadataValue;
QMap<QString, QString> m_metadataLabel;
QString m_errMsg;
template<typename Collection, typename Iterator>
void cacheSection(Collection collection);
};
#endif // EXIV2WRAPPER_H
// SPDX-FileCopyrightText: 2022 Gary Wang <wzc782970009@gmail.com>
//
// SPDX-License-Identifier: MIT
#ifndef EXIV2WRAPPER_H
#define EXIV2WRAPPER_H
#include <memory>
#include <QString>
#include <QMap>
namespace Exiv2 {
class Image;
}
class Exiv2Wrapper
{
public:
Exiv2Wrapper();
~Exiv2Wrapper();
bool load(const QString& filePath);
void cacheSections();
QString comment() const;
QString label(const QString & key) const;
QString value(const QString & key) const;
static QString XmpValue(const QString &rawValue);
static QString XmpValue(const QString &rawValue, QString & language);
private:
std::unique_ptr<Exiv2::Image> m_exivImage;
QMap<QString, QString> m_metadataValue;
QMap<QString, QString> m_metadataLabel;
QString m_errMsg;
template<typename Collection, typename Iterator>
void cacheSection(Collection collection);
};
#endif // EXIV2WRAPPER_H

View File

@ -1,136 +1,136 @@
// SPDX-FileCopyrightText: 2022 Gary Wang <wzc782970009@gmail.com>
// SPDX-FileCopyrightText: 2023 Tad Young <yyc12321@outlook.com>
//
// SPDX-License-Identifier: MIT
#include "framelesswindow.h"
#include <QMouseEvent>
#include <QHoverEvent>
#include <QApplication>
#include <QVBoxLayout>
#include <QWindow>
FramelessWindow::FramelessWindow(QWidget *parent)
: QWidget(parent)
, m_centralLayout(new QVBoxLayout(this))
, m_oldCursorShape(Qt::ArrowCursor)
, m_oldEdges()
{
this->setWindowFlags(Qt::Window | Qt::FramelessWindowHint | Qt::WindowMinMaxButtonsHint);
this->setMouseTracking(true);
this->setAttribute(Qt::WA_Hover, true);
this->installEventFilter(this);
m_centralLayout->setContentsMargins(QMargins());
}
void FramelessWindow::setCentralWidget(QWidget *widget)
{
if (m_centralWidget) {
m_centralLayout->removeWidget(m_centralWidget);
m_centralWidget->deleteLater();
}
m_centralLayout->addWidget(widget);
m_centralWidget = widget;
}
void FramelessWindow::installResizeCapture(QObject* widget)
{
widget->installEventFilter(this);
}
bool FramelessWindow::eventFilter(QObject* o, QEvent* e)
{
switch (e->type()) {
case QEvent::HoverMove:
{
QWidget* wg = qobject_cast<QWidget*>(o);
if (wg != nullptr)
return mouseHover(static_cast<QHoverEvent*>(e), wg);
break;
}
case QEvent::MouseButtonPress:
return mousePress(static_cast<QMouseEvent*>(e));
}
return QWidget::eventFilter(o, e);
}
bool FramelessWindow::mouseHover(QHoverEvent* event, QWidget* wg)
{
if (!isMaximized() && !isFullScreen()) {
QWindow* win = window()->windowHandle();
Qt::Edges edges = this->getEdgesByPos(wg->mapToGlobal(event->oldPos()), win->frameGeometry());
// backup & restore cursor shape
if (edges && !m_oldEdges)
// entering the edge. backup cursor shape
m_oldCursorShape = win->cursor().shape();
if (!edges && m_oldEdges)
// leaving the edge. restore cursor shape
win->setCursor(m_oldCursorShape);
// save the latest edges status
m_oldEdges = edges;
// show resize cursor shape if cursor is within border
if (edges) {
win->setCursor(this->getCursorByEdge(edges, Qt::ArrowCursor));
return true;
}
}
return false;
}
bool FramelessWindow::mousePress(QMouseEvent* event)
{
if (event->buttons() & Qt::LeftButton && !isMaximized() && !isFullScreen()) {
QWindow* win = window()->windowHandle();
Qt::Edges edges = this->getEdgesByPos(event->globalPosition().toPoint(), win->frameGeometry());
if (edges) {
win->startSystemResize(edges);
return true;
}
}
return false;
}
Qt::CursorShape FramelessWindow::getCursorByEdge(const Qt::Edges& edges, Qt::CursorShape default_cursor)
{
if ((edges == (Qt::TopEdge | Qt::LeftEdge)) || (edges == (Qt::RightEdge | Qt::BottomEdge)))
return Qt::SizeFDiagCursor;
else if ((edges == (Qt::TopEdge | Qt::RightEdge)) || (edges == (Qt::LeftEdge | Qt::BottomEdge)))
return Qt::SizeBDiagCursor;
else if (edges & (Qt::TopEdge | Qt::BottomEdge))
return Qt::SizeVerCursor;
else if (edges & (Qt::LeftEdge | Qt::RightEdge))
return Qt::SizeHorCursor;
else
return default_cursor;
}
Qt::Edges FramelessWindow::getEdgesByPos(const QPoint gpos, const QRect& winrect)
{
const int borderWidth = 8;
Qt::Edges edges;
int x = gpos.x() - winrect.x();
int y = gpos.y() - winrect.y();
if (x < borderWidth)
edges |= Qt::LeftEdge;
if (x > (winrect.width() - borderWidth))
edges |= Qt::RightEdge;
if (y < borderWidth)
edges |= Qt::TopEdge;
if (y > (winrect.height() - borderWidth))
edges |= Qt::BottomEdge;
return edges;
}
// SPDX-FileCopyrightText: 2022 Gary Wang <wzc782970009@gmail.com>
// SPDX-FileCopyrightText: 2023 Tad Young <yyc12321@outlook.com>
//
// SPDX-License-Identifier: MIT
#include "framelesswindow.h"
#include <QMouseEvent>
#include <QHoverEvent>
#include <QApplication>
#include <QVBoxLayout>
#include <QWindow>
FramelessWindow::FramelessWindow(QWidget *parent)
: QWidget(parent)
, m_centralLayout(new QVBoxLayout(this))
, m_oldCursorShape(Qt::ArrowCursor)
, m_oldEdges()
{
this->setWindowFlags(Qt::Window | Qt::FramelessWindowHint | Qt::WindowMinMaxButtonsHint);
this->setMouseTracking(true);
this->setAttribute(Qt::WA_Hover, true);
this->installEventFilter(this);
m_centralLayout->setContentsMargins(QMargins());
}
void FramelessWindow::setCentralWidget(QWidget *widget)
{
if (m_centralWidget) {
m_centralLayout->removeWidget(m_centralWidget);
m_centralWidget->deleteLater();
}
m_centralLayout->addWidget(widget);
m_centralWidget = widget;
}
void FramelessWindow::installResizeCapture(QObject* widget)
{
widget->installEventFilter(this);
}
bool FramelessWindow::eventFilter(QObject* o, QEvent* e)
{
switch (e->type()) {
case QEvent::HoverMove:
{
QWidget* wg = qobject_cast<QWidget*>(o);
if (wg != nullptr)
return mouseHover(static_cast<QHoverEvent*>(e), wg);
break;
}
case QEvent::MouseButtonPress:
return mousePress(static_cast<QMouseEvent*>(e));
}
return QWidget::eventFilter(o, e);
}
bool FramelessWindow::mouseHover(QHoverEvent* event, QWidget* wg)
{
if (!isMaximized() && !isFullScreen()) {
QWindow* win = window()->windowHandle();
Qt::Edges edges = this->getEdgesByPos(wg->mapToGlobal(event->oldPos()), win->frameGeometry());
// backup & restore cursor shape
if (edges && !m_oldEdges)
// entering the edge. backup cursor shape
m_oldCursorShape = win->cursor().shape();
if (!edges && m_oldEdges)
// leaving the edge. restore cursor shape
win->setCursor(m_oldCursorShape);
// save the latest edges status
m_oldEdges = edges;
// show resize cursor shape if cursor is within border
if (edges) {
win->setCursor(this->getCursorByEdge(edges, Qt::ArrowCursor));
return true;
}
}
return false;
}
bool FramelessWindow::mousePress(QMouseEvent* event)
{
if (event->buttons() & Qt::LeftButton && !isMaximized() && !isFullScreen()) {
QWindow* win = window()->windowHandle();
Qt::Edges edges = this->getEdgesByPos(event->globalPosition().toPoint(), win->frameGeometry());
if (edges) {
win->startSystemResize(edges);
return true;
}
}
return false;
}
Qt::CursorShape FramelessWindow::getCursorByEdge(const Qt::Edges& edges, Qt::CursorShape default_cursor)
{
if ((edges == (Qt::TopEdge | Qt::LeftEdge)) || (edges == (Qt::RightEdge | Qt::BottomEdge)))
return Qt::SizeFDiagCursor;
else if ((edges == (Qt::TopEdge | Qt::RightEdge)) || (edges == (Qt::LeftEdge | Qt::BottomEdge)))
return Qt::SizeBDiagCursor;
else if (edges & (Qt::TopEdge | Qt::BottomEdge))
return Qt::SizeVerCursor;
else if (edges & (Qt::LeftEdge | Qt::RightEdge))
return Qt::SizeHorCursor;
else
return default_cursor;
}
Qt::Edges FramelessWindow::getEdgesByPos(const QPoint gpos, const QRect& winrect)
{
const int borderWidth = 8;
Qt::Edges edges;
int x = gpos.x() - winrect.x();
int y = gpos.y() - winrect.y();
if (x < borderWidth)
edges |= Qt::LeftEdge;
if (x > (winrect.width() - borderWidth))
edges |= Qt::RightEdge;
if (y < borderWidth)
edges |= Qt::TopEdge;
if (y > (winrect.height() - borderWidth))
edges |= Qt::BottomEdge;
return edges;
}

View File

@ -1,39 +1,39 @@
// SPDX-FileCopyrightText: 2022 Gary Wang <wzc782970009@gmail.com>
//
// SPDX-License-Identifier: MIT
#ifndef FRAMELESSWINDOW_H
#define FRAMELESSWINDOW_H
#include <QWidget>
QT_BEGIN_NAMESPACE
class QVBoxLayout;
QT_END_NAMESPACE
class FramelessWindow : public QWidget
{
Q_OBJECT
public:
explicit FramelessWindow(QWidget *parent = nullptr);
void setCentralWidget(QWidget * widget);
void installResizeCapture(QObject* widget);
protected:
bool eventFilter(QObject *o, QEvent *e) override;
bool mouseHover(QHoverEvent* event, QWidget* wg);
bool mousePress(QMouseEvent* event);
private:
Qt::Edges m_oldEdges;
Qt::CursorShape m_oldCursorShape;
Qt::CursorShape getCursorByEdge(const Qt::Edges& edges, Qt::CursorShape default_cursor);
Qt::Edges getEdgesByPos(const QPoint pos, const QRect& winrect);
QVBoxLayout * m_centralLayout = nullptr;
QWidget * m_centralWidget = nullptr; // just a pointer, doesn't take the ownership.
};
#endif // FRAMELESSWINDOW_H
// SPDX-FileCopyrightText: 2022 Gary Wang <wzc782970009@gmail.com>
//
// SPDX-License-Identifier: MIT
#ifndef FRAMELESSWINDOW_H
#define FRAMELESSWINDOW_H
#include <QWidget>
QT_BEGIN_NAMESPACE
class QVBoxLayout;
QT_END_NAMESPACE
class FramelessWindow : public QWidget
{
Q_OBJECT
public:
explicit FramelessWindow(QWidget *parent = nullptr);
void setCentralWidget(QWidget * widget);
void installResizeCapture(QObject* widget);
protected:
bool eventFilter(QObject *o, QEvent *e) override;
bool mouseHover(QHoverEvent* event, QWidget* wg);
bool mousePress(QMouseEvent* event);
private:
Qt::Edges m_oldEdges;
Qt::CursorShape m_oldCursorShape;
Qt::CursorShape getCursorByEdge(const Qt::Edges& edges, Qt::CursorShape default_cursor);
Qt::Edges getEdgesByPos(const QPoint pos, const QRect& winrect);
QVBoxLayout * m_centralLayout = nullptr;
QWidget * m_centralWidget = nullptr; // just a pointer, doesn't take the ownership.
};
#endif // FRAMELESSWINDOW_H

View File

@ -1,371 +1,495 @@
// SPDX-FileCopyrightText: 2022 Gary Wang <wzc782970009@gmail.com>
//
// SPDX-License-Identifier: MIT
#include "graphicsview.h"
#include "graphicsscene.h"
#include "settings.h"
#include <QDebug>
#include <QMouseEvent>
#include <QScrollBar>
#include <QMimeData>
#include <QImageReader>
#include <QStyleOptionGraphicsItem>
GraphicsView::GraphicsView(QWidget *parent)
: QGraphicsView (parent)
{
setDragMode(QGraphicsView::ScrollHandDrag);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setResizeAnchor(QGraphicsView::AnchorUnderMouse);
setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
setStyleSheet("background-color: rgba(0, 0, 0, 220);"
"border-radius: 3px;");
setAcceptDrops(false);
setCheckerboardEnabled(false);
connect(horizontalScrollBar(), &QScrollBar::valueChanged, this, &GraphicsView::viewportRectChanged);
connect(verticalScrollBar(), &QScrollBar::valueChanged, this, &GraphicsView::viewportRectChanged);
}
void GraphicsView::showFileFromPath(const QString &filePath)
{
emit navigatorViewRequired(false, transform());
if (filePath.endsWith(".svg")) {
showSvg(filePath);
} else {
QImageReader imageReader(filePath);
imageReader.setAutoTransform(true);
imageReader.setDecideFormatFromContent(true);
imageReader.setAllocationLimit(0);
// Since if the image format / plugin does not support this feature, imageFormat() will returns an invalid format.
// So we cannot use imageFormat() and check if it returns QImage::Format_Invalid to detect if we support the file.
// QImage::Format imageFormat = imageReader.imageFormat();
if (imageReader.format().isEmpty()) {
showText(tr("File is not a valid image"));
} else if (imageReader.supportsAnimation() && imageReader.imageCount() > 1) {
showAnimated(filePath);
} else if (!imageReader.canRead()) {
showText(tr("Image data is invalid or currently unsupported"));
} else {
QPixmap && pixmap = QPixmap::fromImageReader(&imageReader);
if (pixmap.isNull()) {
showText(tr("Image data is invalid or currently unsupported"));
} else {
pixmap.setDevicePixelRatio(devicePixelRatioF());
showImage(pixmap);
}
}
}
}
void GraphicsView::showImage(const QPixmap &pixmap)
{
resetTransform();
scene()->showImage(pixmap);
displayScene();
}
void GraphicsView::showImage(const QImage &image)
{
resetTransform();
scene()->showImage(QPixmap::fromImage(image));
displayScene();
}
void GraphicsView::showText(const QString &text)
{
resetTransform();
scene()->showText(text);
displayScene();
}
void GraphicsView::showSvg(const QString &filepath)
{
resetTransform();
scene()->showSvg(filepath);
displayScene();
}
void GraphicsView::showAnimated(const QString &filepath)
{
resetTransform();
scene()->showAnimated(filepath);
displayScene();
}
GraphicsScene *GraphicsView::scene() const
{
return qobject_cast<GraphicsScene*>(QGraphicsView::scene());
}
void GraphicsView::setScene(GraphicsScene *scene)
{
return QGraphicsView::setScene(scene);
}
qreal GraphicsView::scaleFactor() const
{
return QStyleOptionGraphicsItem::levelOfDetailFromTransform(transform());
}
void GraphicsView::resetTransform()
{
if (!shouldAvoidTransform()) {
QGraphicsView::resetTransform();
}
}
void GraphicsView::zoomView(qreal scaleFactor)
{
m_enableFitInView = false;
scale(scaleFactor, scaleFactor);
applyTransformationModeByScaleFactor();
emit navigatorViewRequired(!isThingSmallerThanWindowWith(transform()), transform());
}
// This is always according to user's view.
// the direction of the rotation will NOT be clockwise because the y-axis points downwards.
void GraphicsView::rotateView(bool clockwise)
{
resetScale();
QTransform tf(0, clockwise ? 1 : -1, 0,
clockwise ? -1 : 1, 0, 0,
0, 0, 1);
tf = transform() * tf;
setTransform(tf);
}
void GraphicsView::flipView(bool horizontal)
{
QTransform tf(horizontal ? -1 : 1, 0, 0,
0, horizontal ? 1 : -1, 0,
0, 0, 1);
tf = transform() * tf;
setTransform(tf);
// Ensure the navigation view is also flipped.
emit navigatorViewRequired(!isThingSmallerThanWindowWith(transform()), transform());
}
void GraphicsView::resetScale()
{
setTransform(resetScale(transform()));
applyTransformationModeByScaleFactor();
emit navigatorViewRequired(!isThingSmallerThanWindowWith(transform()), transform());
}
void GraphicsView::fitInView(const QRectF &rect, Qt::AspectRatioMode aspectRadioMode)
{
QGraphicsView::fitInView(rect, aspectRadioMode);
applyTransformationModeByScaleFactor();
}
void GraphicsView::fitByOrientation(Qt::Orientation ori, bool scaleDownOnly)
{
resetScale();
QRectF viewRect = this->viewport()->rect().adjusted(2, 2, -2, -2);
QRectF imageRect = transform().mapRect(sceneRect());
qreal ratio;
if (ori == Qt::Horizontal) {
ratio = viewRect.width() / imageRect.width();
} else {
ratio = viewRect.height() / imageRect.height();
}
if (scaleDownOnly && ratio > 1) ratio = 1;
scale(ratio, ratio);
centerOn(imageRect.top(), 0);
m_enableFitInView = false;
applyTransformationModeByScaleFactor();
emit navigatorViewRequired(!isThingSmallerThanWindowWith(transform()), transform());
}
void GraphicsView::displayScene()
{
if (shouldAvoidTransform()) {
emit navigatorViewRequired(!isThingSmallerThanWindowWith(transform()), transform());
return;
}
if (isSceneBiggerThanView()) {
fitInView(sceneRect(), Qt::KeepAspectRatio);
}
m_enableFitInView = true;
m_firstUserMediaLoaded = true;
}
bool GraphicsView::isSceneBiggerThanView() const
{
if (!isThingSmallerThanWindowWith(transform())) {
return true;
} else {
return false;
}
}
// Automately do fit in view when viewport(window) smaller than image original size.
void GraphicsView::setEnableAutoFitInView(bool enable)
{
m_enableFitInView = enable;
}
bool GraphicsView::avoidResetTransform() const
{
return m_avoidResetTransform;
}
void GraphicsView::setAvoidResetTransform(bool avoidReset)
{
m_avoidResetTransform = avoidReset;
}
inline double zeroOrOne(double number)
{
return qFuzzyIsNull(number) ? 0 : (number > 0 ? 1 : -1);
}
// Note: this only works if we only have 90 degree based rotation
// and no shear/translate.
QTransform GraphicsView::resetScale(const QTransform & orig)
{
return QTransform(zeroOrOne(orig.m11()), zeroOrOne(orig.m12()),
zeroOrOne(orig.m21()), zeroOrOne(orig.m22()),
orig.dx(), orig.dy());
}
void GraphicsView::toggleCheckerboard(bool invertCheckerboardColor)
{
setCheckerboardEnabled(!m_checkerboardEnabled, invertCheckerboardColor);
}
void GraphicsView::mousePressEvent(QMouseEvent *event)
{
if (shouldIgnoreMousePressMoveEvent(event)) {
event->ignore();
// blumia: return here, or the QMouseEvent event transparency won't
// work if we set a QGraphicsView::ScrollHandDrag drag mode.
return;
}
return QGraphicsView::mousePressEvent(event);
}
void GraphicsView::mouseMoveEvent(QMouseEvent *event)
{
if (shouldIgnoreMousePressMoveEvent(event)) {
event->ignore();
}
return QGraphicsView::mouseMoveEvent(event);
}
void GraphicsView::mouseReleaseEvent(QMouseEvent *event)
{
if (event->button() == Qt::ForwardButton || event->button() == Qt::BackButton) {
event->ignore();
} else {
QGraphicsItem *item = itemAt(event->pos());
if (!item) {
event->ignore();
}
}
return QGraphicsView::mouseReleaseEvent(event);
}
void GraphicsView::wheelEvent(QWheelEvent *event)
{
event->ignore();
// blumia: no need for calling parent method.
}
void GraphicsView::resizeEvent(QResizeEvent *event)
{
if (m_enableFitInView) {
bool originalSizeSmallerThanWindow = isThingSmallerThanWindowWith(resetScale(transform()));
if (originalSizeSmallerThanWindow && scaleFactor() >= 1) {
// no longer need to do fitInView()
// but we leave the m_enableFitInView value unchanged in case
// user resize down the window again.
} else if (originalSizeSmallerThanWindow && scaleFactor() < 1) {
resetScale();
} else {
fitInView(sceneRect(), Qt::KeepAspectRatio);
}
} else {
emit navigatorViewRequired(!isThingSmallerThanWindowWith(transform()), transform());
}
return QGraphicsView::resizeEvent(event);
}
bool GraphicsView::isThingSmallerThanWindowWith(const QTransform &transform) const
{
return rect().size().expandedTo(transform.mapRect(sceneRect()).size().toSize())
== rect().size();
}
bool GraphicsView::shouldIgnoreMousePressMoveEvent(const QMouseEvent *event) const
{
if (event->buttons() == Qt::NoButton) {
return true;
}
QGraphicsItem *item = itemAt(event->pos());
if (!item) {
return true;
}
if (isThingSmallerThanWindowWith(transform())) {
return true;
}
return false;
}
void GraphicsView::setCheckerboardEnabled(bool enabled, bool invertColor)
{
m_checkerboardEnabled = enabled;
bool isLightCheckerboard = Settings::instance()->useLightCheckerboard() ^ invertColor;
if (m_checkerboardEnabled) {
// Prepare background check-board pattern
QPixmap tilePixmap(0x20, 0x20);
tilePixmap.fill(isLightCheckerboard ? QColor(220, 220, 220, 170) : QColor(35, 35, 35, 170));
QPainter tilePainter(&tilePixmap);
constexpr QColor color(45, 45, 45, 170);
constexpr QColor invertedColor(210, 210, 210, 170);
tilePainter.fillRect(0, 0, 0x10, 0x10, isLightCheckerboard ? invertedColor : color);
tilePainter.fillRect(0x10, 0x10, 0x10, 0x10, isLightCheckerboard ? invertedColor : color);
tilePainter.end();
setBackgroundBrush(tilePixmap);
} else {
setBackgroundBrush(Qt::transparent);
}
}
void GraphicsView::applyTransformationModeByScaleFactor()
{
if (this->scaleFactor() < 1) {
scene()->trySetTransformationMode(Qt::SmoothTransformation, this->scaleFactor());
} else {
scene()->trySetTransformationMode(Qt::FastTransformation, this->scaleFactor());
}
}
bool GraphicsView::shouldAvoidTransform() const
{
return m_firstUserMediaLoaded && m_avoidResetTransform;
}
// SPDX-FileCopyrightText: 2025 Gary Wang <git@blumia.net>
//
// SPDX-License-Identifier: MIT
#include "graphicsview.h"
#include "graphicsscene.h"
#include "settings.h"
#include <QDebug>
#include <QMouseEvent>
#include <QScrollBar>
#include <QMimeData>
#include <QImageReader>
#include <QStyleOptionGraphicsItem>
GraphicsView::GraphicsView(QWidget *parent)
: QGraphicsView (parent)
{
setDragMode(QGraphicsView::ScrollHandDrag);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setResizeAnchor(QGraphicsView::AnchorUnderMouse);
setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
setStyleSheet("background-color: rgba(0, 0, 0, 220);"
"border-radius: 3px;");
setAcceptDrops(false);
setCheckerboardEnabled(false);
connect(horizontalScrollBar(), &QScrollBar::valueChanged, this, &GraphicsView::viewportRectChanged);
connect(verticalScrollBar(), &QScrollBar::valueChanged, this, &GraphicsView::viewportRectChanged);
}
void GraphicsView::showFileFromPath(const QString &filePath)
{
emit navigatorViewRequired(false, transform());
if (filePath.endsWith(".svg")) {
showSvg(filePath);
} else {
QImageReader imageReader(filePath);
imageReader.setAutoTransform(true);
imageReader.setDecideFormatFromContent(true);
imageReader.setAllocationLimit(0);
// Since if the image format / plugin does not support this feature, imageFormat() will returns an invalid format.
// So we cannot use imageFormat() and check if it returns QImage::Format_Invalid to detect if we support the file.
// QImage::Format imageFormat = imageReader.imageFormat();
if (imageReader.format().isEmpty()) {
showText(tr("File is not a valid image"));
} else if (imageReader.supportsAnimation() && imageReader.imageCount() > 1) {
showAnimated(filePath);
} else if (!imageReader.canRead()) {
showText(tr("Image data is invalid or currently unsupported"));
} else {
QPixmap && pixmap = QPixmap::fromImageReader(&imageReader);
if (pixmap.isNull()) {
showText(tr("Image data is invalid or currently unsupported"));
} else {
pixmap.setDevicePixelRatio(devicePixelRatioF());
showImage(pixmap);
}
}
}
}
void GraphicsView::showImage(const QPixmap &pixmap)
{
resetTransform();
scene()->showImage(pixmap);
displayScene();
}
void GraphicsView::showImage(const QImage &image)
{
resetTransform();
scene()->showImage(QPixmap::fromImage(image));
displayScene();
}
void GraphicsView::showText(const QString &text)
{
resetTransform();
scene()->showText(text);
displayScene();
}
void GraphicsView::showSvg(const QString &filepath)
{
resetTransform();
scene()->showSvg(filepath);
displayScene();
}
void GraphicsView::showAnimated(const QString &filepath)
{
resetTransform();
scene()->showAnimated(filepath);
displayScene();
}
GraphicsScene *GraphicsView::scene() const
{
return qobject_cast<GraphicsScene*>(QGraphicsView::scene());
}
void GraphicsView::setScene(GraphicsScene *scene)
{
return QGraphicsView::setScene(scene);
}
qreal GraphicsView::scaleFactor() const
{
return QStyleOptionGraphicsItem::levelOfDetailFromTransform(transform());
}
void GraphicsView::resetTransform()
{
if (!shouldAvoidTransform()) {
QGraphicsView::resetTransform();
}
}
void GraphicsView::zoomView(qreal scaleFactor)
{
m_enableFitInView = false;
m_longImageMode = false;
scale(scaleFactor, scaleFactor);
applyTransformationModeByScaleFactor();
emit navigatorViewRequired(!isThingSmallerThanWindowWith(transform()), transform());
}
// This is always according to user's view.
// the direction of the rotation will NOT be clockwise because the y-axis points downwards.
void GraphicsView::rotateView(bool clockwise)
{
resetScale();
QTransform tf(0, clockwise ? 1 : -1, 0,
clockwise ? -1 : 1, 0, 0,
0, 0, 1);
tf = transform() * tf;
setTransform(tf);
// Apply transformation mode but don't emit navigator signal here
// Let displayScene() handle the navigator visibility correctly
applyTransformationModeByScaleFactor();
}
void GraphicsView::flipView(bool horizontal)
{
QTransform tf(horizontal ? -1 : 1, 0, 0,
0, horizontal ? 1 : -1, 0,
0, 0, 1);
tf = transform() * tf;
setTransform(tf);
// Ensure the navigation view is also flipped.
emit navigatorViewRequired(!isThingSmallerThanWindowWith(transform()), transform());
}
void GraphicsView::resetScale()
{
setTransform(resetScale(transform()));
applyTransformationModeByScaleFactor();
emit navigatorViewRequired(!isThingSmallerThanWindowWith(transform()), transform());
}
void GraphicsView::fitInView(const QRectF &rect, Qt::AspectRatioMode aspectRadioMode)
{
QGraphicsView::fitInView(rect, aspectRadioMode);
applyTransformationModeByScaleFactor();
}
void GraphicsView::fitByOrientation(Qt::Orientation ori, bool scaleDownOnly)
{
resetScale();
QRectF viewRect = this->viewport()->rect();
QRectF imageRect = transform().mapRect(sceneRect());
QSize viewSize = viewRect.size().toSize();
qreal ratio;
if (ori == Qt::Horizontal) {
// Horizontal fit means fit by width
if (scaleDownOnly && imageRect.width() <= viewSize.width()) {
// Image width already fits, no scaling needed
ratio = 1;
} else {
ratio = viewRect.width() / imageRect.width();
}
} else {
// Vertical fit means fit by height
if (scaleDownOnly && imageRect.height() <= viewSize.height()) {
// Image height already fits, no scaling needed
ratio = 1;
} else {
ratio = viewRect.height() / imageRect.height();
}
}
if (ratio != 1) {
scale(ratio, ratio);
}
// Position the image correctly based on orientation with rotation consideration
QRectF originalScene = sceneRect();
QTransform currentTransform = transform();
if (ori == Qt::Horizontal) {
// For horizontal fit (fit by width), position at top (for tall images)
// Find the scene point that corresponds to the top-center of the transformed image
QPointF sceneTopCenter;
if (qFuzzyIsNull(currentTransform.m12()) && qFuzzyIsNull(currentTransform.m21())) {
// 0° or 180° rotation
if (currentTransform.m11() > 0 && currentTransform.m22() > 0) {
// 0° rotation: use original top-center
sceneTopCenter = QPointF(originalScene.center().x(), originalScene.top());
} else {
// 180° rotation: the visual "top" is now at the scene bottom
sceneTopCenter = QPointF(originalScene.center().x(), originalScene.bottom());
}
} else {
// 90/270 degree rotation: the "top" in view corresponds to left/right in scene
if (currentTransform.m12() > 0) {
// 90 degree: top in view = left in scene
sceneTopCenter = QPointF(originalScene.left(), originalScene.center().y());
} else {
// 270 degree: top in view = right in scene
sceneTopCenter = QPointF(originalScene.right(), originalScene.center().y());
}
}
centerOn(sceneTopCenter);
} else {
// For vertical fit (fit by height), position at left (for wide images)
// Find the scene point that corresponds to the left-center of the transformed image
QPointF sceneLeftCenter;
if (qFuzzyIsNull(currentTransform.m12()) && qFuzzyIsNull(currentTransform.m21())) {
// 0° or 180° rotation
if (currentTransform.m11() > 0 && currentTransform.m22() > 0) {
// 0° rotation: use original left-center
sceneLeftCenter = QPointF(originalScene.left(), originalScene.center().y());
} else {
// 180° rotation: the visual "left" is now at the scene right
sceneLeftCenter = QPointF(originalScene.right(), originalScene.center().y());
}
} else {
// 90/270 degree rotation: the "left" in view corresponds to top/bottom in scene
if (currentTransform.m21() > 0) {
// 90 degree: left in view = top in scene
sceneLeftCenter = QPointF(originalScene.center().x(), originalScene.top());
} else {
// 270 degree: left in view = bottom in scene
sceneLeftCenter = QPointF(originalScene.center().x(), originalScene.bottom());
}
}
centerOn(sceneLeftCenter);
}
m_enableFitInView = false;
applyTransformationModeByScaleFactor();
emit navigatorViewRequired(!isThingSmallerThanWindowWith(transform()), transform());
}
bool GraphicsView::isLongImage() const
{
// Get the transformed image size (considering rotation and other transforms)
QRectF transformedRect = transform().mapRect(sceneRect());
QSizeF imageSize = transformedRect.size();
if (imageSize.isEmpty()) return false;
qreal aspectRatio = imageSize.width() / imageSize.height();
// Check if aspect ratio exceeds 5:2 (wide) or 2:5 (tall)
return aspectRatio > 2.5 || aspectRatio < 0.4;
}
void GraphicsView::fitLongImage()
{
QRectF transformedRect = transform().mapRect(sceneRect());
if (transformedRect.width() < transformedRect.height()) {
fitByOrientation(Qt::Horizontal, true);
} else {
fitByOrientation(Qt::Vertical, true);
}
}
void GraphicsView::displayScene()
{
if (shouldAvoidTransform()) {
emit navigatorViewRequired(!isThingSmallerThanWindowWith(transform()), transform());
return;
}
// Check if should apply long image mode
if (Settings::instance()->autoLongImageMode() && isLongImage()) {
m_longImageMode = true;
m_firstUserMediaLoaded = true;
if (isSceneBiggerThanView()) fitLongImage();
return;
}
if (isSceneBiggerThanView()) {
// Do fit-in-view
fitInView(sceneRect(), Qt::KeepAspectRatio);
// After fitInView, the image should fit the window, so hide navigator
emit navigatorViewRequired(false, transform());
} else {
// Image is already smaller than window, no navigator needed
emit navigatorViewRequired(false, transform());
}
m_longImageMode = false;
m_enableFitInView = true;
m_firstUserMediaLoaded = true;
}
bool GraphicsView::isSceneBiggerThanView() const
{
if (!isThingSmallerThanWindowWith(transform())) {
return true;
} else {
return false;
}
}
// Automately do fit in view when viewport(window) smaller than image original size.
void GraphicsView::setEnableAutoFitInView(bool enable)
{
m_enableFitInView = enable;
}
void GraphicsView::setLongImageMode(bool enable)
{
m_longImageMode = enable;
}
bool GraphicsView::avoidResetTransform() const
{
return m_avoidResetTransform;
}
void GraphicsView::setAvoidResetTransform(bool avoidReset)
{
m_avoidResetTransform = avoidReset;
}
inline double zeroOrOne(double number)
{
return qFuzzyIsNull(number) ? 0 : (number > 0 ? 1 : -1);
}
// Note: this only works if we only have 90 degree based rotation
// and no shear/translate.
QTransform GraphicsView::resetScale(const QTransform & orig)
{
return QTransform(zeroOrOne(orig.m11()), zeroOrOne(orig.m12()),
zeroOrOne(orig.m21()), zeroOrOne(orig.m22()),
orig.dx(), orig.dy());
}
void GraphicsView::toggleCheckerboard(bool invertCheckerboardColor)
{
setCheckerboardEnabled(!m_checkerboardEnabled, invertCheckerboardColor);
}
void GraphicsView::mousePressEvent(QMouseEvent *event)
{
if (shouldIgnoreMousePressMoveEvent(event)) {
event->ignore();
// blumia: return here, or the QMouseEvent event transparency won't
// work if we set a QGraphicsView::ScrollHandDrag drag mode.
return;
}
return QGraphicsView::mousePressEvent(event);
}
void GraphicsView::mouseMoveEvent(QMouseEvent *event)
{
if (shouldIgnoreMousePressMoveEvent(event)) {
event->ignore();
}
return QGraphicsView::mouseMoveEvent(event);
}
void GraphicsView::mouseReleaseEvent(QMouseEvent *event)
{
if (event->button() == Qt::ForwardButton || event->button() == Qt::BackButton) {
event->ignore();
} else {
QGraphicsItem *item = itemAt(event->pos());
if (!item) {
event->ignore();
}
}
return QGraphicsView::mouseReleaseEvent(event);
}
void GraphicsView::wheelEvent(QWheelEvent *event)
{
event->ignore();
// blumia: no need for calling parent method.
}
void GraphicsView::resizeEvent(QResizeEvent *event)
{
if (m_longImageMode) {
// In long image mode, reapply long image logic on resize
// We directly apply the long image mode logic without rechecking
// if we should enter long image mode, as the mode is already active
fitLongImage();
} else if (m_enableFitInView) {
bool originalSizeSmallerThanWindow = isThingSmallerThanWindowWith(resetScale(transform()));
if (originalSizeSmallerThanWindow && scaleFactor() >= 1) {
// no longer need to do fitInView()
// but we leave the m_enableFitInView value unchanged in case
// user resize down the window again.
} else if (originalSizeSmallerThanWindow && scaleFactor() < 1) {
resetScale();
} else {
fitInView(sceneRect(), Qt::KeepAspectRatio);
}
} else {
emit navigatorViewRequired(!isThingSmallerThanWindowWith(transform()), transform());
}
return QGraphicsView::resizeEvent(event);
}
bool GraphicsView::isThingSmallerThanWindowWith(const QTransform &transform) const
{
return rect().size().expandedTo(transform.mapRect(sceneRect()).size().toSize())
== rect().size();
}
bool GraphicsView::shouldIgnoreMousePressMoveEvent(const QMouseEvent *event) const
{
if (event->buttons() == Qt::NoButton) {
return true;
}
QGraphicsItem *item = itemAt(event->pos());
if (!item) {
return true;
}
if (isThingSmallerThanWindowWith(transform())) {
return true;
}
return false;
}
void GraphicsView::setCheckerboardEnabled(bool enabled, bool invertColor)
{
m_checkerboardEnabled = enabled;
bool isLightCheckerboard = Settings::instance()->useLightCheckerboard() ^ invertColor;
if (m_checkerboardEnabled) {
// Prepare background check-board pattern
QPixmap tilePixmap(0x20, 0x20);
tilePixmap.fill(isLightCheckerboard ? QColor(220, 220, 220, 170) : QColor(35, 35, 35, 170));
QPainter tilePainter(&tilePixmap);
constexpr QColor color(45, 45, 45, 170);
constexpr QColor invertedColor(210, 210, 210, 170);
tilePainter.fillRect(0, 0, 0x10, 0x10, isLightCheckerboard ? invertedColor : color);
tilePainter.fillRect(0x10, 0x10, 0x10, 0x10, isLightCheckerboard ? invertedColor : color);
tilePainter.end();
setBackgroundBrush(tilePixmap);
} else {
setBackgroundBrush(Qt::transparent);
}
}
void GraphicsView::applyTransformationModeByScaleFactor()
{
if (this->scaleFactor() < 1) {
scene()->trySetTransformationMode(Qt::SmoothTransformation, this->scaleFactor());
} else {
scene()->trySetTransformationMode(Qt::FastTransformation, this->scaleFactor());
}
}
bool GraphicsView::shouldAvoidTransform() const
{
return m_firstUserMediaLoaded && m_avoidResetTransform;
}

View File

@ -1,79 +1,85 @@
// SPDX-FileCopyrightText: 2022 Gary Wang <wzc782970009@gmail.com>
//
// SPDX-License-Identifier: MIT
#ifndef GRAPHICSVIEW_H
#define GRAPHICSVIEW_H
#include <QGraphicsView>
#include <QUrl>
class GraphicsScene;
class GraphicsView : public QGraphicsView
{
Q_OBJECT
public:
GraphicsView(QWidget *parent = nullptr);
void showFileFromPath(const QString &filePath);
void showImage(const QPixmap &pixmap);
void showImage(const QImage &image);
void showText(const QString &text);
void showSvg(const QString &filepath);
void showAnimated(const QString &filepath);
GraphicsScene * scene() const;
void setScene(GraphicsScene *scene);
qreal scaleFactor() const;
void resetTransform();
void zoomView(qreal scaleFactor);
void rotateView(bool clockwise = true);
void flipView(bool horizontal = true);
void resetScale();
void fitInView(const QRectF &rect, Qt::AspectRatioMode aspectRadioMode = Qt::IgnoreAspectRatio);
void fitByOrientation(Qt::Orientation ori = Qt::Horizontal, bool scaleDownOnly = false);
void displayScene();
bool isSceneBiggerThanView() const;
void setEnableAutoFitInView(bool enable = true);
bool avoidResetTransform() const;
void setAvoidResetTransform(bool avoidReset);
static QTransform resetScale(const QTransform & orig);
signals:
void navigatorViewRequired(bool required, QTransform transform);
void viewportRectChanged();
public slots:
void toggleCheckerboard(bool invertCheckerboardColor = false);
private:
void mousePressEvent(QMouseEvent * event) override;
void mouseMoveEvent(QMouseEvent * event) override;
void mouseReleaseEvent(QMouseEvent * event) override;
void wheelEvent(QWheelEvent *event) override;
void resizeEvent(QResizeEvent *event) override;
bool isThingSmallerThanWindowWith(const QTransform &transform) const;
bool shouldIgnoreMousePressMoveEvent(const QMouseEvent *event) const;
void setCheckerboardEnabled(bool enabled, bool invertColor = false);
void applyTransformationModeByScaleFactor();
inline bool shouldAvoidTransform() const;
// Consider switch to 3 state for "no fit", "always fit" and "fit when view is smaller"?
// ... or even more? e.g. "fit/snap width" things...
// Currently it's "no fit" when it's false and "fit when view is smaller" when it's true.
bool m_enableFitInView = false;
bool m_avoidResetTransform = false;
bool m_checkerboardEnabled = false;
bool m_useLightCheckerboard = false;
bool m_firstUserMediaLoaded = false;
};
#endif // GRAPHICSVIEW_H
// SPDX-FileCopyrightText: 2022 Gary Wang <wzc782970009@gmail.com>
//
// SPDX-License-Identifier: MIT
#ifndef GRAPHICSVIEW_H
#define GRAPHICSVIEW_H
#include <QGraphicsView>
#include <QUrl>
class GraphicsScene;
class GraphicsView : public QGraphicsView
{
Q_OBJECT
public:
GraphicsView(QWidget *parent = nullptr);
void showFileFromPath(const QString &filePath);
void showImage(const QPixmap &pixmap);
void showImage(const QImage &image);
void showText(const QString &text);
void showSvg(const QString &filepath);
void showAnimated(const QString &filepath);
GraphicsScene * scene() const;
void setScene(GraphicsScene *scene);
qreal scaleFactor() const;
void resetTransform();
void zoomView(qreal scaleFactor);
void rotateView(bool clockwise = true);
void flipView(bool horizontal = true);
void resetScale();
void fitInView(const QRectF &rect, Qt::AspectRatioMode aspectRadioMode = Qt::IgnoreAspectRatio);
void fitByOrientation(Qt::Orientation ori = Qt::Horizontal, bool scaleDownOnly = false);
void displayScene();
bool isSceneBiggerThanView() const;
void setEnableAutoFitInView(bool enable = true);
void setLongImageMode(bool enable = true);
bool avoidResetTransform() const;
void setAvoidResetTransform(bool avoidReset);
static QTransform resetScale(const QTransform & orig);
// Long image mode support
bool isLongImage() const;
void fitLongImage();
signals:
void navigatorViewRequired(bool required, QTransform transform);
void viewportRectChanged();
public slots:
void toggleCheckerboard(bool invertCheckerboardColor = false);
private:
void mousePressEvent(QMouseEvent * event) override;
void mouseMoveEvent(QMouseEvent * event) override;
void mouseReleaseEvent(QMouseEvent * event) override;
void wheelEvent(QWheelEvent *event) override;
void resizeEvent(QResizeEvent *event) override;
bool isThingSmallerThanWindowWith(const QTransform &transform) const;
bool shouldIgnoreMousePressMoveEvent(const QMouseEvent *event) const;
void setCheckerboardEnabled(bool enabled, bool invertColor = false);
void applyTransformationModeByScaleFactor();
inline bool shouldAvoidTransform() const;
// Consider switch to 3 state for "no fit", "always fit" and "fit when view is smaller"?
// ... or even more? e.g. "fit/snap width" things...
// Currently it's "no fit" when it's false and "fit when view is smaller" when it's true.
bool m_enableFitInView = false;
bool m_longImageMode = false;
bool m_avoidResetTransform = false;
bool m_checkerboardEnabled = false;
bool m_useLightCheckerboard = false;
bool m_firstUserMediaLoaded = false;
};
#endif // GRAPHICSVIEW_H

View File

@ -1,103 +1,103 @@
// SPDX-FileCopyrightText: 2022 Gary Wang <wzc782970009@gmail.com>
//
// SPDX-License-Identifier: MIT
#include "mainwindow.h"
#include "playlistmanager.h"
#include "settings.h"
#ifdef Q_OS_MACOS
#include "fileopeneventhandler.h"
#endif // Q_OS_MACOS
#include <QApplication>
#include <QCommandLineParser>
#include <QDir>
#include <QTranslator>
#include <QUrl>
using namespace Qt::Literals::StringLiterals;
int main(int argc, char *argv[])
{
QCoreApplication::setApplicationName(u"Pineapple Pictures"_s);
QCoreApplication::setApplicationVersion(PPIC_VERSION_STRING);
QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Settings::instance()->hiDpiScaleFactorBehavior());
QApplication a(argc, argv);
QTranslator translator;
#if defined(TRANSLATION_RESOURCE_EMBEDDING)
const QString qmDir = u":/i18n/"_s;
#elif defined(QM_FILE_INSTALL_ABSOLUTE_DIR)
const QString qmDir = QT_STRINGIFY(QM_FILE_INSTALL_ABSOLUTE_DIR);
#else
const QString qmDir = QDir(QCoreApplication::applicationDirPath()).absoluteFilePath("translations");
#endif
if (translator.load(QLocale(), u"PineapplePictures"_s, u"_"_s, qmDir)) {
QCoreApplication::installTranslator(&translator);
}
QGuiApplication::setApplicationDisplayName(QCoreApplication::translate("main", "Pineapple Pictures"));
// commandline options
QCommandLineOption supportedImageFormats(u"supported-image-formats"_s, QCoreApplication::translate("main", "List supported image format suffixes, and quit program."));
// parse commandline arguments
QCommandLineParser parser;
parser.addOption(supportedImageFormats);
parser.addPositionalArgument("File list", QCoreApplication::translate("main", "File list."));
parser.addHelpOption();
parser.process(a);
if (parser.isSet(supportedImageFormats)) {
#if QT_VERSION < QT_VERSION_CHECK(6, 9, 0)
fputs(qPrintable(MainWindow::supportedImageFormats().join(QChar('\n'))), stdout);
::exit(EXIT_SUCCESS);
#else
QCommandLineParser::showMessageAndExit(QCommandLineParser::MessageType::Information,
MainWindow::supportedImageFormats().join(QChar('\n')));
#endif
}
MainWindow w;
w.show();
#ifdef Q_OS_MACOS
FileOpenEventHandler * fileOpenEventHandler = new FileOpenEventHandler(&a);
a.installEventFilter(fileOpenEventHandler);
a.connect(fileOpenEventHandler, &FileOpenEventHandler::fileOpen, [&w](const QUrl & url){
if (w.isHidden()) {
w.setWindowOpacity(1);
w.showNormal();
} else {
w.activateWindow();
}
w.showUrls({url});
w.initWindowSize();
});
// Handle dock icon clicks to show hidden window
a.connect(&a, &QApplication::applicationStateChanged, [&w](Qt::ApplicationState state) {
if (state == Qt::ApplicationActive && w.isHidden()) {
w.showUrls({});
w.galleryCurrent(true, true);
w.setWindowOpacity(1);
w.showNormal();
w.raise();
w.activateWindow();
}
});
#endif // Q_OS_MACOS
QStringList urlStrList = parser.positionalArguments();
QList<QUrl> && urlList = PlaylistManager::convertToUrlList(urlStrList);
if (!urlList.isEmpty()) {
w.showUrls(urlList);
}
w.initWindowSize();
return QApplication::exec();
}
// SPDX-FileCopyrightText: 2022 Gary Wang <wzc782970009@gmail.com>
//
// SPDX-License-Identifier: MIT
#include "mainwindow.h"
#include "playlistmanager.h"
#include "settings.h"
#ifdef Q_OS_MACOS
#include "fileopeneventhandler.h"
#endif // Q_OS_MACOS
#include <QApplication>
#include <QCommandLineParser>
#include <QDir>
#include <QTranslator>
#include <QUrl>
using namespace Qt::Literals::StringLiterals;
int main(int argc, char *argv[])
{
QCoreApplication::setApplicationName(u"Pineapple Pictures"_s);
QCoreApplication::setApplicationVersion(PPIC_VERSION_STRING);
QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Settings::instance()->hiDpiScaleFactorBehavior());
QApplication a(argc, argv);
QTranslator translator;
#if defined(TRANSLATION_RESOURCE_EMBEDDING)
const QString qmDir = u":/i18n/"_s;
#elif defined(QM_FILE_INSTALL_ABSOLUTE_DIR)
const QString qmDir = QT_STRINGIFY(QM_FILE_INSTALL_ABSOLUTE_DIR);
#else
const QString qmDir = QDir(QCoreApplication::applicationDirPath()).absoluteFilePath("translations");
#endif
if (translator.load(QLocale(), u"PineapplePictures"_s, u"_"_s, qmDir)) {
QCoreApplication::installTranslator(&translator);
}
QGuiApplication::setApplicationDisplayName(QCoreApplication::translate("main", "Pineapple Pictures"));
// commandline options
QCommandLineOption supportedImageFormats(u"supported-image-formats"_s, QCoreApplication::translate("main", "List supported image format suffixes, and quit program."));
// parse commandline arguments
QCommandLineParser parser;
parser.addOption(supportedImageFormats);
parser.addPositionalArgument("File list", QCoreApplication::translate("main", "File list."));
parser.addHelpOption();
parser.process(a);
if (parser.isSet(supportedImageFormats)) {
#if QT_VERSION < QT_VERSION_CHECK(6, 9, 0)
fputs(qPrintable(MainWindow::supportedImageFormats().join(QChar('\n'))), stdout);
::exit(EXIT_SUCCESS);
#else
QCommandLineParser::showMessageAndExit(QCommandLineParser::MessageType::Information,
MainWindow::supportedImageFormats().join(QChar('\n')));
#endif
}
MainWindow w;
w.show();
#ifdef Q_OS_MACOS
FileOpenEventHandler * fileOpenEventHandler = new FileOpenEventHandler(&a);
a.installEventFilter(fileOpenEventHandler);
a.connect(fileOpenEventHandler, &FileOpenEventHandler::fileOpen, [&w](const QUrl & url){
if (w.isHidden()) {
w.setWindowOpacity(1);
w.showNormal();
} else {
w.activateWindow();
}
w.showUrls({url});
w.initWindowSize();
});
// Handle dock icon clicks to show hidden window
a.connect(&a, &QApplication::applicationStateChanged, [&w](Qt::ApplicationState state) {
if (state == Qt::ApplicationActive && w.isHidden()) {
w.showUrls({});
w.galleryCurrent(true, true);
w.setWindowOpacity(1);
w.showNormal();
w.raise();
w.activateWindow();
}
});
#endif // Q_OS_MACOS
QStringList urlStrList = parser.positionalArguments();
QList<QUrl> && urlList = PlaylistManager::convertToUrlList(urlStrList);
if (!urlList.isEmpty()) {
w.showUrls(urlList);
}
w.initWindowSize();
return QApplication::exec();
}

View File

@ -222,7 +222,7 @@ void MainWindow::adjustWindowSizeBySceneRect()
if (m_graphicsView->scaleFactor() < 1 || size().expandedTo(sceneSizeWithMargins) != size()) {
// if it scaled down by the resize policy:
QSize screenSize = qApp->screenAt(QCursor::pos())->availableSize();
QSize screenSize = window()->screen()->availableSize();
if (screenSize.expandedTo(sceneSize) == screenSize) {
// we can show the picture by increase the window size.
QSize finalSize = (screenSize.expandedTo(sceneSizeWithMargins) == screenSize) ?
@ -313,7 +313,7 @@ QStringList MainWindow::supportedImageFormats()
void MainWindow::showEvent(QShowEvent *event)
{
updateWidgetsPosition();
return FramelessWindow::showEvent(event);
}
@ -584,7 +584,7 @@ void MainWindow::centerWindow()
Qt::LeftToRight,
Qt::AlignCenter,
this->size(),
qApp->screenAt(QCursor::pos())->availableGeometry()
window()->screen()->availableGeometry()
)
);
}
@ -700,6 +700,7 @@ void MainWindow::on_actionActualSize_triggered()
{
m_graphicsView->resetScale();
m_graphicsView->setEnableAutoFitInView(false);
m_graphicsView->setLongImageMode(false);
}
void MainWindow::on_actionToggleMaximize_triggered()
@ -728,6 +729,7 @@ void MainWindow::on_actionFitInView_triggered()
{
m_graphicsView->fitInView(m_gv->sceneRect(), Qt::KeepAspectRatio);
m_graphicsView->setEnableAutoFitInView(m_graphicsView->scaleFactor() <= 1);
m_graphicsView->setLongImageMode(false);
}
void MainWindow::on_actionFitByWidth_triggered()
@ -735,6 +737,12 @@ void MainWindow::on_actionFitByWidth_triggered()
m_graphicsView->fitByOrientation();
}
void MainWindow::on_actionFitLongImage_triggered()
{
m_graphicsView->setLongImageMode(true);
m_graphicsView->fitLongImage();
}
void MainWindow::on_actionCopyPixmap_triggered()
{
QClipboard *cb = QApplication::clipboard();
@ -813,14 +821,12 @@ void MainWindow::on_actionRotateClockwise_triggered()
{
m_graphicsView->rotateView();
m_graphicsView->displayScene();
m_gv->setVisible(false);
}
void MainWindow::on_actionRotateCounterClockwise_triggered()
{
m_graphicsView->rotateView(false);
m_graphicsView->displayScene();
m_gv->setVisible(false);
}
void MainWindow::on_actionPrevPicture_triggered()

View File

@ -1,134 +1,135 @@
// SPDX-FileCopyrightText: 2025 Gary Wang <git@blumia.net>
//
// SPDX-License-Identifier: MIT
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include "framelesswindow.h"
#include <QParallelAnimationGroup>
#include <QPropertyAnimation>
#include <QPushButton>
QT_BEGIN_NAMESPACE
class QGraphicsOpacityEffect;
class QGraphicsView;
class QFileSystemWatcher;
QT_END_NAMESPACE
class ActionManager;
class PlaylistManager;
class ToolButton;
class GraphicsView;
class NavigatorView;
class BottomButtonGroup;
class MainWindow : public FramelessWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow() override;
void showUrls(const QList<QUrl> &urls);
void initWindowSize();
void adjustWindowSizeBySceneRect();
QUrl currentImageFileUrl() const;
void clearGallery();
void galleryPrev();
void galleryNext();
void galleryCurrent(bool showLoadImageHintWhenEmpty, bool reloadImage);
static QStringList supportedImageFormats();
protected slots:
void showEvent(QShowEvent *event) override;
void enterEvent(QEnterEvent *event) override;
void leaveEvent(QEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
void mouseDoubleClickEvent(QMouseEvent *event) override;
void wheelEvent(QWheelEvent *event) override;
void resizeEvent(QResizeEvent *event) override;
void contextMenuEvent(QContextMenuEvent *event) override;
void dragEnterEvent(QDragEnterEvent *event) override;
void dragMoveEvent(QDragMoveEvent *event) override;
void dropEvent(QDropEvent *event) override;
void centerWindow();
void closeWindow();
void updateWidgetsPosition();
void toggleProtectedMode();
void toggleStayOnTop();
void toggleAvoidResetTransform();
bool stayOnTop() const;
bool canPaste() const;
void quitAppAction(bool force = false);
void toggleFullscreen();
void toggleMaximize();
protected:
QSize sizeHint() const override;
private slots:
void on_actionOpen_triggered();
void on_actionActualSize_triggered();
void on_actionToggleMaximize_triggered();
void on_actionZoomIn_triggered();
void on_actionZoomOut_triggered();
void on_actionToggleCheckerboard_triggered();
void on_actionRotateClockwise_triggered();
void on_actionRotateCounterClockwise_triggered();
void on_actionPrevPicture_triggered();
void on_actionNextPicture_triggered();
void on_actionTogglePauseAnimation_triggered();
void on_actionAnimationNextFrame_triggered();
void on_actionHorizontalFlip_triggered();
void on_actionFitInView_triggered();
void on_actionFitByWidth_triggered();
void on_actionCopyPixmap_triggered();
void on_actionCopyFilePath_triggered();
void on_actionPaste_triggered();
void on_actionTrash_triggered();
void on_actionToggleStayOnTop_triggered();
void on_actionToggleProtectMode_triggered();
void on_actionToggleAvoidResetTransform_triggered();
void on_actionSettings_triggered();
void on_actionHelp_triggered();
void on_actionProperties_triggered();
void on_actionLocateInFileManager_triggered();
void on_actionQuitApp_triggered();
void doCloseWindow();
private:
bool updateFileWatcher(const QString & basePath = QString());
void updateGalleryButtonsVisibility();
private:
ActionManager *m_am;
PlaylistManager *m_pm;
QPoint m_oldMousePos;
QPropertyAnimation *m_fadeOutAnimation;
QPropertyAnimation *m_floatUpAnimation;
QParallelAnimationGroup *m_exitAnimationGroup;
QFileSystemWatcher *m_fileSystemWatcher;
ToolButton *m_closeButton;
ToolButton *m_prevButton;
ToolButton *m_nextButton;
GraphicsView *m_graphicsView;
NavigatorView *m_gv;
BottomButtonGroup *m_bottomButtonGroup;
bool m_protectedMode = false;
bool m_clickedOnWindow = false;
};
#endif // MAINWINDOW_H
// SPDX-FileCopyrightText: 2025 Gary Wang <git@blumia.net>
//
// SPDX-License-Identifier: MIT
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include "framelesswindow.h"
#include <QParallelAnimationGroup>
#include <QPropertyAnimation>
#include <QPushButton>
QT_BEGIN_NAMESPACE
class QGraphicsOpacityEffect;
class QGraphicsView;
class QFileSystemWatcher;
QT_END_NAMESPACE
class ActionManager;
class PlaylistManager;
class ToolButton;
class GraphicsView;
class NavigatorView;
class BottomButtonGroup;
class MainWindow : public FramelessWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow() override;
void showUrls(const QList<QUrl> &urls);
void initWindowSize();
void adjustWindowSizeBySceneRect();
QUrl currentImageFileUrl() const;
void clearGallery();
void galleryPrev();
void galleryNext();
void galleryCurrent(bool showLoadImageHintWhenEmpty, bool reloadImage);
static QStringList supportedImageFormats();
protected slots:
void showEvent(QShowEvent *event) override;
void enterEvent(QEnterEvent *event) override;
void leaveEvent(QEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
void mouseDoubleClickEvent(QMouseEvent *event) override;
void wheelEvent(QWheelEvent *event) override;
void resizeEvent(QResizeEvent *event) override;
void contextMenuEvent(QContextMenuEvent *event) override;
void dragEnterEvent(QDragEnterEvent *event) override;
void dragMoveEvent(QDragMoveEvent *event) override;
void dropEvent(QDropEvent *event) override;
void centerWindow();
void closeWindow();
void updateWidgetsPosition();
void toggleProtectedMode();
void toggleStayOnTop();
void toggleAvoidResetTransform();
bool stayOnTop() const;
bool canPaste() const;
void quitAppAction(bool force = false);
void toggleFullscreen();
void toggleMaximize();
protected:
QSize sizeHint() const override;
private slots:
void on_actionOpen_triggered();
void on_actionActualSize_triggered();
void on_actionToggleMaximize_triggered();
void on_actionZoomIn_triggered();
void on_actionZoomOut_triggered();
void on_actionToggleCheckerboard_triggered();
void on_actionRotateClockwise_triggered();
void on_actionRotateCounterClockwise_triggered();
void on_actionPrevPicture_triggered();
void on_actionNextPicture_triggered();
void on_actionTogglePauseAnimation_triggered();
void on_actionAnimationNextFrame_triggered();
void on_actionHorizontalFlip_triggered();
void on_actionFitInView_triggered();
void on_actionFitByWidth_triggered();
void on_actionFitLongImage_triggered();
void on_actionCopyPixmap_triggered();
void on_actionCopyFilePath_triggered();
void on_actionPaste_triggered();
void on_actionTrash_triggered();
void on_actionToggleStayOnTop_triggered();
void on_actionToggleProtectMode_triggered();
void on_actionToggleAvoidResetTransform_triggered();
void on_actionSettings_triggered();
void on_actionHelp_triggered();
void on_actionProperties_triggered();
void on_actionLocateInFileManager_triggered();
void on_actionQuitApp_triggered();
void doCloseWindow();
private:
bool updateFileWatcher(const QString & basePath = QString());
void updateGalleryButtonsVisibility();
private:
ActionManager *m_am;
PlaylistManager *m_pm;
QPoint m_oldMousePos;
QPropertyAnimation *m_fadeOutAnimation;
QPropertyAnimation *m_floatUpAnimation;
QParallelAnimationGroup *m_exitAnimationGroup;
QFileSystemWatcher *m_fileSystemWatcher;
ToolButton *m_closeButton;
ToolButton *m_prevButton;
ToolButton *m_nextButton;
GraphicsView *m_graphicsView;
NavigatorView *m_gv;
BottomButtonGroup *m_bottomButtonGroup;
bool m_protectedMode = false;
bool m_clickedOnWindow = false;
};
#endif // MAINWINDOW_H

View File

@ -1,110 +1,110 @@
// SPDX-FileCopyrightText: 2022 Gary Wang <wzc782970009@gmail.com>
//
// SPDX-License-Identifier: MIT
#include "metadatadialog.h"
#include <QDialogButtonBox>
#include <QPainter>
#include <QStyledItemDelegate>
#include <QTreeView>
#include <QVBoxLayout>
#include <QHeaderView>
#include "metadatamodel.h"
class PropertyTreeView : public QTreeView
{
public:
explicit PropertyTreeView(QWidget* parent) : QTreeView(parent) {}
~PropertyTreeView() {}
protected:
void rowsInserted(const QModelIndex& parent, int start, int end) override
{
QTreeView::rowsInserted(parent, start, end);
if (!parent.isValid()) {
// we are inserting a section group
for (int row = start; row <= end; ++row) {
setupSection(row);
}
} else {
// we are inserting a property
setRowHidden(parent.row(), QModelIndex(), false);
}
}
void reset() override
{
QTreeView::reset();
if (model()) {
for (int row = 0; row < model()->rowCount(); ++row) {
setupSection(row);
}
}
}
private:
void setupSection(int row)
{
expand(model()->index(row, 0));
setFirstColumnSpanned(row, QModelIndex(), true);
setRowHidden(row, QModelIndex(), !model()->hasChildren(model()->index(row, 0)));
}
};
class PropertyTreeItemDelegate : public QStyledItemDelegate
{
public:
PropertyTreeItemDelegate(QObject* parent)
: QStyledItemDelegate(parent)
{}
protected:
void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override
{
QStyleOptionViewItem opt = option;
if (!index.parent().isValid()) {
opt.font.setBold(true);
opt.features.setFlag(QStyleOptionViewItem::Alternate);
}
QStyledItemDelegate::paint(painter, opt, index);
}
};
MetadataDialog::MetadataDialog(QWidget *parent)
: QDialog(parent)
, m_treeView(new PropertyTreeView(this))
{
m_treeView->setRootIsDecorated(false);
m_treeView->setIndentation(0);
m_treeView->setItemDelegate(new PropertyTreeItemDelegate(m_treeView));
m_treeView->header()->resizeSection(0, sizeHint().width() / 2);
setWindowTitle(tr("Image Metadata"));
QDialogButtonBox * buttonBox = new QDialogButtonBox(QDialogButtonBox::Close);
setLayout(new QVBoxLayout);
layout()->addWidget(m_treeView);
layout()->addWidget(buttonBox);
connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::close);
setWindowFlag(Qt::WindowContextHelpButtonHint, false);
}
MetadataDialog::~MetadataDialog()
{
}
void MetadataDialog::setMetadataModel(MetadataModel * model)
{
m_treeView->setModel(model);
}
QSize MetadataDialog::sizeHint() const
{
return QSize(520, 350);
}
// SPDX-FileCopyrightText: 2022 Gary Wang <wzc782970009@gmail.com>
//
// SPDX-License-Identifier: MIT
#include "metadatadialog.h"
#include <QDialogButtonBox>
#include <QPainter>
#include <QStyledItemDelegate>
#include <QTreeView>
#include <QVBoxLayout>
#include <QHeaderView>
#include "metadatamodel.h"
class PropertyTreeView : public QTreeView
{
public:
explicit PropertyTreeView(QWidget* parent) : QTreeView(parent) {}
~PropertyTreeView() {}
protected:
void rowsInserted(const QModelIndex& parent, int start, int end) override
{
QTreeView::rowsInserted(parent, start, end);
if (!parent.isValid()) {
// we are inserting a section group
for (int row = start; row <= end; ++row) {
setupSection(row);
}
} else {
// we are inserting a property
setRowHidden(parent.row(), QModelIndex(), false);
}
}
void reset() override
{
QTreeView::reset();
if (model()) {
for (int row = 0; row < model()->rowCount(); ++row) {
setupSection(row);
}
}
}
private:
void setupSection(int row)
{
expand(model()->index(row, 0));
setFirstColumnSpanned(row, QModelIndex(), true);
setRowHidden(row, QModelIndex(), !model()->hasChildren(model()->index(row, 0)));
}
};
class PropertyTreeItemDelegate : public QStyledItemDelegate
{
public:
PropertyTreeItemDelegate(QObject* parent)
: QStyledItemDelegate(parent)
{}
protected:
void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override
{
QStyleOptionViewItem opt = option;
if (!index.parent().isValid()) {
opt.font.setBold(true);
opt.features.setFlag(QStyleOptionViewItem::Alternate);
}
QStyledItemDelegate::paint(painter, opt, index);
}
};
MetadataDialog::MetadataDialog(QWidget *parent)
: QDialog(parent)
, m_treeView(new PropertyTreeView(this))
{
m_treeView->setRootIsDecorated(false);
m_treeView->setIndentation(0);
m_treeView->setItemDelegate(new PropertyTreeItemDelegate(m_treeView));
m_treeView->header()->resizeSection(0, sizeHint().width() / 2);
setWindowTitle(tr("Image Metadata"));
QDialogButtonBox * buttonBox = new QDialogButtonBox(QDialogButtonBox::Close);
setLayout(new QVBoxLayout);
layout()->addWidget(m_treeView);
layout()->addWidget(buttonBox);
connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::close);
setWindowFlag(Qt::WindowContextHelpButtonHint, false);
}
MetadataDialog::~MetadataDialog()
{
}
void MetadataDialog::setMetadataModel(MetadataModel * model)
{
m_treeView->setModel(model);
}
QSize MetadataDialog::sizeHint() const
{
return QSize(520, 350);
}

View File

@ -1,30 +1,30 @@
// SPDX-FileCopyrightText: 2022 Gary Wang <wzc782970009@gmail.com>
//
// SPDX-License-Identifier: MIT
#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
// SPDX-FileCopyrightText: 2022 Gary Wang <wzc782970009@gmail.com>
//
// SPDX-License-Identifier: MIT
#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

View File

@ -1,320 +1,320 @@
// SPDX-FileCopyrightText: 2022 Gary Wang <wzc782970009@gmail.com>
//
// SPDX-License-Identifier: MIT
#include "metadatamodel.h"
#include "exiv2wrapper.h"
#include <QDir>
#include <QDebug>
#include <QDateTime>
#include <QFileInfo>
#include <QImageReader>
using namespace Qt::Literals::StringLiterals;
MetadataModel::MetadataModel(QObject *parent)
: QAbstractItemModel(parent)
{
}
MetadataModel::~MetadataModel()
{
}
void MetadataModel::setFile(const QString &imageFilePath)
{
QFileInfo fileInfo(imageFilePath);
// It'll be fine if we don't re-use the image reader we pass to the graphics scene for now.
QImageReader imgReader(imageFilePath);
imgReader.setAutoTransform(true);
imgReader.setDecideFormatFromContent(true);
const QString & itemTypeString = tr("%1 File").arg(QString(imgReader.format().toUpper()));
const QString & sizeString = QLocale().formattedDataSize(fileInfo.size());
const QString & birthTimeString = QLocale().toString(fileInfo.birthTime(), QLocale::LongFormat);
const QString & lastModifiedTimeString = QLocale().toString(fileInfo.lastModified(), QLocale::LongFormat);
const QString & imageDimensionsString = imageSize(imgReader.size());
const QString & imageRatioString = imageSizeRatio(imgReader.size());
appendSection(u"Description"_s, tr("Description", "Section name."));
appendSection(u"Origin"_s, tr("Origin", "Section name."));
appendSection(u"Image"_s, tr("Image", "Section name."));
appendSection(u"Camera"_s, tr("Camera", "Section name."));
appendSection(u"AdvancedPhoto"_s, tr("Advanced photo", "Section name."));
appendSection(u"GPS"_s, tr("GPS", "Section name."));
appendSection(u"File"_s, tr("File", "Section name."));
if (imgReader.supportsOption(QImageIOHandler::Size)) {
appendProperty(u"Image"_s, u"Image.Dimensions"_s,
tr("Dimensions"), imageDimensionsString);
appendProperty(u"Image"_s, u"Image.SizeRatio"_s,
tr("Aspect ratio"), imageRatioString);
}
if (imgReader.supportsAnimation() && imgReader.imageCount() > 1) {
appendProperty(u"Image"_s, u"Image.FrameCount"_s,
tr("Frame count"), QString::number(imgReader.imageCount()));
}
appendProperty(u"File"_s, u"File.Name"_s,
tr("Name"), fileInfo.fileName());
appendProperty(u"File"_s, u"File.ItemType"_s,
tr("Item type"), itemTypeString);
appendProperty(u"File"_s, u"File.Path"_s,
tr("Folder path"), QDir::toNativeSeparators(fileInfo.path()));
appendProperty(u"File"_s, u"File.Size"_s,
tr("Size"), sizeString);
appendProperty(u"File"_s, u"File.CreatedTime"_s,
tr("Date created"), birthTimeString);
appendProperty(u"File"_s, u"File.LastModified"_s,
tr("Date modified"), lastModifiedTimeString);
Exiv2Wrapper wrapper;
if (wrapper.load(imageFilePath)) {
wrapper.cacheSections();
appendExivPropertyIfExist(wrapper, u"Description"_s,
u"Xmp.dc.title"_s, tr("Title"), true);
appendExivPropertyIfExist(wrapper, u"Description"_s,
u"Exif.Image.ImageDescription"_s, tr("Subject"), true);
appendExivPropertyIfExist(wrapper, u"Description"_s,
u"Exif.Image.Rating"_s, tr("Rating"));
appendExivPropertyIfExist(wrapper, u"Description"_s,
u"Xmp.dc.subject"_s, tr("Tags"));
appendPropertyIfNotEmpty(u"Description"_s, u"Description.Comments"_s,
tr("Comments"), wrapper.comment());
appendExivPropertyIfExist(wrapper, u"Origin"_s,
u"Exif.Image.Artist"_s, tr("Authors"));
appendExivPropertyIfExist(wrapper, u"Origin"_s,
u"Exif.Photo.DateTimeOriginal"_s, tr("Date taken"));
// FIXME: We may fetch the same type of metadata from different metadata collection.
// Current implementation is not pretty and may need to do a rework...
// appendExivPropertyIfExist(wrapper, QStringLiteral("Origin"),
// QStringLiteral("Xmp.xmp.CreatorTool"), tr("Program name"));
appendExivPropertyIfExist(wrapper, u"Origin"_s,
u"Exif.Image.Software"_s, tr("Program name"));
appendExivPropertyIfExist(wrapper, u"Origin"_s,
u"Exif.Image.Copyright"_s, tr("Copyright"));
appendExivPropertyIfExist(wrapper, u"Image"_s,
u"Exif.Image.XResolution"_s, tr("Horizontal resolution"));
appendExivPropertyIfExist(wrapper, u"Image"_s,
u"Exif.Image.YResolution"_s, tr("Vertical resolution"));
appendExivPropertyIfExist(wrapper, u"Image"_s,
u"Exif.Image.ResolutionUnit"_s, tr("Resolution unit"));
appendExivPropertyIfExist(wrapper, u"Image"_s,
u"Exif.Photo.ColorSpace"_s, tr("Colour representation"));
appendExivPropertyIfExist(wrapper, u"Camera"_s,
u"Exif.Image.Make"_s, tr("Camera maker"));
appendExivPropertyIfExist(wrapper, u"Camera"_s,
u"Exif.Image.Model"_s, tr("Camera model"));
appendExivPropertyIfExist(wrapper, u"Camera"_s,
u"Exif.Photo.FNumber"_s, tr("F-stop"));
appendExivPropertyIfExist(wrapper, u"Camera"_s,
u"Exif.Photo.ExposureTime"_s, tr("Exposure time"));
appendExivPropertyIfExist(wrapper, u"Camera"_s,
u"Exif.Photo.ISOSpeedRatings"_s, tr("ISO speed"));
appendExivPropertyIfExist(wrapper, u"Camera"_s,
u"Exif.Photo.ExposureBiasValue"_s, tr("Exposure bias"));
appendExivPropertyIfExist(wrapper, u"Camera"_s,
u"Exif.Photo.FocalLength"_s, tr("Focal length"));
appendExivPropertyIfExist(wrapper, u"Camera"_s,
u"Exif.Photo.MaxApertureValue"_s, tr("Max aperture"));
appendExivPropertyIfExist(wrapper, u"Camera"_s,
u"Exif.Photo.MeteringMode"_s, tr("Metering mode"));
appendExivPropertyIfExist(wrapper, u"Camera"_s,
u"Exif.Photo.SubjectDistance"_s, tr("Subject distance"));
appendExivPropertyIfExist(wrapper, u"Camera"_s,
u"Exif.Photo.Flash"_s, tr("Flash mode"));
appendExivPropertyIfExist(wrapper, u"Camera"_s,
u"Exif.Photo.FocalLengthIn35mmFilm"_s, tr("35mm focal length"));
appendExivPropertyIfExist(wrapper, u"AdvancedPhoto"_s,
u"Exif.Photo.LensModel"_s, tr("Lens model"));
appendExivPropertyIfExist(wrapper, u"AdvancedPhoto"_s,
u"Exif.Photo.Contrast"_s, tr("Contrast"));
appendExivPropertyIfExist(wrapper, u"AdvancedPhoto"_s,
u"Exif.Photo.BrightnessValue"_s, tr("Brightness"));
appendExivPropertyIfExist(wrapper, u"AdvancedPhoto"_s,
u"Exif.Photo.ExposureProgram"_s, tr("Exposure program"));
appendExivPropertyIfExist(wrapper, u"AdvancedPhoto"_s,
u"Exif.Photo.Saturation"_s, tr("Saturation"));
appendExivPropertyIfExist(wrapper, u"AdvancedPhoto"_s,
u"Exif.Photo.Sharpness"_s, tr("Sharpness"));
appendExivPropertyIfExist(wrapper, u"AdvancedPhoto"_s,
u"Exif.Photo.WhiteBalance"_s, tr("White balance"));
appendExivPropertyIfExist(wrapper, u"AdvancedPhoto"_s,
u"Exif.Photo.DigitalZoomRatio"_s, tr("Digital zoom"));
appendExivPropertyIfExist(wrapper, u"AdvancedPhoto"_s,
u"Exif.Photo.ExifVersion"_s, tr("EXIF version"));
appendExivPropertyIfExist(wrapper, u"GPS"_s,
u"Exif.GPSInfo.GPSLatitudeRef"_s, tr("Latitude reference"));
appendExivPropertyIfExist(wrapper, u"GPS"_s,
u"Exif.GPSInfo.GPSLatitude"_s, tr("Latitude"));
appendExivPropertyIfExist(wrapper, u"GPS"_s,
u"Exif.GPSInfo.GPSLongitudeRef"_s, tr("Longitude reference"));
appendExivPropertyIfExist(wrapper, u"GPS"_s,
u"Exif.GPSInfo.GPSLongitude"_s, tr("Longitude"));
appendExivPropertyIfExist(wrapper, u"GPS"_s,
u"Exif.GPSInfo.GPSAltitudeRef"_s, tr("Altitude reference"));
appendExivPropertyIfExist(wrapper, u"GPS"_s,
u"Exif.GPSInfo.GPSAltitude"_s, tr("Altitude"));
}
}
QString MetadataModel::imageSize(const QSize &size)
{
QString imageSize;
if (size.isValid()) {
imageSize = tr("%1 x %2").arg(QString::number(size.width()), QString::number(size.height()));
} else {
imageSize = QLatin1Char('-');
}
return imageSize;
}
int simplegcd(int a, int b) {
return b == 0 ? a : simplegcd(b, a % b);
}
QString MetadataModel::imageSizeRatio(const QSize &size)
{
if (!size.isValid()) {
return QStringLiteral("-");
}
int gcd = simplegcd(size.width(), size.height());
return tr("%1 : %2").arg(QString::number(size.width() / gcd), QString::number(size.height() / gcd));
}
bool MetadataModel::appendSection(const QString &sectionKey, QStringView sectionDisplayName)
{
if (m_sections.contains(sectionKey)) {
return false;
}
m_sections.append(sectionKey);
m_sectionProperties[sectionKey] = qMakePair<QString, QList<QString> >(sectionDisplayName.toString(), {});
return true;
}
bool MetadataModel::appendPropertyIfNotEmpty(const QString &sectionKey, const QString &propertyKey, const QString &propertyDisplayName, const QString &propertyValue)
{
if (propertyValue.isEmpty()) return false;
return appendProperty(sectionKey, propertyKey, propertyDisplayName, propertyValue);
}
bool MetadataModel::appendProperty(const QString &sectionKey, const QString &propertyKey, QStringView propertyDisplayName, QStringView propertyValue)
{
if (!m_sections.contains(sectionKey)) {
return false;
}
QList<QString> & propertyList = m_sectionProperties[sectionKey].second;
if (!propertyList.contains(propertyKey)) {
propertyList.append(propertyKey);
}
m_properties[propertyKey] = qMakePair<QString, QString>(propertyDisplayName.toString(), propertyValue.toString());
return true;
}
bool MetadataModel::appendExivPropertyIfExist(const Exiv2Wrapper &wrapper, const QString &sectionKey, const QString &exiv2propertyKey, const QString &propertyDisplayName, bool isXmpString)
{
const QString & value = wrapper.value(exiv2propertyKey);
if (!value.isEmpty()) {
appendProperty(sectionKey, exiv2propertyKey,
propertyDisplayName.isEmpty() ? wrapper.label(exiv2propertyKey) : propertyDisplayName,
isXmpString ? Exiv2Wrapper::XmpValue(value) : value);
return true;
}
return false;
}
QModelIndex MetadataModel::index(int row, int column, const QModelIndex &parent) const
{
if (!hasIndex(row, column, parent)) {
return QModelIndex();
}
if (!parent.isValid()) {
return createIndex(row, column, RowType::SectionRow);
} else {
// internalid param: row means nth section it belongs to.
return createIndex(row, column, RowType::PropertyRow + parent.row());
}
}
QModelIndex MetadataModel::parent(const QModelIndex &child) const
{
if (!child.isValid()) {
return QModelIndex();
}
if (child.internalId() == RowType::SectionRow) {
return QModelIndex();
} else {
return createIndex(child.internalId() - RowType::PropertyRow, 0, SectionRow);
}
}
int MetadataModel::rowCount(const QModelIndex &parent) const
{
if (!parent.isValid()) {
return m_sections.count();
}
if (parent.internalId() == RowType::SectionRow) {
const QString & sectionKey = m_sections[parent.row()];
return m_sectionProperties[sectionKey].second.count();
}
return 0;
}
int MetadataModel::columnCount(const QModelIndex &) const
{
// Always key(display name) and value.
return 2;
}
QVariant MetadataModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid()) {
return QVariant();
}
if (role != Qt::DisplayRole) {
return QVariant();
}
if (index.internalId() == RowType::SectionRow) {
return (index.column() == 0) ? m_sectionProperties[m_sections[index.row()]].first
: QVariant();
} else {
int sectionIndex = index.internalId() - RowType::PropertyRow;
const QString & sectionKey = m_sections[sectionIndex];
const QList<QString> & propertyList = m_sectionProperties[sectionKey].second;
return (index.column() == 0) ? m_properties[propertyList[index.row()]].first
: m_properties[propertyList[index.row()]].second;
}
}
QVariant MetadataModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (orientation == Qt::Vertical || role != Qt::DisplayRole) {
return QVariant();
}
return section == 0 ? tr("Property") : tr("Value");
}
// SPDX-FileCopyrightText: 2022 Gary Wang <wzc782970009@gmail.com>
//
// SPDX-License-Identifier: MIT
#include "metadatamodel.h"
#include "exiv2wrapper.h"
#include <QDir>
#include <QDebug>
#include <QDateTime>
#include <QFileInfo>
#include <QImageReader>
using namespace Qt::Literals::StringLiterals;
MetadataModel::MetadataModel(QObject *parent)
: QAbstractItemModel(parent)
{
}
MetadataModel::~MetadataModel()
{
}
void MetadataModel::setFile(const QString &imageFilePath)
{
QFileInfo fileInfo(imageFilePath);
// It'll be fine if we don't re-use the image reader we pass to the graphics scene for now.
QImageReader imgReader(imageFilePath);
imgReader.setAutoTransform(true);
imgReader.setDecideFormatFromContent(true);
const QString & itemTypeString = tr("%1 File").arg(QString(imgReader.format().toUpper()));
const QString & sizeString = QLocale().formattedDataSize(fileInfo.size());
const QString & birthTimeString = QLocale().toString(fileInfo.birthTime(), QLocale::LongFormat);
const QString & lastModifiedTimeString = QLocale().toString(fileInfo.lastModified(), QLocale::LongFormat);
const QString & imageDimensionsString = imageSize(imgReader.size());
const QString & imageRatioString = imageSizeRatio(imgReader.size());
appendSection(u"Description"_s, tr("Description", "Section name."));
appendSection(u"Origin"_s, tr("Origin", "Section name."));
appendSection(u"Image"_s, tr("Image", "Section name."));
appendSection(u"Camera"_s, tr("Camera", "Section name."));
appendSection(u"AdvancedPhoto"_s, tr("Advanced photo", "Section name."));
appendSection(u"GPS"_s, tr("GPS", "Section name."));
appendSection(u"File"_s, tr("File", "Section name."));
if (imgReader.supportsOption(QImageIOHandler::Size)) {
appendProperty(u"Image"_s, u"Image.Dimensions"_s,
tr("Dimensions"), imageDimensionsString);
appendProperty(u"Image"_s, u"Image.SizeRatio"_s,
tr("Aspect ratio"), imageRatioString);
}
if (imgReader.supportsAnimation() && imgReader.imageCount() > 1) {
appendProperty(u"Image"_s, u"Image.FrameCount"_s,
tr("Frame count"), QString::number(imgReader.imageCount()));
}
appendProperty(u"File"_s, u"File.Name"_s,
tr("Name"), fileInfo.fileName());
appendProperty(u"File"_s, u"File.ItemType"_s,
tr("Item type"), itemTypeString);
appendProperty(u"File"_s, u"File.Path"_s,
tr("Folder path"), QDir::toNativeSeparators(fileInfo.path()));
appendProperty(u"File"_s, u"File.Size"_s,
tr("Size"), sizeString);
appendProperty(u"File"_s, u"File.CreatedTime"_s,
tr("Date created"), birthTimeString);
appendProperty(u"File"_s, u"File.LastModified"_s,
tr("Date modified"), lastModifiedTimeString);
Exiv2Wrapper wrapper;
if (wrapper.load(imageFilePath)) {
wrapper.cacheSections();
appendExivPropertyIfExist(wrapper, u"Description"_s,
u"Xmp.dc.title"_s, tr("Title"), true);
appendExivPropertyIfExist(wrapper, u"Description"_s,
u"Exif.Image.ImageDescription"_s, tr("Subject"), true);
appendExivPropertyIfExist(wrapper, u"Description"_s,
u"Exif.Image.Rating"_s, tr("Rating"));
appendExivPropertyIfExist(wrapper, u"Description"_s,
u"Xmp.dc.subject"_s, tr("Tags"));
appendPropertyIfNotEmpty(u"Description"_s, u"Description.Comments"_s,
tr("Comments"), wrapper.comment());
appendExivPropertyIfExist(wrapper, u"Origin"_s,
u"Exif.Image.Artist"_s, tr("Authors"));
appendExivPropertyIfExist(wrapper, u"Origin"_s,
u"Exif.Photo.DateTimeOriginal"_s, tr("Date taken"));
// FIXME: We may fetch the same type of metadata from different metadata collection.
// Current implementation is not pretty and may need to do a rework...
// appendExivPropertyIfExist(wrapper, QStringLiteral("Origin"),
// QStringLiteral("Xmp.xmp.CreatorTool"), tr("Program name"));
appendExivPropertyIfExist(wrapper, u"Origin"_s,
u"Exif.Image.Software"_s, tr("Program name"));
appendExivPropertyIfExist(wrapper, u"Origin"_s,
u"Exif.Image.Copyright"_s, tr("Copyright"));
appendExivPropertyIfExist(wrapper, u"Image"_s,
u"Exif.Image.XResolution"_s, tr("Horizontal resolution"));
appendExivPropertyIfExist(wrapper, u"Image"_s,
u"Exif.Image.YResolution"_s, tr("Vertical resolution"));
appendExivPropertyIfExist(wrapper, u"Image"_s,
u"Exif.Image.ResolutionUnit"_s, tr("Resolution unit"));
appendExivPropertyIfExist(wrapper, u"Image"_s,
u"Exif.Photo.ColorSpace"_s, tr("Colour representation"));
appendExivPropertyIfExist(wrapper, u"Camera"_s,
u"Exif.Image.Make"_s, tr("Camera maker"));
appendExivPropertyIfExist(wrapper, u"Camera"_s,
u"Exif.Image.Model"_s, tr("Camera model"));
appendExivPropertyIfExist(wrapper, u"Camera"_s,
u"Exif.Photo.FNumber"_s, tr("F-stop"));
appendExivPropertyIfExist(wrapper, u"Camera"_s,
u"Exif.Photo.ExposureTime"_s, tr("Exposure time"));
appendExivPropertyIfExist(wrapper, u"Camera"_s,
u"Exif.Photo.ISOSpeedRatings"_s, tr("ISO speed"));
appendExivPropertyIfExist(wrapper, u"Camera"_s,
u"Exif.Photo.ExposureBiasValue"_s, tr("Exposure bias"));
appendExivPropertyIfExist(wrapper, u"Camera"_s,
u"Exif.Photo.FocalLength"_s, tr("Focal length"));
appendExivPropertyIfExist(wrapper, u"Camera"_s,
u"Exif.Photo.MaxApertureValue"_s, tr("Max aperture"));
appendExivPropertyIfExist(wrapper, u"Camera"_s,
u"Exif.Photo.MeteringMode"_s, tr("Metering mode"));
appendExivPropertyIfExist(wrapper, u"Camera"_s,
u"Exif.Photo.SubjectDistance"_s, tr("Subject distance"));
appendExivPropertyIfExist(wrapper, u"Camera"_s,
u"Exif.Photo.Flash"_s, tr("Flash mode"));
appendExivPropertyIfExist(wrapper, u"Camera"_s,
u"Exif.Photo.FocalLengthIn35mmFilm"_s, tr("35mm focal length"));
appendExivPropertyIfExist(wrapper, u"AdvancedPhoto"_s,
u"Exif.Photo.LensModel"_s, tr("Lens model"));
appendExivPropertyIfExist(wrapper, u"AdvancedPhoto"_s,
u"Exif.Photo.Contrast"_s, tr("Contrast"));
appendExivPropertyIfExist(wrapper, u"AdvancedPhoto"_s,
u"Exif.Photo.BrightnessValue"_s, tr("Brightness"));
appendExivPropertyIfExist(wrapper, u"AdvancedPhoto"_s,
u"Exif.Photo.ExposureProgram"_s, tr("Exposure program"));
appendExivPropertyIfExist(wrapper, u"AdvancedPhoto"_s,
u"Exif.Photo.Saturation"_s, tr("Saturation"));
appendExivPropertyIfExist(wrapper, u"AdvancedPhoto"_s,
u"Exif.Photo.Sharpness"_s, tr("Sharpness"));
appendExivPropertyIfExist(wrapper, u"AdvancedPhoto"_s,
u"Exif.Photo.WhiteBalance"_s, tr("White balance"));
appendExivPropertyIfExist(wrapper, u"AdvancedPhoto"_s,
u"Exif.Photo.DigitalZoomRatio"_s, tr("Digital zoom"));
appendExivPropertyIfExist(wrapper, u"AdvancedPhoto"_s,
u"Exif.Photo.ExifVersion"_s, tr("EXIF version"));
appendExivPropertyIfExist(wrapper, u"GPS"_s,
u"Exif.GPSInfo.GPSLatitudeRef"_s, tr("Latitude reference"));
appendExivPropertyIfExist(wrapper, u"GPS"_s,
u"Exif.GPSInfo.GPSLatitude"_s, tr("Latitude"));
appendExivPropertyIfExist(wrapper, u"GPS"_s,
u"Exif.GPSInfo.GPSLongitudeRef"_s, tr("Longitude reference"));
appendExivPropertyIfExist(wrapper, u"GPS"_s,
u"Exif.GPSInfo.GPSLongitude"_s, tr("Longitude"));
appendExivPropertyIfExist(wrapper, u"GPS"_s,
u"Exif.GPSInfo.GPSAltitudeRef"_s, tr("Altitude reference"));
appendExivPropertyIfExist(wrapper, u"GPS"_s,
u"Exif.GPSInfo.GPSAltitude"_s, tr("Altitude"));
}
}
QString MetadataModel::imageSize(const QSize &size)
{
QString imageSize;
if (size.isValid()) {
imageSize = tr("%1 x %2").arg(QString::number(size.width()), QString::number(size.height()));
} else {
imageSize = QLatin1Char('-');
}
return imageSize;
}
int simplegcd(int a, int b) {
return b == 0 ? a : simplegcd(b, a % b);
}
QString MetadataModel::imageSizeRatio(const QSize &size)
{
if (!size.isValid()) {
return QStringLiteral("-");
}
int gcd = simplegcd(size.width(), size.height());
return tr("%1 : %2").arg(QString::number(size.width() / gcd), QString::number(size.height() / gcd));
}
bool MetadataModel::appendSection(const QString &sectionKey, QStringView sectionDisplayName)
{
if (m_sections.contains(sectionKey)) {
return false;
}
m_sections.append(sectionKey);
m_sectionProperties[sectionKey] = qMakePair<QString, QList<QString> >(sectionDisplayName.toString(), {});
return true;
}
bool MetadataModel::appendPropertyIfNotEmpty(const QString &sectionKey, const QString &propertyKey, const QString &propertyDisplayName, const QString &propertyValue)
{
if (propertyValue.isEmpty()) return false;
return appendProperty(sectionKey, propertyKey, propertyDisplayName, propertyValue);
}
bool MetadataModel::appendProperty(const QString &sectionKey, const QString &propertyKey, QStringView propertyDisplayName, QStringView propertyValue)
{
if (!m_sections.contains(sectionKey)) {
return false;
}
QList<QString> & propertyList = m_sectionProperties[sectionKey].second;
if (!propertyList.contains(propertyKey)) {
propertyList.append(propertyKey);
}
m_properties[propertyKey] = qMakePair<QString, QString>(propertyDisplayName.toString(), propertyValue.toString());
return true;
}
bool MetadataModel::appendExivPropertyIfExist(const Exiv2Wrapper &wrapper, const QString &sectionKey, const QString &exiv2propertyKey, const QString &propertyDisplayName, bool isXmpString)
{
const QString & value = wrapper.value(exiv2propertyKey);
if (!value.isEmpty()) {
appendProperty(sectionKey, exiv2propertyKey,
propertyDisplayName.isEmpty() ? wrapper.label(exiv2propertyKey) : propertyDisplayName,
isXmpString ? Exiv2Wrapper::XmpValue(value) : value);
return true;
}
return false;
}
QModelIndex MetadataModel::index(int row, int column, const QModelIndex &parent) const
{
if (!hasIndex(row, column, parent)) {
return QModelIndex();
}
if (!parent.isValid()) {
return createIndex(row, column, RowType::SectionRow);
} else {
// internalid param: row means nth section it belongs to.
return createIndex(row, column, RowType::PropertyRow + parent.row());
}
}
QModelIndex MetadataModel::parent(const QModelIndex &child) const
{
if (!child.isValid()) {
return QModelIndex();
}
if (child.internalId() == RowType::SectionRow) {
return QModelIndex();
} else {
return createIndex(child.internalId() - RowType::PropertyRow, 0, SectionRow);
}
}
int MetadataModel::rowCount(const QModelIndex &parent) const
{
if (!parent.isValid()) {
return m_sections.count();
}
if (parent.internalId() == RowType::SectionRow) {
const QString & sectionKey = m_sections[parent.row()];
return m_sectionProperties[sectionKey].second.count();
}
return 0;
}
int MetadataModel::columnCount(const QModelIndex &) const
{
// Always key(display name) and value.
return 2;
}
QVariant MetadataModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid()) {
return QVariant();
}
if (role != Qt::DisplayRole) {
return QVariant();
}
if (index.internalId() == RowType::SectionRow) {
return (index.column() == 0) ? m_sectionProperties[m_sections[index.row()]].first
: QVariant();
} else {
int sectionIndex = index.internalId() - RowType::PropertyRow;
const QString & sectionKey = m_sections[sectionIndex];
const QList<QString> & propertyList = m_sectionProperties[sectionKey].second;
return (index.column() == 0) ? m_properties[propertyList[index.row()]].first
: m_properties[propertyList[index.row()]].second;
}
}
QVariant MetadataModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (orientation == Qt::Vertical || role != Qt::DisplayRole) {
return QVariant();
}
return section == 0 ? tr("Property") : tr("Value");
}

View File

@ -1,52 +1,52 @@
// SPDX-FileCopyrightText: 2022 Gary Wang <wzc782970009@gmail.com>
//
// SPDX-License-Identifier: MIT
#ifndef METADATAMODEL_H
#define METADATAMODEL_H
#include <QAbstractItemModel>
class Exiv2Wrapper;
class MetadataModel : public QAbstractItemModel
{
Q_OBJECT
public:
explicit MetadataModel(QObject *parent = nullptr);
~MetadataModel();
void setFile(const QString & imageFilePath);
static QString imageSize(const QSize &size);
static QString imageSizeRatio(const QSize &size);
bool appendSection(const QString & sectionKey, QStringView sectionDisplayName);
bool appendPropertyIfNotEmpty(const QString & sectionKey, const QString & propertyKey,
const QString & propertyDisplayName, const QString & propertyValue = QString());
bool appendProperty(const QString & sectionKey, const QString & propertyKey,
QStringView propertyDisplayName, QStringView propertyValue = QString());
bool appendExivPropertyIfExist(const Exiv2Wrapper & wrapper, const QString & sectionKey,
const QString & exiv2propertyKey, const QString & propertyDisplayName = QString(),
bool isXmpString = false);
private:
enum RowType : quintptr {
SectionRow,
PropertyRow,
};
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
QModelIndex parent(const QModelIndex &child) const override;
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
int columnCount(const QModelIndex & = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
// [SECTION_KEY]
QList<QString> m_sections;
// {SECTION_KEY: (SECTION_DISPLAY_NAME, [PROPERTY_KEY])}
QMap<QString, QPair<QString, QList<QString> > > m_sectionProperties;
// {PROPERTY_KEY: (PROPERTY_DISPLAY_NAME, PROPERTY_VALUE)}
QMap<QString, QPair<QString, QString> > m_properties;
};
#endif // METADATAMODEL_H
// SPDX-FileCopyrightText: 2022 Gary Wang <wzc782970009@gmail.com>
//
// SPDX-License-Identifier: MIT
#ifndef METADATAMODEL_H
#define METADATAMODEL_H
#include <QAbstractItemModel>
class Exiv2Wrapper;
class MetadataModel : public QAbstractItemModel
{
Q_OBJECT
public:
explicit MetadataModel(QObject *parent = nullptr);
~MetadataModel();
void setFile(const QString & imageFilePath);
static QString imageSize(const QSize &size);
static QString imageSizeRatio(const QSize &size);
bool appendSection(const QString & sectionKey, QStringView sectionDisplayName);
bool appendPropertyIfNotEmpty(const QString & sectionKey, const QString & propertyKey,
const QString & propertyDisplayName, const QString & propertyValue = QString());
bool appendProperty(const QString & sectionKey, const QString & propertyKey,
QStringView propertyDisplayName, QStringView propertyValue = QString());
bool appendExivPropertyIfExist(const Exiv2Wrapper & wrapper, const QString & sectionKey,
const QString & exiv2propertyKey, const QString & propertyDisplayName = QString(),
bool isXmpString = false);
private:
enum RowType : quintptr {
SectionRow,
PropertyRow,
};
QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override;
QModelIndex parent(const QModelIndex &child) const override;
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
int columnCount(const QModelIndex & = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
// [SECTION_KEY]
QList<QString> m_sections;
// {SECTION_KEY: (SECTION_DISPLAY_NAME, [PROPERTY_KEY])}
QMap<QString, QPair<QString, QList<QString> > > m_sectionProperties;
// {PROPERTY_KEY: (PROPERTY_DISPLAY_NAME, PROPERTY_VALUE)}
QMap<QString, QPair<QString, QString> > m_properties;
};
#endif // METADATAMODEL_H

View File

@ -1,86 +1,91 @@
// SPDX-FileCopyrightText: 2022 Gary Wang <wzc782970009@gmail.com>
//
// SPDX-License-Identifier: MIT
#include "navigatorview.h"
#include "graphicsview.h"
#include "opacityhelper.h"
#include <QMouseEvent>
#include <QDebug>
NavigatorView::NavigatorView(QWidget *parent)
: QGraphicsView (parent)
, m_viewportRegion(this->rect())
, m_opacityHelper(new OpacityHelper(this))
{
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setStyleSheet("background-color: rgba(0, 0, 0, 120);"
"border-radius: 3px;");
}
// doesn't take or manage its ownership
void NavigatorView::setMainView(GraphicsView *mainView)
{
m_mainView = mainView;
}
void NavigatorView::setOpacity(qreal opacity, bool animated)
{
m_opacityHelper->setOpacity(opacity, animated);
}
void NavigatorView::updateMainViewportRegion()
{
if (m_mainView != nullptr) {
m_viewportRegion = mapFromScene(m_mainView->mapToScene(m_mainView->rect()));
update();
}
}
void NavigatorView::mousePressEvent(QMouseEvent *event)
{
m_mouseDown = true;
if (m_mainView) {
m_mainView->centerOn(mapToScene(event->pos()));
update();
}
event->accept();
}
void NavigatorView::mouseMoveEvent(QMouseEvent *event)
{
if (m_mouseDown && m_mainView) {
m_mainView->centerOn(mapToScene(event->pos()));
update();
event->accept();
} else {
event->ignore();
}
}
void NavigatorView::mouseReleaseEvent(QMouseEvent *event)
{
m_mouseDown = false;
event->accept();
}
void NavigatorView::wheelEvent(QWheelEvent *event)
{
event->ignore();
return QGraphicsView::wheelEvent(event);
}
void NavigatorView::paintEvent(QPaintEvent *event)
{
QGraphicsView::paintEvent(event);
QPainter painter(viewport());
painter.setPen(QPen(Qt::gray, 2));
painter.drawRect(m_viewportRegion.boundingRect());
}
// SPDX-FileCopyrightText: 2022 Gary Wang <wzc782970009@gmail.com>
//
// SPDX-License-Identifier: MIT
#include "navigatorview.h"
#include "graphicsview.h"
#include "opacityhelper.h"
#include <QMouseEvent>
#include <QDebug>
#include <QTimer>
NavigatorView::NavigatorView(QWidget *parent)
: QGraphicsView (parent)
, m_viewportRegion(this->rect())
, m_opacityHelper(new OpacityHelper(this))
{
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setStyleSheet("background-color: rgba(0, 0, 0, 120);"
"border-radius: 3px;");
}
// doesn't take or manage its ownership
void NavigatorView::setMainView(GraphicsView *mainView)
{
m_mainView = mainView;
}
void NavigatorView::setOpacity(qreal opacity, bool animated)
{
m_opacityHelper->setOpacity(opacity, animated);
}
void NavigatorView::updateMainViewportRegion()
{
// Use QTimer::singleShot with lambda to delay the update
// This ensures all geometry updates are complete before calculating viewport region
QTimer::singleShot(0, [this]() {
if (m_mainView != nullptr) {
m_viewportRegion = mapFromScene(m_mainView->mapToScene(m_mainView->rect()));
update();
}
});
}
void NavigatorView::mousePressEvent(QMouseEvent *event)
{
m_mouseDown = true;
if (m_mainView) {
m_mainView->centerOn(mapToScene(event->pos()));
update();
}
event->accept();
}
void NavigatorView::mouseMoveEvent(QMouseEvent *event)
{
if (m_mouseDown && m_mainView) {
m_mainView->centerOn(mapToScene(event->pos()));
update();
event->accept();
} else {
event->ignore();
}
}
void NavigatorView::mouseReleaseEvent(QMouseEvent *event)
{
m_mouseDown = false;
event->accept();
}
void NavigatorView::wheelEvent(QWheelEvent *event)
{
event->ignore();
return QGraphicsView::wheelEvent(event);
}
void NavigatorView::paintEvent(QPaintEvent *event)
{
QGraphicsView::paintEvent(event);
QPainter painter(viewport());
painter.setPen(QPen(Qt::gray, 2));
painter.drawRect(m_viewportRegion.boundingRect());
}

View File

@ -1,38 +1,38 @@
// SPDX-FileCopyrightText: 2022 Gary Wang <wzc782970009@gmail.com>
//
// SPDX-License-Identifier: MIT
#ifndef NAVIGATORVIEW_H
#define NAVIGATORVIEW_H
#include <QGraphicsView>
class OpacityHelper;
class GraphicsView;
class NavigatorView : public QGraphicsView
{
Q_OBJECT
public:
NavigatorView(QWidget *parent = nullptr);
void setMainView(GraphicsView *mainView);
void setOpacity(qreal opacity, bool animated = true);
public slots:
void updateMainViewportRegion();
private:
void mousePressEvent(QMouseEvent * event) override;
void mouseMoveEvent(QMouseEvent * event) override;
void mouseReleaseEvent(QMouseEvent * event) override;
void wheelEvent(QWheelEvent *event) override;
void paintEvent(QPaintEvent *event) override;
bool m_mouseDown = false;
QPolygon m_viewportRegion;
QGraphicsView *m_mainView = nullptr;
OpacityHelper *m_opacityHelper = nullptr;
};
#endif // NAVIGATORVIEW_H
// SPDX-FileCopyrightText: 2022 Gary Wang <wzc782970009@gmail.com>
//
// SPDX-License-Identifier: MIT
#ifndef NAVIGATORVIEW_H
#define NAVIGATORVIEW_H
#include <QGraphicsView>
class OpacityHelper;
class GraphicsView;
class NavigatorView : public QGraphicsView
{
Q_OBJECT
public:
NavigatorView(QWidget *parent = nullptr);
void setMainView(GraphicsView *mainView);
void setOpacity(qreal opacity, bool animated = true);
public slots:
void updateMainViewportRegion();
private:
void mousePressEvent(QMouseEvent * event) override;
void mouseMoveEvent(QMouseEvent * event) override;
void mouseReleaseEvent(QMouseEvent * event) override;
void wheelEvent(QWheelEvent *event) override;
void paintEvent(QPaintEvent *event) override;
bool m_mouseDown = false;
QPolygon m_viewportRegion;
QGraphicsView *m_mainView = nullptr;
OpacityHelper *m_opacityHelper = nullptr;
};
#endif // NAVIGATORVIEW_H

View File

@ -1,31 +1,31 @@
// SPDX-FileCopyrightText: 2022 Gary Wang <wzc782970009@gmail.com>
//
// SPDX-License-Identifier: MIT
#include "opacityhelper.h"
#include <QGraphicsOpacityEffect>
#include <QPropertyAnimation>
OpacityHelper::OpacityHelper(QWidget *parent)
: QObject(parent)
, m_opacityFx(new QGraphicsOpacityEffect(parent))
, m_opacityAnimation(new QPropertyAnimation(m_opacityFx, "opacity"))
{
parent->setGraphicsEffect(m_opacityFx);
m_opacityAnimation->setDuration(300);
}
void OpacityHelper::setOpacity(qreal opacity, bool animated)
{
if (!animated) {
m_opacityFx->setOpacity(opacity);
return;
}
m_opacityAnimation->stop();
m_opacityAnimation->setStartValue(m_opacityFx->opacity());
m_opacityAnimation->setEndValue(opacity);
m_opacityAnimation->start();
}
// SPDX-FileCopyrightText: 2022 Gary Wang <wzc782970009@gmail.com>
//
// SPDX-License-Identifier: MIT
#include "opacityhelper.h"
#include <QGraphicsOpacityEffect>
#include <QPropertyAnimation>
OpacityHelper::OpacityHelper(QWidget *parent)
: QObject(parent)
, m_opacityFx(new QGraphicsOpacityEffect(parent))
, m_opacityAnimation(new QPropertyAnimation(m_opacityFx, "opacity"))
{
parent->setGraphicsEffect(m_opacityFx);
m_opacityAnimation->setDuration(300);
}
void OpacityHelper::setOpacity(qreal opacity, bool animated)
{
if (!animated) {
m_opacityFx->setOpacity(opacity);
return;
}
m_opacityAnimation->stop();
m_opacityAnimation->setStartValue(m_opacityFx->opacity());
m_opacityAnimation->setEndValue(opacity);
m_opacityAnimation->start();
}

View File

@ -1,27 +1,27 @@
// SPDX-FileCopyrightText: 2022 Gary Wang <wzc782970009@gmail.com>
//
// SPDX-License-Identifier: MIT
#ifndef OPACITYHELPER_H
#define OPACITYHELPER_H
#include <QWidget>
QT_BEGIN_NAMESPACE
class QGraphicsOpacityEffect;
class QPropertyAnimation;
QT_END_NAMESPACE
class OpacityHelper : QObject
{
public:
OpacityHelper(QWidget * parent);
void setOpacity(qreal opacity, bool animated = true);
protected:
QGraphicsOpacityEffect * m_opacityFx;
QPropertyAnimation * m_opacityAnimation;
};
#endif // OPACITYHELPER_H
// SPDX-FileCopyrightText: 2022 Gary Wang <wzc782970009@gmail.com>
//
// SPDX-License-Identifier: MIT
#ifndef OPACITYHELPER_H
#define OPACITYHELPER_H
#include <QWidget>
QT_BEGIN_NAMESPACE
class QGraphicsOpacityEffect;
class QPropertyAnimation;
QT_END_NAMESPACE
class OpacityHelper : QObject
{
public:
OpacityHelper(QWidget * parent);
void setOpacity(qreal opacity, bool animated = true);
protected:
QGraphicsOpacityEffect * m_opacityFx;
QPropertyAnimation * m_opacityAnimation;
};
#endif // OPACITYHELPER_H

View File

@ -1,283 +1,283 @@
// SPDX-FileCopyrightText: 2025 Gary Wang <git@blumia.net>
//
// SPDX-License-Identifier: MIT
#include "playlistmanager.h"
#include <QCollator>
#include <QDir>
#include <QFileInfo>
#include <QUrl>
PlaylistModel::PlaylistModel(QObject *parent)
: QAbstractListModel(parent)
{
}
PlaylistModel::~PlaylistModel()
= default;
void PlaylistModel::setPlaylist(const QList<QUrl> &urls)
{
beginResetModel();
m_playlist = urls;
endResetModel();
}
QModelIndex PlaylistModel::loadPlaylist(const QList<QUrl> & urls)
{
if (urls.isEmpty()) return {};
if (urls.count() == 1) {
return loadPlaylist(urls.constFirst());
} else {
setPlaylist(urls);
return index(0);
}
}
QModelIndex PlaylistModel::loadPlaylist(const QUrl &url)
{
QFileInfo info(url.toLocalFile());
QDir dir(info.path());
QString && currentFileName = info.fileName();
if (dir.path() == m_currentDir) {
int idx = indexOf(url);
return idx == -1 ? appendToPlaylist(url) : index(idx);
}
QStringList entryList = dir.entryList(
m_autoLoadSuffixes,
QDir::Files | QDir::NoSymLinks, QDir::NoSort);
QCollator collator;
collator.setNumericMode(true);
std::sort(entryList.begin(), entryList.end(), collator);
QList<QUrl> playlist;
int idx = -1;
for (int i = 0; i < entryList.count(); i++) {
const QString & fileName = entryList.at(i);
const QString & oneEntry = dir.absoluteFilePath(fileName);
const QUrl & url = QUrl::fromLocalFile(oneEntry);
playlist.append(url);
if (fileName == currentFileName) {
idx = i;
}
}
if (idx == -1) {
idx = playlist.count();
playlist.append(url);
}
m_currentDir = dir.path();
setPlaylist(playlist);
return index(idx);
}
QModelIndex PlaylistModel::appendToPlaylist(const QUrl &url)
{
const int lastIndex = rowCount();
beginInsertRows(QModelIndex(), lastIndex, lastIndex);
m_playlist.append(url);
endInsertRows();
return index(lastIndex);
}
bool PlaylistModel::removeAt(int index)
{
if (index < 0 || index >= rowCount()) return false;
beginRemoveRows(QModelIndex(), index, index);
m_playlist.removeAt(index);
endRemoveRows();
return true;
}
int PlaylistModel::indexOf(const QUrl &url) const
{
return m_playlist.indexOf(url);
}
QUrl PlaylistModel::urlByIndex(int index) const
{
return m_playlist.value(index);
}
QStringList PlaylistModel::autoLoadFilterSuffixes() const
{
return m_autoLoadSuffixes;
}
QHash<int, QByteArray> PlaylistModel::roleNames() const
{
QHash<int, QByteArray> result = QAbstractListModel::roleNames();
result.insert(UrlRole, "url");
return result;
}
int PlaylistModel::rowCount(const QModelIndex &parent) const
{
return m_playlist.count();
}
QVariant PlaylistModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid()) return {};
switch (role) {
case Qt::DisplayRole:
return m_playlist.at(index.row()).fileName();
case UrlRole:
return m_playlist.at(index.row());
}
return {};
}
PlaylistManager::PlaylistManager(QObject *parent)
: QObject(parent)
{
connect(&m_model, &PlaylistModel::rowsRemoved, this,
[this](const QModelIndex &, int, int) {
if (m_model.rowCount() <= m_currentIndex) {
setProperty("currentIndex", m_currentIndex - 1);
}
});
auto onRowCountChanged = [this](){
emit totalCountChanged(m_model.rowCount());
};
connect(&m_model, &PlaylistModel::rowsInserted, this, onRowCountChanged);
connect(&m_model, &PlaylistModel::rowsRemoved, this, onRowCountChanged);
connect(&m_model, &PlaylistModel::modelReset, this, onRowCountChanged);
}
PlaylistManager::~PlaylistManager()
{
}
PlaylistModel *PlaylistManager::model()
{
return &m_model;
}
void PlaylistManager::setPlaylist(const QList<QUrl> &urls)
{
m_model.setPlaylist(urls);
}
QModelIndex PlaylistManager::loadPlaylist(const QList<QUrl> &urls)
{
QModelIndex idx = m_model.loadPlaylist(urls);
setProperty("currentIndex", idx.row());
return idx;
}
QModelIndex PlaylistManager::loadPlaylist(const QUrl &url)
{
QModelIndex idx = m_model.loadPlaylist(url);
setProperty("currentIndex", idx.row());
return idx;
}
QModelIndex PlaylistManager::loadM3U8Playlist(const QUrl &url)
{
QFile file(url.toLocalFile());
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
QList<QUrl> urls;
while (!file.atEnd()) {
QString line = file.readLine();
if (line.startsWith('#')) {
continue;
}
QFileInfo fileInfo(file);
QUrl item = QUrl::fromUserInput(line, fileInfo.absolutePath());
urls.append(item);
}
return loadPlaylist(urls);
} else {
return {};
}
}
int PlaylistManager::totalCount() const
{
return m_model.rowCount();
}
QModelIndex PlaylistManager::previousIndex() const
{
int count = totalCount();
if (count == 0) return {};
return m_model.index(isFirstIndex() ? count - 1 : m_currentIndex - 1);
}
QModelIndex PlaylistManager::nextIndex() const
{
int count = totalCount();
if (count == 0) return {};
return m_model.index(isLastIndex() ? 0 : m_currentIndex + 1);
}
QModelIndex PlaylistManager::curIndex() const
{
return m_model.index(m_currentIndex);
}
bool PlaylistManager::isFirstIndex() const
{
return m_currentIndex == 0;
}
bool PlaylistManager::isLastIndex() const
{
return m_currentIndex + 1 == totalCount();
}
void PlaylistManager::setCurrentIndex(const QModelIndex &index)
{
if (index.isValid() && index.row() >= 0 && index.row() < totalCount()) {
setProperty("currentIndex", index.row());
}
}
QUrl PlaylistManager::urlByIndex(const QModelIndex &index)
{
return m_model.urlByIndex(index.row());
}
QString PlaylistManager::localFileByIndex(const QModelIndex &index)
{
return urlByIndex(index).toLocalFile();
}
bool PlaylistManager::removeAt(const QModelIndex &index)
{
return m_model.removeAt(index.row());
}
void PlaylistManager::setAutoLoadFilterSuffixes(const QStringList &nameFilters)
{
m_model.setProperty("autoLoadFilterSuffixes", nameFilters);
}
QList<QUrl> PlaylistManager::convertToUrlList(const QStringList &files)
{
QList<QUrl> urlList;
for (const QString & str : std::as_const(files)) {
QUrl url = QUrl::fromLocalFile(str);
if (url.isValid()) {
urlList.append(url);
}
}
return urlList;
}
// SPDX-FileCopyrightText: 2025 Gary Wang <git@blumia.net>
//
// SPDX-License-Identifier: MIT
#include "playlistmanager.h"
#include <QCollator>
#include <QDir>
#include <QFileInfo>
#include <QUrl>
PlaylistModel::PlaylistModel(QObject *parent)
: QAbstractListModel(parent)
{
}
PlaylistModel::~PlaylistModel()
= default;
void PlaylistModel::setPlaylist(const QList<QUrl> &urls)
{
beginResetModel();
m_playlist = urls;
endResetModel();
}
QModelIndex PlaylistModel::loadPlaylist(const QList<QUrl> & urls)
{
if (urls.isEmpty()) return {};
if (urls.count() == 1) {
return loadPlaylist(urls.constFirst());
} else {
setPlaylist(urls);
return index(0);
}
}
QModelIndex PlaylistModel::loadPlaylist(const QUrl &url)
{
QFileInfo info(url.toLocalFile());
QDir dir(info.path());
QString && currentFileName = info.fileName();
if (dir.path() == m_currentDir) {
int idx = indexOf(url);
return idx == -1 ? appendToPlaylist(url) : index(idx);
}
QStringList entryList = dir.entryList(
m_autoLoadSuffixes,
QDir::Files | QDir::NoSymLinks, QDir::NoSort);
QCollator collator;
collator.setNumericMode(true);
std::sort(entryList.begin(), entryList.end(), collator);
QList<QUrl> playlist;
int idx = -1;
for (int i = 0; i < entryList.count(); i++) {
const QString & fileName = entryList.at(i);
const QString & oneEntry = dir.absoluteFilePath(fileName);
const QUrl & url = QUrl::fromLocalFile(oneEntry);
playlist.append(url);
if (fileName == currentFileName) {
idx = i;
}
}
if (idx == -1) {
idx = playlist.count();
playlist.append(url);
}
m_currentDir = dir.path();
setPlaylist(playlist);
return index(idx);
}
QModelIndex PlaylistModel::appendToPlaylist(const QUrl &url)
{
const int lastIndex = rowCount();
beginInsertRows(QModelIndex(), lastIndex, lastIndex);
m_playlist.append(url);
endInsertRows();
return index(lastIndex);
}
bool PlaylistModel::removeAt(int index)
{
if (index < 0 || index >= rowCount()) return false;
beginRemoveRows(QModelIndex(), index, index);
m_playlist.removeAt(index);
endRemoveRows();
return true;
}
int PlaylistModel::indexOf(const QUrl &url) const
{
return m_playlist.indexOf(url);
}
QUrl PlaylistModel::urlByIndex(int index) const
{
return m_playlist.value(index);
}
QStringList PlaylistModel::autoLoadFilterSuffixes() const
{
return m_autoLoadSuffixes;
}
QHash<int, QByteArray> PlaylistModel::roleNames() const
{
QHash<int, QByteArray> result = QAbstractListModel::roleNames();
result.insert(UrlRole, "url");
return result;
}
int PlaylistModel::rowCount(const QModelIndex &parent) const
{
return m_playlist.count();
}
QVariant PlaylistModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid()) return {};
switch (role) {
case Qt::DisplayRole:
return m_playlist.at(index.row()).fileName();
case UrlRole:
return m_playlist.at(index.row());
}
return {};
}
PlaylistManager::PlaylistManager(QObject *parent)
: QObject(parent)
{
connect(&m_model, &PlaylistModel::rowsRemoved, this,
[this](const QModelIndex &, int, int) {
if (m_model.rowCount() <= m_currentIndex) {
setProperty("currentIndex", m_currentIndex - 1);
}
});
auto onRowCountChanged = [this](){
emit totalCountChanged(m_model.rowCount());
};
connect(&m_model, &PlaylistModel::rowsInserted, this, onRowCountChanged);
connect(&m_model, &PlaylistModel::rowsRemoved, this, onRowCountChanged);
connect(&m_model, &PlaylistModel::modelReset, this, onRowCountChanged);
}
PlaylistManager::~PlaylistManager()
{
}
PlaylistModel *PlaylistManager::model()
{
return &m_model;
}
void PlaylistManager::setPlaylist(const QList<QUrl> &urls)
{
m_model.setPlaylist(urls);
}
QModelIndex PlaylistManager::loadPlaylist(const QList<QUrl> &urls)
{
QModelIndex idx = m_model.loadPlaylist(urls);
setProperty("currentIndex", idx.row());
return idx;
}
QModelIndex PlaylistManager::loadPlaylist(const QUrl &url)
{
QModelIndex idx = m_model.loadPlaylist(url);
setProperty("currentIndex", idx.row());
return idx;
}
QModelIndex PlaylistManager::loadM3U8Playlist(const QUrl &url)
{
QFile file(url.toLocalFile());
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
QList<QUrl> urls;
while (!file.atEnd()) {
QString line = file.readLine();
if (line.startsWith('#')) {
continue;
}
QFileInfo fileInfo(file);
QUrl item = QUrl::fromUserInput(line, fileInfo.absolutePath());
urls.append(item);
}
return loadPlaylist(urls);
} else {
return {};
}
}
int PlaylistManager::totalCount() const
{
return m_model.rowCount();
}
QModelIndex PlaylistManager::previousIndex() const
{
int count = totalCount();
if (count == 0) return {};
return m_model.index(isFirstIndex() ? count - 1 : m_currentIndex - 1);
}
QModelIndex PlaylistManager::nextIndex() const
{
int count = totalCount();
if (count == 0) return {};
return m_model.index(isLastIndex() ? 0 : m_currentIndex + 1);
}
QModelIndex PlaylistManager::curIndex() const
{
return m_model.index(m_currentIndex);
}
bool PlaylistManager::isFirstIndex() const
{
return m_currentIndex == 0;
}
bool PlaylistManager::isLastIndex() const
{
return m_currentIndex + 1 == totalCount();
}
void PlaylistManager::setCurrentIndex(const QModelIndex &index)
{
if (index.isValid() && index.row() >= 0 && index.row() < totalCount()) {
setProperty("currentIndex", index.row());
}
}
QUrl PlaylistManager::urlByIndex(const QModelIndex &index)
{
return m_model.urlByIndex(index.row());
}
QString PlaylistManager::localFileByIndex(const QModelIndex &index)
{
return urlByIndex(index).toLocalFile();
}
bool PlaylistManager::removeAt(const QModelIndex &index)
{
return m_model.removeAt(index.row());
}
void PlaylistManager::setAutoLoadFilterSuffixes(const QStringList &nameFilters)
{
m_model.setProperty("autoLoadFilterSuffixes", nameFilters);
}
QList<QUrl> PlaylistManager::convertToUrlList(const QStringList &files)
{
QList<QUrl> urlList;
for (const QString & str : std::as_const(files)) {
QUrl url = QUrl::fromLocalFile(str);
if (url.isValid()) {
urlList.append(url);
}
}
return urlList;
}

View File

@ -1,88 +1,88 @@
// SPDX-FileCopyrightText: 2025 Gary Wang <git@blumia.net>
//
// SPDX-License-Identifier: MIT
#pragma once
#include <QUrl>
#include <QAbstractListModel>
class PlaylistModel : public QAbstractListModel
{
Q_OBJECT
public:
enum PlaylistRole {
UrlRole = Qt::UserRole
};
Q_ENUM(PlaylistRole)
Q_PROPERTY(QStringList autoLoadFilterSuffixes MEMBER m_autoLoadSuffixes NOTIFY autoLoadFilterSuffixesChanged)
explicit PlaylistModel(QObject *parent = nullptr);
~PlaylistModel() override;
void setPlaylist(const QList<QUrl> & urls);
QModelIndex loadPlaylist(const QList<QUrl> & urls);
QModelIndex loadPlaylist(const QUrl & url);
QModelIndex appendToPlaylist(const QUrl & url);
bool removeAt(int index);
int indexOf(const QUrl & url) const;
QUrl urlByIndex(int index) const;
QStringList autoLoadFilterSuffixes() const;
QHash<int, QByteArray> roleNames() const override;
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
signals:
void autoLoadFilterSuffixesChanged(QStringList suffixes);
private:
// model data
QList<QUrl> m_playlist;
// properties
QStringList m_autoLoadSuffixes = {};
// internal
QString m_currentDir;
};
class PlaylistManager : public QObject
{
Q_OBJECT
public:
Q_PROPERTY(int currentIndex MEMBER m_currentIndex NOTIFY currentIndexChanged)
Q_PROPERTY(QStringList autoLoadFilterSuffixes WRITE setAutoLoadFilterSuffixes)
Q_PROPERTY(PlaylistModel * model READ model CONSTANT)
explicit PlaylistManager(QObject *parent = nullptr);
~PlaylistManager();
PlaylistModel * model();
void setPlaylist(const QList<QUrl> & url);
Q_INVOKABLE QModelIndex loadPlaylist(const QList<QUrl> & urls);
Q_INVOKABLE QModelIndex loadPlaylist(const QUrl & url);
Q_INVOKABLE QModelIndex loadM3U8Playlist(const QUrl & url);
int totalCount() const;
QModelIndex previousIndex() const;
QModelIndex nextIndex() const;
QModelIndex curIndex() const;
bool isFirstIndex() const;
bool isLastIndex() const;
void setCurrentIndex(const QModelIndex & index);
QUrl urlByIndex(const QModelIndex & index);
QString localFileByIndex(const QModelIndex & index);
bool removeAt(const QModelIndex & index);
void setAutoLoadFilterSuffixes(const QStringList &nameFilters);
static QList<QUrl> convertToUrlList(const QStringList & files);
signals:
void currentIndexChanged(int index);
void totalCountChanged(int count);
private:
int m_currentIndex = -1;
PlaylistModel m_model;
};
// SPDX-FileCopyrightText: 2025 Gary Wang <git@blumia.net>
//
// SPDX-License-Identifier: MIT
#pragma once
#include <QUrl>
#include <QAbstractListModel>
class PlaylistModel : public QAbstractListModel
{
Q_OBJECT
public:
enum PlaylistRole {
UrlRole = Qt::UserRole
};
Q_ENUM(PlaylistRole)
Q_PROPERTY(QStringList autoLoadFilterSuffixes MEMBER m_autoLoadSuffixes NOTIFY autoLoadFilterSuffixesChanged)
explicit PlaylistModel(QObject *parent = nullptr);
~PlaylistModel() override;
void setPlaylist(const QList<QUrl> & urls);
QModelIndex loadPlaylist(const QList<QUrl> & urls);
QModelIndex loadPlaylist(const QUrl & url);
QModelIndex appendToPlaylist(const QUrl & url);
bool removeAt(int index);
int indexOf(const QUrl & url) const;
QUrl urlByIndex(int index) const;
QStringList autoLoadFilterSuffixes() const;
QHash<int, QByteArray> roleNames() const override;
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
signals:
void autoLoadFilterSuffixesChanged(QStringList suffixes);
private:
// model data
QList<QUrl> m_playlist;
// properties
QStringList m_autoLoadSuffixes = {};
// internal
QString m_currentDir;
};
class PlaylistManager : public QObject
{
Q_OBJECT
public:
Q_PROPERTY(int currentIndex MEMBER m_currentIndex NOTIFY currentIndexChanged)
Q_PROPERTY(QStringList autoLoadFilterSuffixes WRITE setAutoLoadFilterSuffixes)
Q_PROPERTY(PlaylistModel * model READ model CONSTANT)
explicit PlaylistManager(QObject *parent = nullptr);
~PlaylistManager();
PlaylistModel * model();
void setPlaylist(const QList<QUrl> & url);
Q_INVOKABLE QModelIndex loadPlaylist(const QList<QUrl> & urls);
Q_INVOKABLE QModelIndex loadPlaylist(const QUrl & url);
Q_INVOKABLE QModelIndex loadM3U8Playlist(const QUrl & url);
int totalCount() const;
QModelIndex previousIndex() const;
QModelIndex nextIndex() const;
QModelIndex curIndex() const;
bool isFirstIndex() const;
bool isLastIndex() const;
void setCurrentIndex(const QModelIndex & index);
QUrl urlByIndex(const QModelIndex & index);
QString localFileByIndex(const QModelIndex & index);
bool removeAt(const QModelIndex & index);
void setAutoLoadFilterSuffixes(const QStringList &nameFilters);
static QList<QUrl> convertToUrlList(const QStringList & files);
signals:
void currentIndexChanged(int index);
void totalCountChanged(int count);
private:
int m_currentIndex = -1;
PlaylistModel m_model;
};

View File

@ -1,226 +1,237 @@
// SPDX-FileCopyrightText: 2022 Gary Wang <wzc782970009@gmail.com>
//
// SPDX-License-Identifier: MIT
#include "settings.h"
#include <QApplication>
#include <QStandardPaths>
#include <QDebug>
#include <QDir>
#include <QAction>
#include <QWidget>
#include <QKeySequence>
#include <QMetaEnum>
namespace QEnumHelper
{
template <typename E>
E fromString(const QString &text, const E defaultValue)
{
bool ok;
E result = static_cast<E>(QMetaEnum::fromType<E>().keyToValue(text.toUtf8(), &ok));
if (!ok) {
return defaultValue;
}
return result;
}
template <typename E>
QString toString(E value)
{
const int intValue = static_cast<int>(value);
return QString::fromUtf8(QMetaEnum::fromType<E>().valueToKey(intValue));
}
}
Settings *Settings::m_settings_instance = nullptr;
Settings *Settings::instance()
{
if (!m_settings_instance) {
m_settings_instance = new Settings;
}
return m_settings_instance;
}
bool Settings::stayOnTop() const
{
return m_qsettings->value("stay_on_top", true).toBool();
}
bool Settings::useBuiltInCloseAnimation() const
{
return m_qsettings->value("use_built_in_close_animation", true).toBool();
}
bool Settings::useLightCheckerboard() const
{
return m_qsettings->value("use_light_checkerboard", false).toBool();
}
bool Settings::loopGallery() const
{
return m_qsettings->value("loop_gallery", true).toBool();
}
Settings::DoubleClickBehavior Settings::doubleClickBehavior() const
{
QString result = m_qsettings->value("double_click_behavior", "Close").toString();
return QEnumHelper::fromString<DoubleClickBehavior>(result, DoubleClickBehavior::Close);
}
Settings::MouseWheelBehavior Settings::mouseWheelBehavior() const
{
QString result = m_qsettings->value("mouse_wheel_behavior", "Zoom").toString();
return QEnumHelper::fromString<MouseWheelBehavior>(result, MouseWheelBehavior::Zoom);
}
Settings::WindowSizeBehavior Settings::initWindowSizeBehavior() const
{
QString result = m_qsettings->value("init_window_size_behavior", "Auto").toString();
return QEnumHelper::fromString<WindowSizeBehavior>(result, WindowSizeBehavior::Auto);
}
Qt::HighDpiScaleFactorRoundingPolicy Settings::hiDpiScaleFactorBehavior() const
{
QString result = m_qsettings->value("hidpi_scale_factor_behavior", "PassThrough").toString();
return QEnumHelper::fromString<Qt::HighDpiScaleFactorRoundingPolicy>(result, Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
}
void Settings::setStayOnTop(bool on)
{
m_qsettings->setValue("stay_on_top", on);
m_qsettings->sync();
}
void Settings::setUseBuiltInCloseAnimation(bool on)
{
m_qsettings->setValue("use_built_in_close_animation", on);
m_qsettings->sync();
}
void Settings::setUseLightCheckerboard(bool light)
{
m_qsettings->setValue("use_light_checkerboard", light);
m_qsettings->sync();
}
void Settings::setLoopGallery(bool on)
{
m_qsettings->setValue("loop_gallery", on);
m_qsettings->sync();
}
void Settings::setDoubleClickBehavior(DoubleClickBehavior dcb)
{
m_qsettings->setValue("double_click_behavior", QEnumHelper::toString(dcb));
m_qsettings->sync();
}
void Settings::setMouseWheelBehavior(MouseWheelBehavior mwb)
{
m_qsettings->setValue("mouse_wheel_behavior", QEnumHelper::toString(mwb));
m_qsettings->sync();
}
void Settings::setInitWindowSizeBehavior(WindowSizeBehavior wsb)
{
m_qsettings->setValue("init_window_size_behavior", QEnumHelper::toString(wsb));
m_qsettings->sync();
}
void Settings::setHiDpiScaleFactorBehavior(Qt::HighDpiScaleFactorRoundingPolicy hidpi)
{
m_qsettings->setValue("hidpi_scale_factor_behavior", QEnumHelper::toString(hidpi));
m_qsettings->sync();
}
void Settings::applyUserShortcuts(QWidget *widget)
{
m_qsettings->beginGroup("shortcuts");
const QStringList shortcutNames = m_qsettings->allKeys();
for (const QString & name : shortcutNames) {
QList<QKeySequence> shortcuts = m_qsettings->value(name).value<QList<QKeySequence>>();
setShortcutsForAction(widget, name, shortcuts, false);
}
m_qsettings->endGroup();
}
bool Settings::setShortcutsForAction(QWidget *widget, const QString &objectName,
QList<QKeySequence> shortcuts, bool writeConfig)
{
QAction * targetAction = nullptr;
for (QAction * action : widget->actions()) {
if (action->objectName() == objectName) {
targetAction = action;
} else {
for (const QKeySequence & shortcut : std::as_const(shortcuts)) {
if (action->shortcuts().contains(shortcut)) {
return false;
}
}
}
}
if (targetAction) {
targetAction->setShortcuts(shortcuts);
}
if (targetAction && writeConfig) {
m_qsettings->beginGroup("shortcuts");
m_qsettings->setValue(objectName, QVariant::fromValue(shortcuts));
m_qsettings->endGroup();
m_qsettings->sync();
}
return true;
}
#if defined(FLAG_PORTABLE_MODE_SUPPORT) && defined(Q_OS_WIN)
#include <windows.h>
// QCoreApplication::applicationDirPath() parses the "applicationDirPath" from arg0, which...
// 1. rely on a QApplication object instance
// but we need to call QGuiApplication::setHighDpiScaleFactorRoundingPolicy() before QApplication get created
// 2. arg0 is NOT garanteed to be the path of execution
// see also: https://stackoverflow.com/questions/383973/is-args0-guaranteed-to-be-the-path-of-execution
// This function is here mainly for #1.
QString getApplicationDirPath()
{
WCHAR buffer[MAX_PATH];
GetModuleFileNameW(NULL, buffer, MAX_PATH);
QString appPath = QString::fromWCharArray(buffer);
return appPath.left(appPath.lastIndexOf('\\'));
}
#endif // defined(FLAG_PORTABLE_MODE_SUPPORT) && defined(Q_OS_WIN)
Settings::Settings()
: QObject(qApp)
{
QString configPath;
#if defined(FLAG_PORTABLE_MODE_SUPPORT) && defined(Q_OS_WIN)
QString portableConfigDirPath = QDir(getApplicationDirPath()).absoluteFilePath("data");
QFileInfo portableConfigDirInfo(portableConfigDirPath);
if (portableConfigDirInfo.exists() && portableConfigDirInfo.isDir() && portableConfigDirInfo.isWritable()) {
// we can use it.
configPath = portableConfigDirPath;
}
#endif // defined(FLAG_PORTABLE_MODE_SUPPORT) && defined(Q_OS_WIN)
if (configPath.isEmpty()) {
// Should be %LOCALAPPDATA%\<APPNAME> under Windows, ~/.config/<APPNAME> under Linux.
configPath = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation);
}
m_qsettings = new QSettings(QDir(configPath).absoluteFilePath("config.ini"), QSettings::IniFormat, this);
qRegisterMetaType<QList<QKeySequence>>();
}
// SPDX-FileCopyrightText: 2022 Gary Wang <wzc782970009@gmail.com>
//
// SPDX-License-Identifier: MIT
#include "settings.h"
#include <QApplication>
#include <QStandardPaths>
#include <QDebug>
#include <QDir>
#include <QAction>
#include <QWidget>
#include <QKeySequence>
#include <QMetaEnum>
namespace QEnumHelper
{
template <typename E>
E fromString(const QString &text, const E defaultValue)
{
bool ok;
E result = static_cast<E>(QMetaEnum::fromType<E>().keyToValue(text.toUtf8(), &ok));
if (!ok) {
return defaultValue;
}
return result;
}
template <typename E>
QString toString(E value)
{
const int intValue = static_cast<int>(value);
return QString::fromUtf8(QMetaEnum::fromType<E>().valueToKey(intValue));
}
}
Settings *Settings::m_settings_instance = nullptr;
Settings *Settings::instance()
{
if (!m_settings_instance) {
m_settings_instance = new Settings;
}
return m_settings_instance;
}
bool Settings::stayOnTop() const
{
return m_qsettings->value("stay_on_top", true).toBool();
}
bool Settings::useBuiltInCloseAnimation() const
{
return m_qsettings->value("use_built_in_close_animation", true).toBool();
}
bool Settings::useLightCheckerboard() const
{
return m_qsettings->value("use_light_checkerboard", false).toBool();
}
bool Settings::loopGallery() const
{
return m_qsettings->value("loop_gallery", true).toBool();
}
bool Settings::autoLongImageMode() const
{
return m_qsettings->value("auto_long_image_mode", true).toBool();
}
Settings::DoubleClickBehavior Settings::doubleClickBehavior() const
{
QString result = m_qsettings->value("double_click_behavior", "Close").toString();
return QEnumHelper::fromString<DoubleClickBehavior>(result, DoubleClickBehavior::Close);
}
Settings::MouseWheelBehavior Settings::mouseWheelBehavior() const
{
QString result = m_qsettings->value("mouse_wheel_behavior", "Zoom").toString();
return QEnumHelper::fromString<MouseWheelBehavior>(result, MouseWheelBehavior::Zoom);
}
Settings::WindowSizeBehavior Settings::initWindowSizeBehavior() const
{
QString result = m_qsettings->value("init_window_size_behavior", "Auto").toString();
return QEnumHelper::fromString<WindowSizeBehavior>(result, WindowSizeBehavior::Auto);
}
Qt::HighDpiScaleFactorRoundingPolicy Settings::hiDpiScaleFactorBehavior() const
{
QString result = m_qsettings->value("hidpi_scale_factor_behavior", "PassThrough").toString();
return QEnumHelper::fromString<Qt::HighDpiScaleFactorRoundingPolicy>(result, Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
}
void Settings::setStayOnTop(bool on)
{
m_qsettings->setValue("stay_on_top", on);
m_qsettings->sync();
}
void Settings::setUseBuiltInCloseAnimation(bool on)
{
m_qsettings->setValue("use_built_in_close_animation", on);
m_qsettings->sync();
}
void Settings::setUseLightCheckerboard(bool light)
{
m_qsettings->setValue("use_light_checkerboard", light);
m_qsettings->sync();
}
void Settings::setLoopGallery(bool on)
{
m_qsettings->setValue("loop_gallery", on);
m_qsettings->sync();
}
void Settings::setAutoLongImageMode(bool on)
{
m_qsettings->setValue("auto_long_image_mode", on);
m_qsettings->sync();
}
void Settings::setDoubleClickBehavior(DoubleClickBehavior dcb)
{
m_qsettings->setValue("double_click_behavior", QEnumHelper::toString(dcb));
m_qsettings->sync();
}
void Settings::setMouseWheelBehavior(MouseWheelBehavior mwb)
{
m_qsettings->setValue("mouse_wheel_behavior", QEnumHelper::toString(mwb));
m_qsettings->sync();
}
void Settings::setInitWindowSizeBehavior(WindowSizeBehavior wsb)
{
m_qsettings->setValue("init_window_size_behavior", QEnumHelper::toString(wsb));
m_qsettings->sync();
}
void Settings::setHiDpiScaleFactorBehavior(Qt::HighDpiScaleFactorRoundingPolicy hidpi)
{
m_qsettings->setValue("hidpi_scale_factor_behavior", QEnumHelper::toString(hidpi));
m_qsettings->sync();
}
void Settings::applyUserShortcuts(QWidget *widget)
{
m_qsettings->beginGroup("shortcuts");
const QStringList shortcutNames = m_qsettings->allKeys();
for (const QString & name : shortcutNames) {
QList<QKeySequence> shortcuts = m_qsettings->value(name).value<QList<QKeySequence>>();
setShortcutsForAction(widget, name, shortcuts, false);
}
m_qsettings->endGroup();
}
bool Settings::setShortcutsForAction(QWidget *widget, const QString &objectName,
QList<QKeySequence> shortcuts, bool writeConfig)
{
QAction * targetAction = nullptr;
for (QAction * action : widget->actions()) {
if (action->objectName() == objectName) {
targetAction = action;
} else {
for (const QKeySequence & shortcut : std::as_const(shortcuts)) {
if (action->shortcuts().contains(shortcut)) {
return false;
}
}
}
}
if (targetAction) {
targetAction->setShortcuts(shortcuts);
}
if (targetAction && writeConfig) {
m_qsettings->beginGroup("shortcuts");
m_qsettings->setValue(objectName, QVariant::fromValue(shortcuts));
m_qsettings->endGroup();
m_qsettings->sync();
}
return true;
}
#if defined(FLAG_PORTABLE_MODE_SUPPORT) && defined(Q_OS_WIN)
#include <windows.h>
// QCoreApplication::applicationDirPath() parses the "applicationDirPath" from arg0, which...
// 1. rely on a QApplication object instance
// but we need to call QGuiApplication::setHighDpiScaleFactorRoundingPolicy() before QApplication get created
// 2. arg0 is NOT garanteed to be the path of execution
// see also: https://stackoverflow.com/questions/383973/is-args0-guaranteed-to-be-the-path-of-execution
// This function is here mainly for #1.
QString getApplicationDirPath()
{
WCHAR buffer[MAX_PATH];
GetModuleFileNameW(NULL, buffer, MAX_PATH);
QString appPath = QString::fromWCharArray(buffer);
return appPath.left(appPath.lastIndexOf('\\'));
}
#endif // defined(FLAG_PORTABLE_MODE_SUPPORT) && defined(Q_OS_WIN)
Settings::Settings()
: QObject(qApp)
{
QString configPath;
#if defined(FLAG_PORTABLE_MODE_SUPPORT) && defined(Q_OS_WIN)
QString portableConfigDirPath = QDir(getApplicationDirPath()).absoluteFilePath("data");
QFileInfo portableConfigDirInfo(portableConfigDirPath);
if (portableConfigDirInfo.exists() && portableConfigDirInfo.isDir() && portableConfigDirInfo.isWritable()) {
// we can use it.
configPath = portableConfigDirPath;
}
#endif // defined(FLAG_PORTABLE_MODE_SUPPORT) && defined(Q_OS_WIN)
if (configPath.isEmpty()) {
// Should be %LOCALAPPDATA%\<APPNAME> under Windows, ~/.config/<APPNAME> under Linux.
configPath = QStandardPaths::writableLocation(QStandardPaths::AppConfigLocation);
}
m_qsettings = new QSettings(QDir(configPath).absoluteFilePath("config.ini"), QSettings::IniFormat, this);
qRegisterMetaType<QList<QKeySequence>>();
}

View File

@ -1,69 +1,71 @@
// SPDX-FileCopyrightText: 2022 Gary Wang <wzc782970009@gmail.com>
//
// SPDX-License-Identifier: MIT
#pragma once
#include <QObject>
#include <QSettings>
class Settings : public QObject
{
Q_OBJECT
public:
enum DoubleClickBehavior {
Ignore,
Close,
Maximize,
FullScreen,
};
Q_ENUM(DoubleClickBehavior)
enum MouseWheelBehavior {
Zoom,
Switch,
};
Q_ENUM(MouseWheelBehavior)
enum WindowSizeBehavior {
Auto,
Maximized,
Windowed,
};
Q_ENUM(WindowSizeBehavior)
static Settings *instance();
bool stayOnTop() const;
bool useBuiltInCloseAnimation() const;
bool useLightCheckerboard() const;
bool loopGallery() const;
DoubleClickBehavior doubleClickBehavior() const;
MouseWheelBehavior mouseWheelBehavior() const;
WindowSizeBehavior initWindowSizeBehavior() const;
Qt::HighDpiScaleFactorRoundingPolicy hiDpiScaleFactorBehavior() const;
void setStayOnTop(bool on);
void setUseBuiltInCloseAnimation(bool on);
void setUseLightCheckerboard(bool light);
void setLoopGallery(bool on);
void setDoubleClickBehavior(DoubleClickBehavior dcb);
void setMouseWheelBehavior(MouseWheelBehavior mwb);
void setInitWindowSizeBehavior(WindowSizeBehavior wsb);
void setHiDpiScaleFactorBehavior(Qt::HighDpiScaleFactorRoundingPolicy hidpi);
void applyUserShortcuts(QWidget * widget);
bool setShortcutsForAction(QWidget * widget, const QString & objectName,
QList<QKeySequence> shortcuts, bool writeConfig = true);
private:
Settings();
static Settings *m_settings_instance;
QSettings *m_qsettings;
signals:
public slots:
};
// SPDX-FileCopyrightText: 2022 Gary Wang <wzc782970009@gmail.com>
//
// SPDX-License-Identifier: MIT
#pragma once
#include <QObject>
#include <QSettings>
class Settings : public QObject
{
Q_OBJECT
public:
enum DoubleClickBehavior {
Ignore,
Close,
Maximize,
FullScreen,
};
Q_ENUM(DoubleClickBehavior)
enum MouseWheelBehavior {
Zoom,
Switch,
};
Q_ENUM(MouseWheelBehavior)
enum WindowSizeBehavior {
Auto,
Maximized,
Windowed,
};
Q_ENUM(WindowSizeBehavior)
static Settings *instance();
bool stayOnTop() const;
bool useBuiltInCloseAnimation() const;
bool useLightCheckerboard() const;
bool loopGallery() const;
bool autoLongImageMode() const;
DoubleClickBehavior doubleClickBehavior() const;
MouseWheelBehavior mouseWheelBehavior() const;
WindowSizeBehavior initWindowSizeBehavior() const;
Qt::HighDpiScaleFactorRoundingPolicy hiDpiScaleFactorBehavior() const;
void setStayOnTop(bool on);
void setUseBuiltInCloseAnimation(bool on);
void setUseLightCheckerboard(bool light);
void setLoopGallery(bool on);
void setAutoLongImageMode(bool on);
void setDoubleClickBehavior(DoubleClickBehavior dcb);
void setMouseWheelBehavior(MouseWheelBehavior mwb);
void setInitWindowSizeBehavior(WindowSizeBehavior wsb);
void setHiDpiScaleFactorBehavior(Qt::HighDpiScaleFactorRoundingPolicy hidpi);
void applyUserShortcuts(QWidget * widget);
bool setShortcutsForAction(QWidget * widget, const QString & objectName,
QList<QKeySequence> shortcuts, bool writeConfig = true);
private:
Settings();
static Settings *m_settings_instance;
QSettings *m_qsettings;
signals:
public slots:
};

View File

@ -1,200 +1,207 @@
// SPDX-FileCopyrightText: 2022 Gary Wang <wzc782970009@gmail.com>
//
// SPDX-License-Identifier: MIT
#include "settingsdialog.h"
#include "settings.h"
#include "shortcutedit.h"
#include <QAction>
#include <QCheckBox>
#include <QComboBox>
#include <QFormLayout>
#include <QKeySequenceEdit>
#include <QScrollArea>
#include <QSplitter>
#include <QStringListModel>
#include <QMessageBox>
SettingsDialog::SettingsDialog(QWidget *parent)
: QDialog(parent)
, m_stayOnTop(new QCheckBox)
, m_useBuiltInCloseAnimation(new QCheckBox)
, m_useLightCheckerboard(new QCheckBox)
, m_loopGallery(new QCheckBox)
, m_doubleClickBehavior(new QComboBox)
, m_mouseWheelBehavior(new QComboBox)
, m_initWindowSizeBehavior(new QComboBox)
, m_hiDpiRoundingPolicyBehavior(new QComboBox)
{
this->setWindowTitle(tr("Settings"));
QHBoxLayout * mainLayout = new QHBoxLayout(this);
QTabWidget * settingsTabs = new QTabWidget(this);
mainLayout->addWidget(settingsTabs);
QWidget * settingsFormHolder = new QWidget;
QFormLayout * settingsForm = new QFormLayout(settingsFormHolder);
settingsTabs->addTab(settingsFormHolder, tr("Options"));
QSplitter * shortcutEditorSplitter = new QSplitter;
shortcutEditorSplitter->setOrientation(Qt::Vertical);
shortcutEditorSplitter->setChildrenCollapsible(false);
QScrollArea * shortcutScrollArea = new QScrollArea;
shortcutEditorSplitter->addWidget(shortcutScrollArea);
shortcutScrollArea->setWidgetResizable(true);
shortcutScrollArea->setMinimumHeight(200);
QWidget * shortcutsFormHolder = new QWidget;
QFormLayout * shortcutsForm = new QFormLayout(shortcutsFormHolder);
shortcutScrollArea->setWidget(shortcutsFormHolder);
settingsTabs->addTab(shortcutEditorSplitter, tr("Shortcuts"));
for (const QAction * action : parent->actions()) {
ShortcutEdit * shortcutEdit = new ShortcutEdit;
shortcutEdit->setObjectName(QLatin1String("shortcut_") + action->objectName());
shortcutEdit->setShortcuts(action->shortcuts());
shortcutsForm->addRow(action->text(), shortcutEdit);
connect(shortcutEdit, &ShortcutEdit::editButtonClicked, this, [=](){
if (shortcutEditorSplitter->count() == 1) shortcutEditorSplitter->addWidget(new QWidget);
ShortcutEditor * shortcutEditor = new ShortcutEditor(shortcutEdit);
shortcutEditor->setDescription(tr("Editing shortcuts for action \"%1\":").arg(action->text()));
QWidget * oldEditor = shortcutEditorSplitter->replaceWidget(1, shortcutEditor);
shortcutEditorSplitter->setSizes({shortcutEditorSplitter->height(), 1});
oldEditor->deleteLater();
});
connect(shortcutEdit, &ShortcutEdit::applyShortcutsRequested, this, [=](QList<QKeySequence> newShortcuts){
bool succ = Settings::instance()->setShortcutsForAction(parent, shortcutEdit->objectName().mid(9),
newShortcuts);
if (!succ) {
QMessageBox::warning(this, tr("Failed to set shortcuts"),
tr("Please check if shortcuts are duplicated with existing shortcuts."));
}
shortcutEdit->setShortcuts(action->shortcuts());
});
}
static QList< QPair<Settings::DoubleClickBehavior, QString> > _dc_options {
{ Settings::DoubleClickBehavior::Ignore, tr("Do nothing") },
{ Settings::DoubleClickBehavior::Close, tr("Close the window") },
{ Settings::DoubleClickBehavior::Maximize, tr("Toggle maximize") },
{ Settings::DoubleClickBehavior::FullScreen, tr("Toggle fullscreen") }
};
static QList< QPair<Settings::MouseWheelBehavior, QString> > _mw_options {
{ Settings::MouseWheelBehavior::Zoom, tr("Zoom in and out") },
{ Settings::MouseWheelBehavior::Switch, tr("View next or previous item") }
};
static QList< QPair<Settings::WindowSizeBehavior, QString> > _iws_options {
{ Settings::WindowSizeBehavior::Auto, tr("Auto size") },
{ Settings::WindowSizeBehavior::Maximized, tr("Maximized") },
{ Settings::WindowSizeBehavior::Windowed, tr("Windowed") }
};
static QList< QPair<Qt::HighDpiScaleFactorRoundingPolicy, QString> > _hidpi_options {
{ Qt::HighDpiScaleFactorRoundingPolicy::Round, tr("Round (Integer scaling)", "This option means round up for .5 and above") },
{ Qt::HighDpiScaleFactorRoundingPolicy::Ceil, tr("Ceil (Integer scaling)", "This option means always round up") },
{ Qt::HighDpiScaleFactorRoundingPolicy::Floor, tr("Floor (Integer scaling)", "This option means always round down") },
{ Qt::HighDpiScaleFactorRoundingPolicy::PassThrough, tr("Follow system (Fractional scaling)", "This option means don't round") }
};
QStringList dcbDropDown;
for (const QPair<Settings::DoubleClickBehavior, QString> & dcOption : _dc_options) {
dcbDropDown.append(dcOption.second);
}
QStringList mwbDropDown;
for (const QPair<Settings::MouseWheelBehavior, QString> & mwOption : _mw_options) {
mwbDropDown.append(mwOption.second);
}
QStringList iwsbDropDown;
for (const QPair<Settings::WindowSizeBehavior, QString> & iwsOption : _iws_options) {
iwsbDropDown.append(iwsOption.second);
}
QStringList hidpiDropDown;
for (const QPair<Qt::HighDpiScaleFactorRoundingPolicy, QString> & hidpiOption : _hidpi_options) {
hidpiDropDown.append(hidpiOption.second);
}
settingsForm->addRow(tr("Stay on top when start-up"), m_stayOnTop);
settingsForm->addRow(tr("Use built-in close window animation"), m_useBuiltInCloseAnimation);
settingsForm->addRow(tr("Use light-color checkerboard"), m_useLightCheckerboard);
settingsForm->addRow(tr("Loop the loaded gallery"), m_loopGallery);
settingsForm->addRow(tr("Double-click behavior"), m_doubleClickBehavior);
settingsForm->addRow(tr("Mouse wheel behavior"), m_mouseWheelBehavior);
settingsForm->addRow(tr("Default window size"), m_initWindowSizeBehavior);
settingsForm->addRow(tr("HiDPI scale factor rounding policy"), m_hiDpiRoundingPolicyBehavior);
m_stayOnTop->setChecked(Settings::instance()->stayOnTop());
m_useBuiltInCloseAnimation->setChecked(Settings::instance()->useBuiltInCloseAnimation());
m_useLightCheckerboard->setChecked(Settings::instance()->useLightCheckerboard());
m_loopGallery->setChecked(Settings::instance()->loopGallery());
m_doubleClickBehavior->setModel(new QStringListModel(dcbDropDown));
Settings::DoubleClickBehavior dcb = Settings::instance()->doubleClickBehavior();
m_doubleClickBehavior->setCurrentIndex(static_cast<int>(dcb));
m_mouseWheelBehavior->setModel(new QStringListModel(mwbDropDown));
Settings::MouseWheelBehavior mwb = Settings::instance()->mouseWheelBehavior();
m_mouseWheelBehavior->setCurrentIndex(static_cast<int>(mwb));
m_initWindowSizeBehavior->setModel(new QStringListModel(iwsbDropDown));
Settings::WindowSizeBehavior iwsb = Settings::instance()->initWindowSizeBehavior();
m_initWindowSizeBehavior->setCurrentIndex(static_cast<int>(iwsb));
m_hiDpiRoundingPolicyBehavior->setModel(new QStringListModel(hidpiDropDown));
Qt::HighDpiScaleFactorRoundingPolicy hidpi = Settings::instance()->hiDpiScaleFactorBehavior();
for (int i = 0; i < _hidpi_options.count(); i++) {
if (_hidpi_options.at(i).first == hidpi) {
m_hiDpiRoundingPolicyBehavior->setCurrentIndex(i);
break;
}
}
#if QT_VERSION >= QT_VERSION_CHECK(6, 7, 0)
# define QCHECKBOX_CHECKSTATECHANGED QCheckBox::checkStateChanged
# define QT_CHECKSTATE Qt::CheckState
#else
# define QCHECKBOX_CHECKSTATECHANGED QCheckBox::stateChanged
# define QT_CHECKSTATE int
#endif // QT_VERSION >= QT_VERSION_CHECK(6, 7, 0)
connect(m_stayOnTop, &QCHECKBOX_CHECKSTATECHANGED, this, [ = ](QT_CHECKSTATE state){
Settings::instance()->setStayOnTop(state == Qt::Checked);
});
connect(m_useBuiltInCloseAnimation, &QCHECKBOX_CHECKSTATECHANGED, this, [ = ](QT_CHECKSTATE state){
Settings::instance()->setUseBuiltInCloseAnimation(state == Qt::Checked);
});
connect(m_useLightCheckerboard, &QCHECKBOX_CHECKSTATECHANGED, this, [ = ](QT_CHECKSTATE state){
Settings::instance()->setUseLightCheckerboard(state == Qt::Checked);
});
connect(m_loopGallery, &QCHECKBOX_CHECKSTATECHANGED, this, [ = ](QT_CHECKSTATE state){
Settings::instance()->setLoopGallery(state == Qt::Checked);
});
connect(m_doubleClickBehavior, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [ = ](int index){
Settings::instance()->setDoubleClickBehavior(_dc_options.at(index).first);
});
connect(m_mouseWheelBehavior, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [ = ](int index){
Settings::instance()->setMouseWheelBehavior(_mw_options.at(index).first);
});
connect(m_initWindowSizeBehavior, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [ = ](int index){
Settings::instance()->setInitWindowSizeBehavior(_iws_options.at(index).first);
});
connect(m_hiDpiRoundingPolicyBehavior, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [ = ](int index){
Settings::instance()->setHiDpiScaleFactorBehavior(_hidpi_options.at(index).first);
});
adjustSize();
setWindowFlag(Qt::WindowContextHelpButtonHint, false);
}
SettingsDialog::~SettingsDialog()
{
}
// SPDX-FileCopyrightText: 2022 Gary Wang <wzc782970009@gmail.com>
//
// SPDX-License-Identifier: MIT
#include "settingsdialog.h"
#include "settings.h"
#include "shortcutedit.h"
#include <QAction>
#include <QCheckBox>
#include <QComboBox>
#include <QFormLayout>
#include <QKeySequenceEdit>
#include <QScrollArea>
#include <QSplitter>
#include <QStringListModel>
#include <QMessageBox>
SettingsDialog::SettingsDialog(QWidget *parent)
: QDialog(parent)
, m_stayOnTop(new QCheckBox)
, m_useBuiltInCloseAnimation(new QCheckBox)
, m_useLightCheckerboard(new QCheckBox)
, m_loopGallery(new QCheckBox)
, m_autoLongImageMode(new QCheckBox)
, m_doubleClickBehavior(new QComboBox)
, m_mouseWheelBehavior(new QComboBox)
, m_initWindowSizeBehavior(new QComboBox)
, m_hiDpiRoundingPolicyBehavior(new QComboBox)
{
this->setWindowTitle(tr("Settings"));
QHBoxLayout * mainLayout = new QHBoxLayout(this);
QTabWidget * settingsTabs = new QTabWidget(this);
mainLayout->addWidget(settingsTabs);
QWidget * settingsFormHolder = new QWidget;
QFormLayout * settingsForm = new QFormLayout(settingsFormHolder);
settingsTabs->addTab(settingsFormHolder, tr("Options"));
QSplitter * shortcutEditorSplitter = new QSplitter;
shortcutEditorSplitter->setOrientation(Qt::Vertical);
shortcutEditorSplitter->setChildrenCollapsible(false);
QScrollArea * shortcutScrollArea = new QScrollArea;
shortcutEditorSplitter->addWidget(shortcutScrollArea);
shortcutScrollArea->setWidgetResizable(true);
shortcutScrollArea->setMinimumHeight(200);
QWidget * shortcutsFormHolder = new QWidget;
QFormLayout * shortcutsForm = new QFormLayout(shortcutsFormHolder);
shortcutScrollArea->setWidget(shortcutsFormHolder);
settingsTabs->addTab(shortcutEditorSplitter, tr("Shortcuts"));
for (const QAction * action : parent->actions()) {
ShortcutEdit * shortcutEdit = new ShortcutEdit;
shortcutEdit->setObjectName(QLatin1String("shortcut_") + action->objectName());
shortcutEdit->setShortcuts(action->shortcuts());
shortcutsForm->addRow(action->text(), shortcutEdit);
connect(shortcutEdit, &ShortcutEdit::editButtonClicked, this, [=](){
if (shortcutEditorSplitter->count() == 1) shortcutEditorSplitter->addWidget(new QWidget);
ShortcutEditor * shortcutEditor = new ShortcutEditor(shortcutEdit);
shortcutEditor->setDescription(tr("Editing shortcuts for action \"%1\":").arg(action->text()));
QWidget * oldEditor = shortcutEditorSplitter->replaceWidget(1, shortcutEditor);
shortcutEditorSplitter->setSizes({shortcutEditorSplitter->height(), 1});
oldEditor->deleteLater();
});
connect(shortcutEdit, &ShortcutEdit::applyShortcutsRequested, this, [=](QList<QKeySequence> newShortcuts){
bool succ = Settings::instance()->setShortcutsForAction(parent, shortcutEdit->objectName().mid(9),
newShortcuts);
if (!succ) {
QMessageBox::warning(this, tr("Failed to set shortcuts"),
tr("Please check if shortcuts are duplicated with existing shortcuts."));
}
shortcutEdit->setShortcuts(action->shortcuts());
});
}
static QList< QPair<Settings::DoubleClickBehavior, QString> > _dc_options {
{ Settings::DoubleClickBehavior::Ignore, tr("Do nothing") },
{ Settings::DoubleClickBehavior::Close, tr("Close the window") },
{ Settings::DoubleClickBehavior::Maximize, tr("Toggle maximize") },
{ Settings::DoubleClickBehavior::FullScreen, tr("Toggle fullscreen") }
};
static QList< QPair<Settings::MouseWheelBehavior, QString> > _mw_options {
{ Settings::MouseWheelBehavior::Zoom, tr("Zoom in and out") },
{ Settings::MouseWheelBehavior::Switch, tr("View next or previous item") }
};
static QList< QPair<Settings::WindowSizeBehavior, QString> > _iws_options {
{ Settings::WindowSizeBehavior::Auto, tr("Auto size") },
{ Settings::WindowSizeBehavior::Maximized, tr("Maximized") },
{ Settings::WindowSizeBehavior::Windowed, tr("Windowed") }
};
static QList< QPair<Qt::HighDpiScaleFactorRoundingPolicy, QString> > _hidpi_options {
{ Qt::HighDpiScaleFactorRoundingPolicy::Round, tr("Round (Integer scaling)", "This option means round up for .5 and above") },
{ Qt::HighDpiScaleFactorRoundingPolicy::Ceil, tr("Ceil (Integer scaling)", "This option means always round up") },
{ Qt::HighDpiScaleFactorRoundingPolicy::Floor, tr("Floor (Integer scaling)", "This option means always round down") },
{ Qt::HighDpiScaleFactorRoundingPolicy::PassThrough, tr("Follow system (Fractional scaling)", "This option means don't round") }
};
QStringList dcbDropDown;
for (const QPair<Settings::DoubleClickBehavior, QString> & dcOption : _dc_options) {
dcbDropDown.append(dcOption.second);
}
QStringList mwbDropDown;
for (const QPair<Settings::MouseWheelBehavior, QString> & mwOption : _mw_options) {
mwbDropDown.append(mwOption.second);
}
QStringList iwsbDropDown;
for (const QPair<Settings::WindowSizeBehavior, QString> & iwsOption : _iws_options) {
iwsbDropDown.append(iwsOption.second);
}
QStringList hidpiDropDown;
for (const QPair<Qt::HighDpiScaleFactorRoundingPolicy, QString> & hidpiOption : _hidpi_options) {
hidpiDropDown.append(hidpiOption.second);
}
settingsForm->addRow(tr("Stay on top when start-up"), m_stayOnTop);
settingsForm->addRow(tr("Use built-in close window animation"), m_useBuiltInCloseAnimation);
settingsForm->addRow(tr("Use light-color checkerboard"), m_useLightCheckerboard);
settingsForm->addRow(tr("Loop the loaded gallery"), m_loopGallery);
settingsForm->addRow(tr("Auto long image mode"), m_autoLongImageMode);
settingsForm->addRow(tr("Double-click behavior"), m_doubleClickBehavior);
settingsForm->addRow(tr("Mouse wheel behavior"), m_mouseWheelBehavior);
settingsForm->addRow(tr("Default window size"), m_initWindowSizeBehavior);
settingsForm->addRow(tr("HiDPI scale factor rounding policy"), m_hiDpiRoundingPolicyBehavior);
m_stayOnTop->setChecked(Settings::instance()->stayOnTop());
m_useBuiltInCloseAnimation->setChecked(Settings::instance()->useBuiltInCloseAnimation());
m_useLightCheckerboard->setChecked(Settings::instance()->useLightCheckerboard());
m_loopGallery->setChecked(Settings::instance()->loopGallery());
m_autoLongImageMode->setChecked(Settings::instance()->autoLongImageMode());
m_doubleClickBehavior->setModel(new QStringListModel(dcbDropDown));
Settings::DoubleClickBehavior dcb = Settings::instance()->doubleClickBehavior();
m_doubleClickBehavior->setCurrentIndex(static_cast<int>(dcb));
m_mouseWheelBehavior->setModel(new QStringListModel(mwbDropDown));
Settings::MouseWheelBehavior mwb = Settings::instance()->mouseWheelBehavior();
m_mouseWheelBehavior->setCurrentIndex(static_cast<int>(mwb));
m_initWindowSizeBehavior->setModel(new QStringListModel(iwsbDropDown));
Settings::WindowSizeBehavior iwsb = Settings::instance()->initWindowSizeBehavior();
m_initWindowSizeBehavior->setCurrentIndex(static_cast<int>(iwsb));
m_hiDpiRoundingPolicyBehavior->setModel(new QStringListModel(hidpiDropDown));
Qt::HighDpiScaleFactorRoundingPolicy hidpi = Settings::instance()->hiDpiScaleFactorBehavior();
for (int i = 0; i < _hidpi_options.count(); i++) {
if (_hidpi_options.at(i).first == hidpi) {
m_hiDpiRoundingPolicyBehavior->setCurrentIndex(i);
break;
}
}
#if QT_VERSION >= QT_VERSION_CHECK(6, 7, 0)
# define QCHECKBOX_CHECKSTATECHANGED QCheckBox::checkStateChanged
# define QT_CHECKSTATE Qt::CheckState
#else
# define QCHECKBOX_CHECKSTATECHANGED QCheckBox::stateChanged
# define QT_CHECKSTATE int
#endif // QT_VERSION >= QT_VERSION_CHECK(6, 7, 0)
connect(m_stayOnTop, &QCHECKBOX_CHECKSTATECHANGED, this, [ = ](QT_CHECKSTATE state){
Settings::instance()->setStayOnTop(state == Qt::Checked);
});
connect(m_useBuiltInCloseAnimation, &QCHECKBOX_CHECKSTATECHANGED, this, [ = ](QT_CHECKSTATE state){
Settings::instance()->setUseBuiltInCloseAnimation(state == Qt::Checked);
});
connect(m_useLightCheckerboard, &QCHECKBOX_CHECKSTATECHANGED, this, [ = ](QT_CHECKSTATE state){
Settings::instance()->setUseLightCheckerboard(state == Qt::Checked);
});
connect(m_loopGallery, &QCHECKBOX_CHECKSTATECHANGED, this, [ = ](QT_CHECKSTATE state){
Settings::instance()->setLoopGallery(state == Qt::Checked);
});
connect(m_autoLongImageMode, &QCHECKBOX_CHECKSTATECHANGED, this, [ = ](QT_CHECKSTATE state){
Settings::instance()->setAutoLongImageMode(state == Qt::Checked);
});
connect(m_doubleClickBehavior, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [ = ](int index){
Settings::instance()->setDoubleClickBehavior(_dc_options.at(index).first);
});
connect(m_mouseWheelBehavior, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [ = ](int index){
Settings::instance()->setMouseWheelBehavior(_mw_options.at(index).first);
});
connect(m_initWindowSizeBehavior, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [ = ](int index){
Settings::instance()->setInitWindowSizeBehavior(_iws_options.at(index).first);
});
connect(m_hiDpiRoundingPolicyBehavior, QOverload<int>::of(&QComboBox::currentIndexChanged), this, [ = ](int index){
Settings::instance()->setHiDpiScaleFactorBehavior(_hidpi_options.at(index).first);
});
adjustSize();
setWindowFlag(Qt::WindowContextHelpButtonHint, false);
}
SettingsDialog::~SettingsDialog()
{
}

View File

@ -1,35 +1,36 @@
// SPDX-FileCopyrightText: 2022 Gary Wang <wzc782970009@gmail.com>
//
// SPDX-License-Identifier: MIT
#ifndef SETTINGSDIALOG_H
#define SETTINGSDIALOG_H
#include <QObject>
#include <QDialog>
class QCheckBox;
class QComboBox;
class SettingsDialog : public QDialog
{
Q_OBJECT
public:
explicit SettingsDialog(QWidget *parent = nullptr);
~SettingsDialog();
signals:
public slots:
private:
QCheckBox * m_stayOnTop = nullptr;
QCheckBox * m_useBuiltInCloseAnimation = nullptr;
QCheckBox * m_useLightCheckerboard = nullptr;
QCheckBox * m_loopGallery = nullptr;
QComboBox * m_doubleClickBehavior = nullptr;
QComboBox * m_mouseWheelBehavior = nullptr;
QComboBox * m_initWindowSizeBehavior = nullptr;
QComboBox * m_hiDpiRoundingPolicyBehavior = nullptr;
};
#endif // SETTINGSDIALOG_H
// SPDX-FileCopyrightText: 2022 Gary Wang <wzc782970009@gmail.com>
//
// SPDX-License-Identifier: MIT
#ifndef SETTINGSDIALOG_H
#define SETTINGSDIALOG_H
#include <QObject>
#include <QDialog>
class QCheckBox;
class QComboBox;
class SettingsDialog : public QDialog
{
Q_OBJECT
public:
explicit SettingsDialog(QWidget *parent = nullptr);
~SettingsDialog();
signals:
public slots:
private:
QCheckBox * m_stayOnTop = nullptr;
QCheckBox * m_useBuiltInCloseAnimation = nullptr;
QCheckBox * m_useLightCheckerboard = nullptr;
QCheckBox * m_loopGallery = nullptr;
QCheckBox * m_autoLongImageMode = nullptr;
QComboBox * m_doubleClickBehavior = nullptr;
QComboBox * m_mouseWheelBehavior = nullptr;
QComboBox * m_initWindowSizeBehavior = nullptr;
QComboBox * m_hiDpiRoundingPolicyBehavior = nullptr;
};
#endif // SETTINGSDIALOG_H

View File

@ -1,38 +1,38 @@
// SPDX-FileCopyrightText: 2022 Gary Wang <wzc782970009@gmail.com>
//
// SPDX-License-Identifier: MIT
#include "toolbutton.h"
#include "actionmanager.h"
#include "opacityhelper.h"
#include <QPainter>
#include <QGraphicsOpacityEffect>
#include <QPropertyAnimation>
ToolButton::ToolButton(bool hoverColor, QWidget *parent)
: QPushButton(parent)
, m_opacityHelper(new OpacityHelper(this))
{
setFlat(true);
QString qss = "QPushButton {"
"background: transparent;"
"}";
if (hoverColor) {
qss += "QPushButton:hover {"
"background: red;"
"}";
}
setStyleSheet(qss);
}
void ToolButton::setIconResourcePath(const QString &iconp)
{
this->setIcon(ActionManager::loadHidpiIcon(iconp, this->iconSize()));
}
void ToolButton::setOpacity(qreal opacity, bool animated)
{
m_opacityHelper->setOpacity(opacity, animated);
}
// SPDX-FileCopyrightText: 2022 Gary Wang <wzc782970009@gmail.com>
//
// SPDX-License-Identifier: MIT
#include "toolbutton.h"
#include "actionmanager.h"
#include "opacityhelper.h"
#include <QPainter>
#include <QGraphicsOpacityEffect>
#include <QPropertyAnimation>
ToolButton::ToolButton(bool hoverColor, QWidget *parent)
: QPushButton(parent)
, m_opacityHelper(new OpacityHelper(this))
{
setFlat(true);
QString qss = "QPushButton {"
"background: transparent;"
"}";
if (hoverColor) {
qss += "QPushButton:hover {"
"background: red;"
"}";
}
setStyleSheet(qss);
}
void ToolButton::setIconResourcePath(const QString &iconp)
{
this->setIcon(ActionManager::loadHidpiIcon(iconp, this->iconSize()));
}
void ToolButton::setOpacity(qreal opacity, bool animated)
{
m_opacityHelper->setOpacity(opacity, animated);
}

View File

@ -1,25 +1,25 @@
// SPDX-FileCopyrightText: 2022 Gary Wang <wzc782970009@gmail.com>
//
// SPDX-License-Identifier: MIT
#ifndef TOOLBUTTON_H
#define TOOLBUTTON_H
#include <QPushButton>
class OpacityHelper;
class ToolButton : public QPushButton
{
Q_OBJECT
public:
ToolButton(bool hoverColor = false, QWidget * parent = nullptr);
void setIconResourcePath(const QString &iconp);
public slots:
void setOpacity(qreal opacity, bool animated = true);
private:
OpacityHelper * m_opacityHelper;
};
#endif // TOOLBUTTON_H
// SPDX-FileCopyrightText: 2022 Gary Wang <wzc782970009@gmail.com>
//
// SPDX-License-Identifier: MIT
#ifndef TOOLBUTTON_H
#define TOOLBUTTON_H
#include <QPushButton>
class OpacityHelper;
class ToolButton : public QPushButton
{
Q_OBJECT
public:
ToolButton(bool hoverColor = false, QWidget * parent = nullptr);
void setIconResourcePath(const QString &iconp);
public slots:
void setOpacity(qreal opacity, bool animated = true);
private:
OpacityHelper * m_opacityHelper;
};
#endif // TOOLBUTTON_H

View File

@ -174,7 +174,7 @@
<context>
<name>GraphicsScene</name>
<message>
<location filename="../mainwindow.cpp" line="276"/>
<location filename="../mainwindow.cpp" line="292"/>
<location filename="../graphicsscene.cpp" line="100"/>
<source>Drag image here</source>
<translation>Arrossegueu una imatge aquí</translation>
@ -209,189 +209,194 @@
<context>
<name>MainWindow</name>
<message>
<location filename="../mainwindow.cpp" line="181"/>
<location filename="../mainwindow.cpp" line="545"/>
<location filename="../mainwindow.cpp" line="190"/>
<location filename="../mainwindow.cpp" line="561"/>
<source>File url list is empty</source>
<translation>La llista d&apos;ubicacions és buida</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="445"/>
<location filename="../mainwindow.cpp" line="461"/>
<source>&amp;Copy</source>
<translation>&amp;Copia</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="553"/>
<location filename="../mainwindow.cpp" line="569"/>
<source>Image data is invalid</source>
<translation>Les dades de la imatge no són vàlides</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="560"/>
<location filename="../mainwindow.cpp" line="576"/>
<source>Not supported mimedata: %1</source>
<translation>El tipus MIME no és compatible: %1</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="759"/>
<location filename="../mainwindow.cpp" line="783"/>
<source>Image From Clipboard</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="777"/>
<location filename="../mainwindow.cpp" line="801"/>
<source>Are you sure you want to move &quot;%1&quot; to recycle bin?</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="781"/>
<location filename="../mainwindow.cpp" line="805"/>
<source>Failed to move file to trash</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="782"/>
<location filename="../mainwindow.cpp" line="806"/>
<source>Move to trash failed, it might caused by file permission issue, file system limitation, or platform limitation.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="114"/>
<location filename="../actionmanager.cpp" line="106"/>
<source>Copy P&amp;ixmap</source>
<translation>Copia el &amp;mapa de píxels</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="115"/>
<location filename="../actionmanager.cpp" line="107"/>
<source>Copy &amp;File Path</source>
<translation>Copia el camí del &amp;fitxer</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="133"/>
<location filename="../actionmanager.cpp" line="125"/>
<source>Properties</source>
<translation>Propietats</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="118"/>
<location filename="../actionmanager.cpp" line="110"/>
<location filename="../aboutdialog.cpp" line="41"/>
<source>Stay on top</source>
<translation>Mantén a sobre</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="119"/>
<location filename="../actionmanager.cpp" line="111"/>
<location filename="../aboutdialog.cpp" line="44"/>
<source>Protected mode</source>
<translation>Mode protegit</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="120"/>
<location filename="../actionmanager.cpp" line="112"/>
<location filename="../aboutdialog.cpp" line="47"/>
<source>Keep transformation</source>
<comment>The &apos;transformation&apos; means the flip/rotation status that currently applied to the image view</comment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="99"/>
<location filename="../actionmanager.cpp" line="90"/>
<source>Zoom in</source>
<translation>Amplia</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="100"/>
<location filename="../actionmanager.cpp" line="91"/>
<source>Zoom out</source>
<translation>Redueix</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="108"/>
<location filename="../actionmanager.cpp" line="99"/>
<source>Pause/Resume Animation</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="109"/>
<location filename="../actionmanager.cpp" line="100"/>
<source>Animation Go to Next Frame</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="111"/>
<location filename="../actionmanager.cpp" line="102"/>
<source>Flip &amp;Horizontally</source>
<translation>Inverteix &amp;horitzontalment</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="112"/>
<location filename="../actionmanager.cpp" line="103"/>
<source>Fit to view</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="113"/>
<location filename="../actionmanager.cpp" line="104"/>
<source>Fit to width</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="116"/>
<location filename="../actionmanager.cpp" line="105"/>
<source>Fit long image</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="108"/>
<source>&amp;Paste</source>
<translation>&amp;Enganxa</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="101"/>
<location filename="../actionmanager.cpp" line="92"/>
<source>Toggle Checkerboard</source>
<translation>Commuta el tauler d&apos;escacs</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="95"/>
<location filename="../actionmanager.cpp" line="86"/>
<source>&amp;Open...</source>
<translation>&amp;Obre...</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="97"/>
<location filename="../actionmanager.cpp" line="88"/>
<source>Actual size</source>
<translation>Mida real</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="98"/>
<location filename="../actionmanager.cpp" line="89"/>
<source>Toggle maximize</source>
<translation>Commuta la maximització</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="102"/>
<location filename="../actionmanager.cpp" line="93"/>
<source>Rotate right</source>
<translation>Commuta la maximització</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="103"/>
<location filename="../actionmanager.cpp" line="94"/>
<source>Rotate left</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="105"/>
<location filename="../actionmanager.cpp" line="96"/>
<source>Previous image</source>
<translation>Imatge anterior</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="106"/>
<location filename="../actionmanager.cpp" line="97"/>
<source>Next image</source>
<translation>Imatge següent</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="776"/>
<location filename="../actionmanager.cpp" line="117"/>
<location filename="../mainwindow.cpp" line="800"/>
<location filename="../actionmanager.cpp" line="109"/>
<source>Move to Trash</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="121"/>
<location filename="../actionmanager.cpp" line="113"/>
<source>Configure...</source>
<translation>Configura...</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="122"/>
<location filename="../actionmanager.cpp" line="114"/>
<source>Help</source>
<translation>Ajuda</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="125"/>
<location filename="../actionmanager.cpp" line="117"/>
<source>Show in File Explorer</source>
<comment>File Explorer is the name of explorer.exe under Windows</comment>
<translation>Mostra al navegador de fitxers</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="131"/>
<location filename="../actionmanager.cpp" line="123"/>
<source>Show in directory</source>
<translation>Mostra a la carpeta</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="134"/>
<location filename="../actionmanager.cpp" line="126"/>
<source>Quit</source>
<translation>Surt</translation>
</message>
@ -722,141 +727,146 @@
<context>
<name>SettingsDialog</name>
<message>
<location filename="../settingsdialog.cpp" line="31"/>
<location filename="../settingsdialog.cpp" line="32"/>
<source>Settings</source>
<translation>Paràmetres</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="39"/>
<location filename="../settingsdialog.cpp" line="40"/>
<source>Options</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="51"/>
<location filename="../settingsdialog.cpp" line="52"/>
<source>Shortcuts</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="61"/>
<location filename="../settingsdialog.cpp" line="62"/>
<source>Editing shortcuts for action &quot;%1&quot;:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="70"/>
<location filename="../settingsdialog.cpp" line="71"/>
<source>Failed to set shortcuts</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="71"/>
<location filename="../settingsdialog.cpp" line="72"/>
<source>Please check if shortcuts are duplicated with existing shortcuts.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="78"/>
<location filename="../settingsdialog.cpp" line="79"/>
<source>Do nothing</source>
<translation>No facis res</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="79"/>
<location filename="../settingsdialog.cpp" line="80"/>
<source>Close the window</source>
<translation>Tanca la finestra</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="80"/>
<location filename="../settingsdialog.cpp" line="81"/>
<source>Toggle maximize</source>
<translation>Commuta la maximització</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="81"/>
<location filename="../settingsdialog.cpp" line="82"/>
<source>Toggle fullscreen</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="85"/>
<location filename="../settingsdialog.cpp" line="86"/>
<source>Zoom in and out</source>
<translation>Amplia i redueix</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="86"/>
<location filename="../settingsdialog.cpp" line="87"/>
<source>View next or previous item</source>
<translation>Mostra l&apos;element següent o l&apos;anterior</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="90"/>
<location filename="../settingsdialog.cpp" line="91"/>
<source>Auto size</source>
<translation>Mida automàtica</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="91"/>
<location filename="../settingsdialog.cpp" line="92"/>
<source>Maximized</source>
<translation>Maximitza</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="92"/>
<location filename="../settingsdialog.cpp" line="93"/>
<source>Windowed</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="96"/>
<location filename="../settingsdialog.cpp" line="97"/>
<source>Round (Integer scaling)</source>
<comment>This option means round up for .5 and above</comment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="97"/>
<location filename="../settingsdialog.cpp" line="98"/>
<source>Ceil (Integer scaling)</source>
<comment>This option means always round up</comment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="98"/>
<location filename="../settingsdialog.cpp" line="99"/>
<source>Floor (Integer scaling)</source>
<comment>This option means always round down</comment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="99"/>
<location filename="../settingsdialog.cpp" line="100"/>
<source>Follow system (Fractional scaling)</source>
<comment>This option means don&apos;t round</comment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="122"/>
<location filename="../settingsdialog.cpp" line="123"/>
<source>Stay on top when start-up</source>
<translation>Mantingues a sobre a l&apos;inici</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="123"/>
<location filename="../settingsdialog.cpp" line="124"/>
<source>Use built-in close window animation</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="124"/>
<location filename="../settingsdialog.cpp" line="125"/>
<source>Use light-color checkerboard</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="125"/>
<location filename="../settingsdialog.cpp" line="126"/>
<source>Loop the loaded gallery</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="126"/>
<location filename="../settingsdialog.cpp" line="127"/>
<source>Auto long image mode</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="128"/>
<source>Double-click behavior</source>
<translation>Comportament del doble clic</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="127"/>
<location filename="../settingsdialog.cpp" line="129"/>
<source>Mouse wheel behavior</source>
<translation>Comportament de la roda del ratolí</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="128"/>
<location filename="../settingsdialog.cpp" line="130"/>
<source>Default window size</source>
<translation>Mida de la finestra per defecte</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="129"/>
<location filename="../settingsdialog.cpp" line="131"/>
<source>HiDPI scale factor rounding policy</source>
<translation type="unfinished"></translation>
</message>
@ -864,7 +874,7 @@
<context>
<name>ShortcutEdit</name>
<message>
<location filename="../shortcutedit.cpp" line="109"/>
<location filename="../shortcutedit.cpp" line="104"/>
<source>No shortcuts</source>
<translation type="unfinished"></translation>
</message>
@ -872,7 +882,7 @@
<context>
<name>ShortcutEditor</name>
<message>
<location filename="../shortcutedit.cpp" line="75"/>
<location filename="../shortcutedit.cpp" line="70"/>
<source>Shortcut #%1</source>
<translation type="unfinished"></translation>
</message>

View File

@ -178,7 +178,7 @@
<context>
<name>GraphicsScene</name>
<message>
<location filename="../mainwindow.cpp" line="276"/>
<location filename="../mainwindow.cpp" line="292"/>
<location filename="../graphicsscene.cpp" line="100"/>
<source>Drag image here</source>
<translation>Ziehen Sie das Bild hierher</translation>
@ -213,189 +213,194 @@
<context>
<name>MainWindow</name>
<message>
<location filename="../mainwindow.cpp" line="181"/>
<location filename="../mainwindow.cpp" line="545"/>
<location filename="../mainwindow.cpp" line="190"/>
<location filename="../mainwindow.cpp" line="561"/>
<source>File url list is empty</source>
<translation>Die Datei-URL-Liste ist leer</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="445"/>
<location filename="../mainwindow.cpp" line="461"/>
<source>&amp;Copy</source>
<translation>&amp;Kopieren</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="553"/>
<location filename="../mainwindow.cpp" line="569"/>
<source>Image data is invalid</source>
<translation>Bilddaten sind ungültig</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="560"/>
<location filename="../mainwindow.cpp" line="576"/>
<source>Not supported mimedata: %1</source>
<translation>Nicht unterstützte Mimedaten: %1</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="759"/>
<location filename="../mainwindow.cpp" line="783"/>
<source>Image From Clipboard</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="777"/>
<location filename="../mainwindow.cpp" line="801"/>
<source>Are you sure you want to move &quot;%1&quot; to recycle bin?</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="781"/>
<location filename="../mainwindow.cpp" line="805"/>
<source>Failed to move file to trash</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="782"/>
<location filename="../mainwindow.cpp" line="806"/>
<source>Move to trash failed, it might caused by file permission issue, file system limitation, or platform limitation.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="114"/>
<location filename="../actionmanager.cpp" line="106"/>
<source>Copy P&amp;ixmap</source>
<translation>P&amp;ixmap kopieren</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="115"/>
<location filename="../actionmanager.cpp" line="107"/>
<source>Copy &amp;File Path</source>
<translation>&amp;Dateipfad kopieren</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="133"/>
<location filename="../actionmanager.cpp" line="125"/>
<source>Properties</source>
<translation>Eigenschaften</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="118"/>
<location filename="../actionmanager.cpp" line="110"/>
<location filename="../aboutdialog.cpp" line="41"/>
<source>Stay on top</source>
<translation>Oben bleiben</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="119"/>
<location filename="../actionmanager.cpp" line="111"/>
<location filename="../aboutdialog.cpp" line="44"/>
<source>Protected mode</source>
<translation>Geschützter Modus</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="120"/>
<location filename="../actionmanager.cpp" line="112"/>
<location filename="../aboutdialog.cpp" line="47"/>
<source>Keep transformation</source>
<comment>The &apos;transformation&apos; means the flip/rotation status that currently applied to the image view</comment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="99"/>
<location filename="../actionmanager.cpp" line="90"/>
<source>Zoom in</source>
<translation>Hineinzoomen</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="100"/>
<location filename="../actionmanager.cpp" line="91"/>
<source>Zoom out</source>
<translation>Herauszoomen</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="108"/>
<location filename="../actionmanager.cpp" line="99"/>
<source>Pause/Resume Animation</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="109"/>
<location filename="../actionmanager.cpp" line="100"/>
<source>Animation Go to Next Frame</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="111"/>
<location filename="../actionmanager.cpp" line="102"/>
<source>Flip &amp;Horizontally</source>
<translation>&amp;Horizontal spiegeln</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="112"/>
<location filename="../actionmanager.cpp" line="103"/>
<source>Fit to view</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="113"/>
<location filename="../actionmanager.cpp" line="104"/>
<source>Fit to width</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="116"/>
<location filename="../actionmanager.cpp" line="105"/>
<source>Fit long image</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="108"/>
<source>&amp;Paste</source>
<translation>%Einfügen</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="101"/>
<location filename="../actionmanager.cpp" line="92"/>
<source>Toggle Checkerboard</source>
<translation>Schachbrettmuster umschalten</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="95"/>
<location filename="../actionmanager.cpp" line="86"/>
<source>&amp;Open...</source>
<translation>&amp;Öffnen...</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="97"/>
<location filename="../actionmanager.cpp" line="88"/>
<source>Actual size</source>
<translation>Tatsächliche Größe</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="98"/>
<location filename="../actionmanager.cpp" line="89"/>
<source>Toggle maximize</source>
<translation>Maximieren umschalten</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="102"/>
<location filename="../actionmanager.cpp" line="93"/>
<source>Rotate right</source>
<translation>Nach rechts drehen</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="103"/>
<location filename="../actionmanager.cpp" line="94"/>
<source>Rotate left</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="105"/>
<location filename="../actionmanager.cpp" line="96"/>
<source>Previous image</source>
<translation>Vorheriges Bild</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="106"/>
<location filename="../actionmanager.cpp" line="97"/>
<source>Next image</source>
<translation>Nächstes Bild</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="776"/>
<location filename="../actionmanager.cpp" line="117"/>
<location filename="../mainwindow.cpp" line="800"/>
<location filename="../actionmanager.cpp" line="109"/>
<source>Move to Trash</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="121"/>
<location filename="../actionmanager.cpp" line="113"/>
<source>Configure...</source>
<translation>Konfigurieren&#xa0;</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="122"/>
<location filename="../actionmanager.cpp" line="114"/>
<source>Help</source>
<translation>Hilfe</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="125"/>
<location filename="../actionmanager.cpp" line="117"/>
<source>Show in File Explorer</source>
<comment>File Explorer is the name of explorer.exe under Windows</comment>
<translation>Im Dateiexplorer zeigen</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="131"/>
<location filename="../actionmanager.cpp" line="123"/>
<source>Show in directory</source>
<translation>Im Verzeichnis zeigen</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="134"/>
<location filename="../actionmanager.cpp" line="126"/>
<source>Quit</source>
<translation>Beenden</translation>
</message>
@ -726,141 +731,146 @@
<context>
<name>SettingsDialog</name>
<message>
<location filename="../settingsdialog.cpp" line="31"/>
<location filename="../settingsdialog.cpp" line="32"/>
<source>Settings</source>
<translation>Einstellungen</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="39"/>
<location filename="../settingsdialog.cpp" line="40"/>
<source>Options</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="51"/>
<location filename="../settingsdialog.cpp" line="52"/>
<source>Shortcuts</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="61"/>
<location filename="../settingsdialog.cpp" line="62"/>
<source>Editing shortcuts for action &quot;%1&quot;:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="70"/>
<location filename="../settingsdialog.cpp" line="71"/>
<source>Failed to set shortcuts</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="71"/>
<location filename="../settingsdialog.cpp" line="72"/>
<source>Please check if shortcuts are duplicated with existing shortcuts.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="78"/>
<location filename="../settingsdialog.cpp" line="79"/>
<source>Do nothing</source>
<translation>Nichts tun</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="79"/>
<location filename="../settingsdialog.cpp" line="80"/>
<source>Close the window</source>
<translation>Fenster schließen</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="80"/>
<location filename="../settingsdialog.cpp" line="81"/>
<source>Toggle maximize</source>
<translation>Maximieren umschalten</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="81"/>
<location filename="../settingsdialog.cpp" line="82"/>
<source>Toggle fullscreen</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="85"/>
<location filename="../settingsdialog.cpp" line="86"/>
<source>Zoom in and out</source>
<translation>Hinein- und Hinauszoomen</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="86"/>
<location filename="../settingsdialog.cpp" line="87"/>
<source>View next or previous item</source>
<translation>Zeige nächstes oder vorheriges Element</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="90"/>
<location filename="../settingsdialog.cpp" line="91"/>
<source>Auto size</source>
<translation>Automatische Größe</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="91"/>
<location filename="../settingsdialog.cpp" line="92"/>
<source>Maximized</source>
<translation>Maximiert</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="92"/>
<location filename="../settingsdialog.cpp" line="93"/>
<source>Windowed</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="96"/>
<location filename="../settingsdialog.cpp" line="97"/>
<source>Round (Integer scaling)</source>
<comment>This option means round up for .5 and above</comment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="97"/>
<location filename="../settingsdialog.cpp" line="98"/>
<source>Ceil (Integer scaling)</source>
<comment>This option means always round up</comment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="98"/>
<location filename="../settingsdialog.cpp" line="99"/>
<source>Floor (Integer scaling)</source>
<comment>This option means always round down</comment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="99"/>
<location filename="../settingsdialog.cpp" line="100"/>
<source>Follow system (Fractional scaling)</source>
<comment>This option means don&apos;t round</comment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="122"/>
<location filename="../settingsdialog.cpp" line="123"/>
<source>Stay on top when start-up</source>
<translation>Beim Start oben bleiben</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="123"/>
<location filename="../settingsdialog.cpp" line="124"/>
<source>Use built-in close window animation</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="124"/>
<location filename="../settingsdialog.cpp" line="125"/>
<source>Use light-color checkerboard</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="125"/>
<location filename="../settingsdialog.cpp" line="126"/>
<source>Loop the loaded gallery</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="126"/>
<location filename="../settingsdialog.cpp" line="127"/>
<source>Auto long image mode</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="128"/>
<source>Double-click behavior</source>
<translation>Doppelklickverhalten</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="127"/>
<location filename="../settingsdialog.cpp" line="129"/>
<source>Mouse wheel behavior</source>
<translation>Mausradverhalten</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="128"/>
<location filename="../settingsdialog.cpp" line="130"/>
<source>Default window size</source>
<translation>Standard-Fenstergröße</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="129"/>
<location filename="../settingsdialog.cpp" line="131"/>
<source>HiDPI scale factor rounding policy</source>
<translation type="unfinished"></translation>
</message>
@ -868,7 +878,7 @@
<context>
<name>ShortcutEdit</name>
<message>
<location filename="../shortcutedit.cpp" line="109"/>
<location filename="../shortcutedit.cpp" line="104"/>
<source>No shortcuts</source>
<translation type="unfinished"></translation>
</message>
@ -876,7 +886,7 @@
<context>
<name>ShortcutEditor</name>
<message>
<location filename="../shortcutedit.cpp" line="75"/>
<location filename="../shortcutedit.cpp" line="70"/>
<source>Shortcut #%1</source>
<translation type="unfinished"></translation>
</message>

View File

@ -174,7 +174,7 @@
<context>
<name>GraphicsScene</name>
<message>
<location filename="../mainwindow.cpp" line="276"/>
<location filename="../mainwindow.cpp" line="292"/>
<location filename="../graphicsscene.cpp" line="100"/>
<source>Drag image here</source>
<translation type="unfinished"></translation>
@ -197,189 +197,194 @@
<context>
<name>MainWindow</name>
<message>
<location filename="../mainwindow.cpp" line="181"/>
<location filename="../mainwindow.cpp" line="545"/>
<location filename="../mainwindow.cpp" line="190"/>
<location filename="../mainwindow.cpp" line="561"/>
<source>File url list is empty</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="445"/>
<location filename="../mainwindow.cpp" line="461"/>
<source>&amp;Copy</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="553"/>
<location filename="../mainwindow.cpp" line="569"/>
<source>Image data is invalid</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="560"/>
<location filename="../mainwindow.cpp" line="576"/>
<source>Not supported mimedata: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="759"/>
<location filename="../mainwindow.cpp" line="783"/>
<source>Image From Clipboard</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="777"/>
<location filename="../mainwindow.cpp" line="801"/>
<source>Are you sure you want to move &quot;%1&quot; to recycle bin?</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="781"/>
<location filename="../mainwindow.cpp" line="805"/>
<source>Failed to move file to trash</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="782"/>
<location filename="../mainwindow.cpp" line="806"/>
<source>Move to trash failed, it might caused by file permission issue, file system limitation, or platform limitation.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="114"/>
<location filename="../actionmanager.cpp" line="106"/>
<source>Copy P&amp;ixmap</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="115"/>
<location filename="../actionmanager.cpp" line="107"/>
<source>Copy &amp;File Path</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="133"/>
<location filename="../actionmanager.cpp" line="125"/>
<source>Properties</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="118"/>
<location filename="../actionmanager.cpp" line="110"/>
<location filename="../aboutdialog.cpp" line="41"/>
<source>Stay on top</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="119"/>
<location filename="../actionmanager.cpp" line="111"/>
<location filename="../aboutdialog.cpp" line="44"/>
<source>Protected mode</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="120"/>
<location filename="../actionmanager.cpp" line="112"/>
<location filename="../aboutdialog.cpp" line="47"/>
<source>Keep transformation</source>
<comment>The &apos;transformation&apos; means the flip/rotation status that currently applied to the image view</comment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="99"/>
<location filename="../actionmanager.cpp" line="90"/>
<source>Zoom in</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="100"/>
<location filename="../actionmanager.cpp" line="91"/>
<source>Zoom out</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="108"/>
<location filename="../actionmanager.cpp" line="99"/>
<source>Pause/Resume Animation</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="109"/>
<location filename="../actionmanager.cpp" line="100"/>
<source>Animation Go to Next Frame</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="111"/>
<location filename="../actionmanager.cpp" line="102"/>
<source>Flip &amp;Horizontally</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="112"/>
<location filename="../actionmanager.cpp" line="103"/>
<source>Fit to view</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="113"/>
<location filename="../actionmanager.cpp" line="104"/>
<source>Fit to width</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="116"/>
<location filename="../actionmanager.cpp" line="105"/>
<source>Fit long image</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="108"/>
<source>&amp;Paste</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="101"/>
<location filename="../actionmanager.cpp" line="92"/>
<source>Toggle Checkerboard</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="95"/>
<location filename="../actionmanager.cpp" line="86"/>
<source>&amp;Open...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="97"/>
<location filename="../actionmanager.cpp" line="88"/>
<source>Actual size</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="98"/>
<location filename="../actionmanager.cpp" line="89"/>
<source>Toggle maximize</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="102"/>
<location filename="../actionmanager.cpp" line="93"/>
<source>Rotate right</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="103"/>
<location filename="../actionmanager.cpp" line="94"/>
<source>Rotate left</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="105"/>
<location filename="../actionmanager.cpp" line="96"/>
<source>Previous image</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="106"/>
<location filename="../actionmanager.cpp" line="97"/>
<source>Next image</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="776"/>
<location filename="../actionmanager.cpp" line="117"/>
<location filename="../mainwindow.cpp" line="800"/>
<location filename="../actionmanager.cpp" line="109"/>
<source>Move to Trash</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="121"/>
<location filename="../actionmanager.cpp" line="113"/>
<source>Configure...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="122"/>
<location filename="../actionmanager.cpp" line="114"/>
<source>Help</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="125"/>
<location filename="../actionmanager.cpp" line="117"/>
<source>Show in File Explorer</source>
<comment>File Explorer is the name of explorer.exe under Windows</comment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="131"/>
<location filename="../actionmanager.cpp" line="123"/>
<source>Show in directory</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="134"/>
<location filename="../actionmanager.cpp" line="126"/>
<source>Quit</source>
<translation type="unfinished"></translation>
</message>
@ -710,141 +715,146 @@
<context>
<name>SettingsDialog</name>
<message>
<location filename="../settingsdialog.cpp" line="31"/>
<location filename="../settingsdialog.cpp" line="32"/>
<source>Settings</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="39"/>
<location filename="../settingsdialog.cpp" line="40"/>
<source>Options</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="51"/>
<location filename="../settingsdialog.cpp" line="52"/>
<source>Shortcuts</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="61"/>
<location filename="../settingsdialog.cpp" line="62"/>
<source>Editing shortcuts for action &quot;%1&quot;:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="70"/>
<location filename="../settingsdialog.cpp" line="71"/>
<source>Failed to set shortcuts</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="71"/>
<location filename="../settingsdialog.cpp" line="72"/>
<source>Please check if shortcuts are duplicated with existing shortcuts.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="78"/>
<location filename="../settingsdialog.cpp" line="79"/>
<source>Do nothing</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="79"/>
<location filename="../settingsdialog.cpp" line="80"/>
<source>Close the window</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="80"/>
<location filename="../settingsdialog.cpp" line="81"/>
<source>Toggle maximize</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="81"/>
<location filename="../settingsdialog.cpp" line="82"/>
<source>Toggle fullscreen</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="85"/>
<location filename="../settingsdialog.cpp" line="86"/>
<source>Zoom in and out</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="86"/>
<location filename="../settingsdialog.cpp" line="87"/>
<source>View next or previous item</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="90"/>
<location filename="../settingsdialog.cpp" line="91"/>
<source>Auto size</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="91"/>
<location filename="../settingsdialog.cpp" line="92"/>
<source>Maximized</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="92"/>
<location filename="../settingsdialog.cpp" line="93"/>
<source>Windowed</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="96"/>
<location filename="../settingsdialog.cpp" line="97"/>
<source>Round (Integer scaling)</source>
<comment>This option means round up for .5 and above</comment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="97"/>
<location filename="../settingsdialog.cpp" line="98"/>
<source>Ceil (Integer scaling)</source>
<comment>This option means always round up</comment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="98"/>
<location filename="../settingsdialog.cpp" line="99"/>
<source>Floor (Integer scaling)</source>
<comment>This option means always round down</comment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="99"/>
<location filename="../settingsdialog.cpp" line="100"/>
<source>Follow system (Fractional scaling)</source>
<comment>This option means don&apos;t round</comment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="122"/>
<location filename="../settingsdialog.cpp" line="123"/>
<source>Stay on top when start-up</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="123"/>
<location filename="../settingsdialog.cpp" line="124"/>
<source>Use built-in close window animation</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="124"/>
<location filename="../settingsdialog.cpp" line="125"/>
<source>Use light-color checkerboard</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="125"/>
<location filename="../settingsdialog.cpp" line="126"/>
<source>Loop the loaded gallery</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="126"/>
<source>Double-click behavior</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="127"/>
<source>Mouse wheel behavior</source>
<source>Auto long image mode</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="128"/>
<source>Default window size</source>
<source>Double-click behavior</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="129"/>
<source>Mouse wheel behavior</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="130"/>
<source>Default window size</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="131"/>
<source>HiDPI scale factor rounding policy</source>
<translation type="unfinished"></translation>
</message>
@ -852,7 +862,7 @@
<context>
<name>ShortcutEdit</name>
<message>
<location filename="../shortcutedit.cpp" line="109"/>
<location filename="../shortcutedit.cpp" line="104"/>
<source>No shortcuts</source>
<translation type="unfinished"></translation>
</message>
@ -860,7 +870,7 @@
<context>
<name>ShortcutEditor</name>
<message>
<location filename="../shortcutedit.cpp" line="75"/>
<location filename="../shortcutedit.cpp" line="70"/>
<source>Shortcut #%1</source>
<translation type="unfinished"></translation>
</message>

View File

@ -178,7 +178,7 @@
<context>
<name>GraphicsScene</name>
<message>
<location filename="../mainwindow.cpp" line="276"/>
<location filename="../mainwindow.cpp" line="292"/>
<location filename="../graphicsscene.cpp" line="100"/>
<source>Drag image here</source>
<translation>Arrastre una imagen aquí</translation>
@ -213,189 +213,194 @@
<context>
<name>MainWindow</name>
<message>
<location filename="../mainwindow.cpp" line="181"/>
<location filename="../mainwindow.cpp" line="545"/>
<location filename="../mainwindow.cpp" line="190"/>
<location filename="../mainwindow.cpp" line="561"/>
<source>File url list is empty</source>
<translation>La lista de ubicaciones está vacía</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="445"/>
<location filename="../mainwindow.cpp" line="461"/>
<source>&amp;Copy</source>
<translation>&amp;Copiar</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="553"/>
<location filename="../mainwindow.cpp" line="569"/>
<source>Image data is invalid</source>
<translation>Los datos de la imagen no son válidos</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="560"/>
<location filename="../mainwindow.cpp" line="576"/>
<source>Not supported mimedata: %1</source>
<translation>El tipo MIME no es compatible: %1</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="759"/>
<location filename="../mainwindow.cpp" line="783"/>
<source>Image From Clipboard</source>
<translation>Imagen del portapapeles</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="777"/>
<location filename="../mainwindow.cpp" line="801"/>
<source>Are you sure you want to move &quot;%1&quot; to recycle bin?</source>
<translation>¿Estás seguro de que quieres mover &quot;%1&quot; a la papelera de reciclaje?</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="781"/>
<location filename="../mainwindow.cpp" line="805"/>
<source>Failed to move file to trash</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="782"/>
<location filename="../mainwindow.cpp" line="806"/>
<source>Move to trash failed, it might caused by file permission issue, file system limitation, or platform limitation.</source>
<translation>Mover a la papelera ha fallado, puede deberse a un problema con los permisos de los archivos, una limitación del sistema de archivos o una limitación de la plataforma.</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="114"/>
<location filename="../actionmanager.cpp" line="106"/>
<source>Copy P&amp;ixmap</source>
<translation>Copiar &amp;mapa de píxeles</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="115"/>
<location filename="../actionmanager.cpp" line="107"/>
<source>Copy &amp;File Path</source>
<translation>Copiar &amp;ruta de archivo</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="133"/>
<location filename="../actionmanager.cpp" line="125"/>
<source>Properties</source>
<translation>Propiedades</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="118"/>
<location filename="../actionmanager.cpp" line="110"/>
<location filename="../aboutdialog.cpp" line="41"/>
<source>Stay on top</source>
<translation>Mantener encima</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="119"/>
<location filename="../actionmanager.cpp" line="111"/>
<location filename="../aboutdialog.cpp" line="44"/>
<source>Protected mode</source>
<translation>Modo protegido</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="120"/>
<location filename="../actionmanager.cpp" line="112"/>
<location filename="../aboutdialog.cpp" line="47"/>
<source>Keep transformation</source>
<comment>The &apos;transformation&apos; means the flip/rotation status that currently applied to the image view</comment>
<translation>Conservar la transformación</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="99"/>
<location filename="../actionmanager.cpp" line="90"/>
<source>Zoom in</source>
<translation>Ampliar</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="100"/>
<location filename="../actionmanager.cpp" line="91"/>
<source>Zoom out</source>
<translation>Reducir</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="108"/>
<location filename="../actionmanager.cpp" line="99"/>
<source>Pause/Resume Animation</source>
<translation>Pausar/Reanudar animación</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="109"/>
<location filename="../actionmanager.cpp" line="100"/>
<source>Animation Go to Next Frame</source>
<translation>Ir al siguiente fotograma</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="111"/>
<location filename="../actionmanager.cpp" line="102"/>
<source>Flip &amp;Horizontally</source>
<translation>Voltear &amp;horizontalmente</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="112"/>
<location filename="../actionmanager.cpp" line="103"/>
<source>Fit to view</source>
<translation>Para visualizar</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="113"/>
<location filename="../actionmanager.cpp" line="104"/>
<source>Fit to width</source>
<translation>Ajustar al ancho</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="116"/>
<location filename="../actionmanager.cpp" line="105"/>
<source>Fit long image</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="108"/>
<source>&amp;Paste</source>
<translation>&amp;Pegar</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="101"/>
<location filename="../actionmanager.cpp" line="92"/>
<source>Toggle Checkerboard</source>
<translation>Activar/desactivar el tablero de ajedrez</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="95"/>
<location filename="../actionmanager.cpp" line="86"/>
<source>&amp;Open...</source>
<translation>&amp;Abrir...</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="97"/>
<location filename="../actionmanager.cpp" line="88"/>
<source>Actual size</source>
<translation>Tamaño real</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="98"/>
<location filename="../actionmanager.cpp" line="89"/>
<source>Toggle maximize</source>
<translation>Maximizar/desmaximizar</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="102"/>
<location filename="../actionmanager.cpp" line="93"/>
<source>Rotate right</source>
<translation>Girar a la derecha</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="103"/>
<location filename="../actionmanager.cpp" line="94"/>
<source>Rotate left</source>
<translation>Girar a la izquierda</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="105"/>
<location filename="../actionmanager.cpp" line="96"/>
<source>Previous image</source>
<translation>Imagen anterior</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="106"/>
<location filename="../actionmanager.cpp" line="97"/>
<source>Next image</source>
<translation>Imagen siguiente</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="776"/>
<location filename="../actionmanager.cpp" line="117"/>
<location filename="../mainwindow.cpp" line="800"/>
<location filename="../actionmanager.cpp" line="109"/>
<source>Move to Trash</source>
<translation>Mover a la papelera</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="121"/>
<location filename="../actionmanager.cpp" line="113"/>
<source>Configure...</source>
<translation>Configurar...</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="122"/>
<location filename="../actionmanager.cpp" line="114"/>
<source>Help</source>
<translation>Ayuda</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="125"/>
<location filename="../actionmanager.cpp" line="117"/>
<source>Show in File Explorer</source>
<comment>File Explorer is the name of explorer.exe under Windows</comment>
<translation>Mostrar en el Explorador de archivos</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="131"/>
<location filename="../actionmanager.cpp" line="123"/>
<source>Show in directory</source>
<translation>Mostrar en la carpeta</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="134"/>
<location filename="../actionmanager.cpp" line="126"/>
<source>Quit</source>
<translation>Salir</translation>
</message>
@ -726,141 +731,146 @@
<context>
<name>SettingsDialog</name>
<message>
<location filename="../settingsdialog.cpp" line="31"/>
<location filename="../settingsdialog.cpp" line="32"/>
<source>Settings</source>
<translation>Preferencias</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="39"/>
<location filename="../settingsdialog.cpp" line="40"/>
<source>Options</source>
<translation>Opciones</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="51"/>
<location filename="../settingsdialog.cpp" line="52"/>
<source>Shortcuts</source>
<translation>Atajos</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="61"/>
<location filename="../settingsdialog.cpp" line="62"/>
<source>Editing shortcuts for action &quot;%1&quot;:</source>
<translation>Editando atajos para la acción &quot;%1&quot;:</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="70"/>
<location filename="../settingsdialog.cpp" line="71"/>
<source>Failed to set shortcuts</source>
<translation>No se pudieron establecer accesos directos</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="71"/>
<location filename="../settingsdialog.cpp" line="72"/>
<source>Please check if shortcuts are duplicated with existing shortcuts.</source>
<translation>Por favor, verifique si los accesos directos están duplicados.</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="78"/>
<location filename="../settingsdialog.cpp" line="79"/>
<source>Do nothing</source>
<translation>No hacer nada</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="79"/>
<location filename="../settingsdialog.cpp" line="80"/>
<source>Close the window</source>
<translation>Cerrar la ventana</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="80"/>
<location filename="../settingsdialog.cpp" line="81"/>
<source>Toggle maximize</source>
<translation>Maximizar/desmaximizar</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="81"/>
<location filename="../settingsdialog.cpp" line="82"/>
<source>Toggle fullscreen</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="85"/>
<location filename="../settingsdialog.cpp" line="86"/>
<source>Zoom in and out</source>
<translation>Ampliar y reducir</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="86"/>
<location filename="../settingsdialog.cpp" line="87"/>
<source>View next or previous item</source>
<translation>Mostrar el elemento siguiente/anterior</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="90"/>
<location filename="../settingsdialog.cpp" line="91"/>
<source>Auto size</source>
<translation>Tamaño automático</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="91"/>
<location filename="../settingsdialog.cpp" line="92"/>
<source>Maximized</source>
<translation>Maximizar</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="92"/>
<location filename="../settingsdialog.cpp" line="93"/>
<source>Windowed</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="96"/>
<location filename="../settingsdialog.cpp" line="97"/>
<source>Round (Integer scaling)</source>
<comment>This option means round up for .5 and above</comment>
<translation>Redondeo (escala de enteros)</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="97"/>
<location filename="../settingsdialog.cpp" line="98"/>
<source>Ceil (Integer scaling)</source>
<comment>This option means always round up</comment>
<translation>Ceil (redondear enteros hacia arriba)</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="98"/>
<location filename="../settingsdialog.cpp" line="99"/>
<source>Floor (Integer scaling)</source>
<comment>This option means always round down</comment>
<translation>Floor (redondear enteros hacia abajo)</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="99"/>
<location filename="../settingsdialog.cpp" line="100"/>
<source>Follow system (Fractional scaling)</source>
<comment>This option means don&apos;t round</comment>
<translation>Redondeo (redondear los enteros)</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="122"/>
<location filename="../settingsdialog.cpp" line="123"/>
<source>Stay on top when start-up</source>
<translation>Mantener encima al inicio</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="123"/>
<location filename="../settingsdialog.cpp" line="124"/>
<source>Use built-in close window animation</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="124"/>
<location filename="../settingsdialog.cpp" line="125"/>
<source>Use light-color checkerboard</source>
<translation>Utilice un tablero de ajedrez de color claro</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="125"/>
<location filename="../settingsdialog.cpp" line="126"/>
<source>Loop the loaded gallery</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="126"/>
<location filename="../settingsdialog.cpp" line="127"/>
<source>Auto long image mode</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="128"/>
<source>Double-click behavior</source>
<translation>Comportamiento del doble clic</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="127"/>
<location filename="../settingsdialog.cpp" line="129"/>
<source>Mouse wheel behavior</source>
<translation>Comportamiento de la rueda del ratón</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="128"/>
<location filename="../settingsdialog.cpp" line="130"/>
<source>Default window size</source>
<translation>Tamaño de la ventana por defecto</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="129"/>
<location filename="../settingsdialog.cpp" line="131"/>
<source>HiDPI scale factor rounding policy</source>
<translation>Política de redondeo del factor de escala HiDPI</translation>
</message>
@ -868,7 +878,7 @@
<context>
<name>ShortcutEdit</name>
<message>
<location filename="../shortcutedit.cpp" line="109"/>
<location filename="../shortcutedit.cpp" line="104"/>
<source>No shortcuts</source>
<translation>Sin atajos</translation>
</message>
@ -876,7 +886,7 @@
<context>
<name>ShortcutEditor</name>
<message>
<location filename="../shortcutedit.cpp" line="75"/>
<location filename="../shortcutedit.cpp" line="70"/>
<source>Shortcut #%1</source>
<translation>Atajos #%1</translation>
</message>

View File

@ -178,7 +178,7 @@
<context>
<name>GraphicsScene</name>
<message>
<location filename="../mainwindow.cpp" line="276"/>
<location filename="../mainwindow.cpp" line="292"/>
<location filename="../graphicsscene.cpp" line="100"/>
<source>Drag image here</source>
<translation>Faites glisser l&apos;image ici</translation>
@ -213,189 +213,194 @@
<context>
<name>MainWindow</name>
<message>
<location filename="../mainwindow.cpp" line="181"/>
<location filename="../mainwindow.cpp" line="545"/>
<location filename="../mainwindow.cpp" line="190"/>
<location filename="../mainwindow.cpp" line="561"/>
<source>File url list is empty</source>
<translation>La liste des URL de fichiers est vide</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="445"/>
<location filename="../mainwindow.cpp" line="461"/>
<source>&amp;Copy</source>
<translation>&amp;Copier</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="553"/>
<location filename="../mainwindow.cpp" line="569"/>
<source>Image data is invalid</source>
<translation>Les données d&apos;image ne sont pas valides</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="560"/>
<location filename="../mainwindow.cpp" line="576"/>
<source>Not supported mimedata: %1</source>
<translation>Mimedata non pris en charge&#xa0;: %1</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="759"/>
<location filename="../mainwindow.cpp" line="783"/>
<source>Image From Clipboard</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="777"/>
<location filename="../mainwindow.cpp" line="801"/>
<source>Are you sure you want to move &quot;%1&quot; to recycle bin?</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="781"/>
<location filename="../mainwindow.cpp" line="805"/>
<source>Failed to move file to trash</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="782"/>
<location filename="../mainwindow.cpp" line="806"/>
<source>Move to trash failed, it might caused by file permission issue, file system limitation, or platform limitation.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="114"/>
<location filename="../actionmanager.cpp" line="106"/>
<source>Copy P&amp;ixmap</source>
<translation>Copier P&amp;ixmap</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="115"/>
<location filename="../actionmanager.cpp" line="107"/>
<source>Copy &amp;File Path</source>
<translation>Copier le &amp;chemin du fichier</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="133"/>
<location filename="../actionmanager.cpp" line="125"/>
<source>Properties</source>
<translation>Propriétés</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="118"/>
<location filename="../actionmanager.cpp" line="110"/>
<location filename="../aboutdialog.cpp" line="41"/>
<source>Stay on top</source>
<translation>Rester en-haut</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="119"/>
<location filename="../actionmanager.cpp" line="111"/>
<location filename="../aboutdialog.cpp" line="44"/>
<source>Protected mode</source>
<translation>Mode protégé</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="120"/>
<location filename="../actionmanager.cpp" line="112"/>
<location filename="../aboutdialog.cpp" line="47"/>
<source>Keep transformation</source>
<comment>The &apos;transformation&apos; means the flip/rotation status that currently applied to the image view</comment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="99"/>
<location filename="../actionmanager.cpp" line="90"/>
<source>Zoom in</source>
<translation>Zoom avant</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="100"/>
<location filename="../actionmanager.cpp" line="91"/>
<source>Zoom out</source>
<translation>Zoom arrière</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="108"/>
<location filename="../actionmanager.cpp" line="99"/>
<source>Pause/Resume Animation</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="109"/>
<location filename="../actionmanager.cpp" line="100"/>
<source>Animation Go to Next Frame</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="111"/>
<location filename="../actionmanager.cpp" line="102"/>
<source>Flip &amp;Horizontally</source>
<translation>Retourner &amp;horizontalement</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="112"/>
<location filename="../actionmanager.cpp" line="103"/>
<source>Fit to view</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="113"/>
<location filename="../actionmanager.cpp" line="104"/>
<source>Fit to width</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="116"/>
<location filename="../actionmanager.cpp" line="105"/>
<source>Fit long image</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="108"/>
<source>&amp;Paste</source>
<translation>Co&amp;ller</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="101"/>
<location filename="../actionmanager.cpp" line="92"/>
<source>Toggle Checkerboard</source>
<translation>Dés/activer le damier</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="95"/>
<location filename="../actionmanager.cpp" line="86"/>
<source>&amp;Open...</source>
<translation>&amp;Ouvrir...</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="97"/>
<location filename="../actionmanager.cpp" line="88"/>
<source>Actual size</source>
<translation>Taille actuelle</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="98"/>
<location filename="../actionmanager.cpp" line="89"/>
<source>Toggle maximize</source>
<translation>Dés/activer l&apos;agrandissement</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="102"/>
<location filename="../actionmanager.cpp" line="93"/>
<source>Rotate right</source>
<translation>Pivoter vers la droite</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="103"/>
<location filename="../actionmanager.cpp" line="94"/>
<source>Rotate left</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="105"/>
<location filename="../actionmanager.cpp" line="96"/>
<source>Previous image</source>
<translation>Image précédente</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="106"/>
<location filename="../actionmanager.cpp" line="97"/>
<source>Next image</source>
<translation>Image suivant</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="776"/>
<location filename="../actionmanager.cpp" line="117"/>
<location filename="../mainwindow.cpp" line="800"/>
<location filename="../actionmanager.cpp" line="109"/>
<source>Move to Trash</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="121"/>
<location filename="../actionmanager.cpp" line="113"/>
<source>Configure...</source>
<translation>Configurer</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="122"/>
<location filename="../actionmanager.cpp" line="114"/>
<source>Help</source>
<translation>Aide</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="125"/>
<location filename="../actionmanager.cpp" line="117"/>
<source>Show in File Explorer</source>
<comment>File Explorer is the name of explorer.exe under Windows</comment>
<translation>Afficher dans le navigateur de fichiers</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="131"/>
<location filename="../actionmanager.cpp" line="123"/>
<source>Show in directory</source>
<translation>Afficher dans le dossier</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="134"/>
<location filename="../actionmanager.cpp" line="126"/>
<source>Quit</source>
<translation>Quitter</translation>
</message>
@ -726,141 +731,146 @@
<context>
<name>SettingsDialog</name>
<message>
<location filename="../settingsdialog.cpp" line="31"/>
<location filename="../settingsdialog.cpp" line="32"/>
<source>Settings</source>
<translation>Paramètres</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="39"/>
<location filename="../settingsdialog.cpp" line="40"/>
<source>Options</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="51"/>
<location filename="../settingsdialog.cpp" line="52"/>
<source>Shortcuts</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="61"/>
<location filename="../settingsdialog.cpp" line="62"/>
<source>Editing shortcuts for action &quot;%1&quot;:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="70"/>
<location filename="../settingsdialog.cpp" line="71"/>
<source>Failed to set shortcuts</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="71"/>
<location filename="../settingsdialog.cpp" line="72"/>
<source>Please check if shortcuts are duplicated with existing shortcuts.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="78"/>
<location filename="../settingsdialog.cpp" line="79"/>
<source>Do nothing</source>
<translation>Ne rien faire</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="79"/>
<location filename="../settingsdialog.cpp" line="80"/>
<source>Close the window</source>
<translation>Fermer la fenêtre</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="80"/>
<location filename="../settingsdialog.cpp" line="81"/>
<source>Toggle maximize</source>
<translation>Activer/désactiver l&apos;agrandissement</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="81"/>
<location filename="../settingsdialog.cpp" line="82"/>
<source>Toggle fullscreen</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="85"/>
<location filename="../settingsdialog.cpp" line="86"/>
<source>Zoom in and out</source>
<translation>Zoom avant et arrière</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="86"/>
<location filename="../settingsdialog.cpp" line="87"/>
<source>View next or previous item</source>
<translation>Voir l&apos;élément suivant ou précédent</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="90"/>
<location filename="../settingsdialog.cpp" line="91"/>
<source>Auto size</source>
<translation>Taille automatique</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="91"/>
<location filename="../settingsdialog.cpp" line="92"/>
<source>Maximized</source>
<translation>Agrandi</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="92"/>
<location filename="../settingsdialog.cpp" line="93"/>
<source>Windowed</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="96"/>
<location filename="../settingsdialog.cpp" line="97"/>
<source>Round (Integer scaling)</source>
<comment>This option means round up for .5 and above</comment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="97"/>
<location filename="../settingsdialog.cpp" line="98"/>
<source>Ceil (Integer scaling)</source>
<comment>This option means always round up</comment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="98"/>
<location filename="../settingsdialog.cpp" line="99"/>
<source>Floor (Integer scaling)</source>
<comment>This option means always round down</comment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="99"/>
<location filename="../settingsdialog.cpp" line="100"/>
<source>Follow system (Fractional scaling)</source>
<comment>This option means don&apos;t round</comment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="122"/>
<location filename="../settingsdialog.cpp" line="123"/>
<source>Stay on top when start-up</source>
<translation>Rester en-haut lors du démarrage</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="123"/>
<location filename="../settingsdialog.cpp" line="124"/>
<source>Use built-in close window animation</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="124"/>
<location filename="../settingsdialog.cpp" line="125"/>
<source>Use light-color checkerboard</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="125"/>
<location filename="../settingsdialog.cpp" line="126"/>
<source>Loop the loaded gallery</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="126"/>
<location filename="../settingsdialog.cpp" line="127"/>
<source>Auto long image mode</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="128"/>
<source>Double-click behavior</source>
<translation>Comportement du double-clic</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="127"/>
<location filename="../settingsdialog.cpp" line="129"/>
<source>Mouse wheel behavior</source>
<translation>Comportement de la molette de la souris</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="128"/>
<location filename="../settingsdialog.cpp" line="130"/>
<source>Default window size</source>
<translation>Taille de la fenêtre par défaut</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="129"/>
<location filename="../settingsdialog.cpp" line="131"/>
<source>HiDPI scale factor rounding policy</source>
<translation type="unfinished"></translation>
</message>
@ -868,7 +878,7 @@
<context>
<name>ShortcutEdit</name>
<message>
<location filename="../shortcutedit.cpp" line="109"/>
<location filename="../shortcutedit.cpp" line="104"/>
<source>No shortcuts</source>
<translation type="unfinished"></translation>
</message>
@ -876,7 +886,7 @@
<context>
<name>ShortcutEditor</name>
<message>
<location filename="../shortcutedit.cpp" line="75"/>
<location filename="../shortcutedit.cpp" line="70"/>
<source>Shortcut #%1</source>
<translation type="unfinished"></translation>
</message>

View File

@ -178,7 +178,7 @@
<context>
<name>GraphicsScene</name>
<message>
<location filename="../mainwindow.cpp" line="276"/>
<location filename="../mainwindow.cpp" line="292"/>
<location filename="../graphicsscene.cpp" line="100"/>
<source>Drag image here</source>
<translation>Tarik gambar ke sini</translation>
@ -213,189 +213,194 @@
<context>
<name>MainWindow</name>
<message>
<location filename="../mainwindow.cpp" line="181"/>
<location filename="../mainwindow.cpp" line="545"/>
<location filename="../mainwindow.cpp" line="190"/>
<location filename="../mainwindow.cpp" line="561"/>
<source>File url list is empty</source>
<translation>Daftar url file kosong</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="445"/>
<location filename="../mainwindow.cpp" line="461"/>
<source>&amp;Copy</source>
<translation>&amp;Salin</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="553"/>
<location filename="../mainwindow.cpp" line="569"/>
<source>Image data is invalid</source>
<translation>Data gambar tidak valid</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="560"/>
<location filename="../mainwindow.cpp" line="576"/>
<source>Not supported mimedata: %1</source>
<translation>Tidak didukung mimedata: %1</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="759"/>
<location filename="../mainwindow.cpp" line="783"/>
<source>Image From Clipboard</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="777"/>
<location filename="../mainwindow.cpp" line="801"/>
<source>Are you sure you want to move &quot;%1&quot; to recycle bin?</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="781"/>
<location filename="../mainwindow.cpp" line="805"/>
<source>Failed to move file to trash</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="782"/>
<location filename="../mainwindow.cpp" line="806"/>
<source>Move to trash failed, it might caused by file permission issue, file system limitation, or platform limitation.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="114"/>
<location filename="../actionmanager.cpp" line="106"/>
<source>Copy P&amp;ixmap</source>
<translation>Salin P&amp;ixmap</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="115"/>
<location filename="../actionmanager.cpp" line="107"/>
<source>Copy &amp;File Path</source>
<translation>Salin &amp;Path Berkas</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="133"/>
<location filename="../actionmanager.cpp" line="125"/>
<source>Properties</source>
<translation>Properti</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="118"/>
<location filename="../actionmanager.cpp" line="110"/>
<location filename="../aboutdialog.cpp" line="41"/>
<source>Stay on top</source>
<translation>Tetap di atas</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="119"/>
<location filename="../actionmanager.cpp" line="111"/>
<location filename="../aboutdialog.cpp" line="44"/>
<source>Protected mode</source>
<translation>Mode Terlindungi</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="120"/>
<location filename="../actionmanager.cpp" line="112"/>
<location filename="../aboutdialog.cpp" line="47"/>
<source>Keep transformation</source>
<comment>The &apos;transformation&apos; means the flip/rotation status that currently applied to the image view</comment>
<translation>Simpan transformasi</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="99"/>
<location filename="../actionmanager.cpp" line="90"/>
<source>Zoom in</source>
<translation>Perbesar</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="100"/>
<location filename="../actionmanager.cpp" line="91"/>
<source>Zoom out</source>
<translation>Perkecil</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="108"/>
<location filename="../actionmanager.cpp" line="99"/>
<source>Pause/Resume Animation</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="109"/>
<location filename="../actionmanager.cpp" line="100"/>
<source>Animation Go to Next Frame</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="111"/>
<location filename="../actionmanager.cpp" line="102"/>
<source>Flip &amp;Horizontally</source>
<translation>Putar Secara &amp;Horizontal</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="112"/>
<location filename="../actionmanager.cpp" line="103"/>
<source>Fit to view</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="113"/>
<location filename="../actionmanager.cpp" line="104"/>
<source>Fit to width</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="116"/>
<location filename="../actionmanager.cpp" line="105"/>
<source>Fit long image</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="108"/>
<source>&amp;Paste</source>
<translation>&amp;Tempel</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="101"/>
<location filename="../actionmanager.cpp" line="92"/>
<source>Toggle Checkerboard</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="95"/>
<location filename="../actionmanager.cpp" line="86"/>
<source>&amp;Open...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="97"/>
<location filename="../actionmanager.cpp" line="88"/>
<source>Actual size</source>
<translation>Ukuran asli</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="98"/>
<location filename="../actionmanager.cpp" line="89"/>
<source>Toggle maximize</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="102"/>
<location filename="../actionmanager.cpp" line="93"/>
<source>Rotate right</source>
<translation>Putar ke kanan</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="103"/>
<location filename="../actionmanager.cpp" line="94"/>
<source>Rotate left</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="105"/>
<location filename="../actionmanager.cpp" line="96"/>
<source>Previous image</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="106"/>
<location filename="../actionmanager.cpp" line="97"/>
<source>Next image</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="776"/>
<location filename="../actionmanager.cpp" line="117"/>
<location filename="../mainwindow.cpp" line="800"/>
<location filename="../actionmanager.cpp" line="109"/>
<source>Move to Trash</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="121"/>
<location filename="../actionmanager.cpp" line="113"/>
<source>Configure...</source>
<translation>Konfigurasi...</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="122"/>
<location filename="../actionmanager.cpp" line="114"/>
<source>Help</source>
<translation>Dukungan</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="125"/>
<location filename="../actionmanager.cpp" line="117"/>
<source>Show in File Explorer</source>
<comment>File Explorer is the name of explorer.exe under Windows</comment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="131"/>
<location filename="../actionmanager.cpp" line="123"/>
<source>Show in directory</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="134"/>
<location filename="../actionmanager.cpp" line="126"/>
<source>Quit</source>
<translation>Keluar</translation>
</message>
@ -726,141 +731,146 @@
<context>
<name>SettingsDialog</name>
<message>
<location filename="../settingsdialog.cpp" line="31"/>
<location filename="../settingsdialog.cpp" line="32"/>
<source>Settings</source>
<translation>Pengaturan</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="39"/>
<location filename="../settingsdialog.cpp" line="40"/>
<source>Options</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="51"/>
<location filename="../settingsdialog.cpp" line="52"/>
<source>Shortcuts</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="61"/>
<location filename="../settingsdialog.cpp" line="62"/>
<source>Editing shortcuts for action &quot;%1&quot;:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="70"/>
<location filename="../settingsdialog.cpp" line="71"/>
<source>Failed to set shortcuts</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="71"/>
<location filename="../settingsdialog.cpp" line="72"/>
<source>Please check if shortcuts are duplicated with existing shortcuts.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="78"/>
<location filename="../settingsdialog.cpp" line="79"/>
<source>Do nothing</source>
<translation>Jangan lakukan apapun</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="79"/>
<location filename="../settingsdialog.cpp" line="80"/>
<source>Close the window</source>
<translation>Tutup jendela</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="80"/>
<location filename="../settingsdialog.cpp" line="81"/>
<source>Toggle maximize</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="81"/>
<location filename="../settingsdialog.cpp" line="82"/>
<source>Toggle fullscreen</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="85"/>
<location filename="../settingsdialog.cpp" line="86"/>
<source>Zoom in and out</source>
<translation>Perbesar dan perkecil</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="86"/>
<location filename="../settingsdialog.cpp" line="87"/>
<source>View next or previous item</source>
<translation>Lihat item berikutnya atau sebelumnya</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="90"/>
<location filename="../settingsdialog.cpp" line="91"/>
<source>Auto size</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="91"/>
<location filename="../settingsdialog.cpp" line="92"/>
<source>Maximized</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="92"/>
<location filename="../settingsdialog.cpp" line="93"/>
<source>Windowed</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="96"/>
<location filename="../settingsdialog.cpp" line="97"/>
<source>Round (Integer scaling)</source>
<comment>This option means round up for .5 and above</comment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="97"/>
<location filename="../settingsdialog.cpp" line="98"/>
<source>Ceil (Integer scaling)</source>
<comment>This option means always round up</comment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="98"/>
<location filename="../settingsdialog.cpp" line="99"/>
<source>Floor (Integer scaling)</source>
<comment>This option means always round down</comment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="99"/>
<location filename="../settingsdialog.cpp" line="100"/>
<source>Follow system (Fractional scaling)</source>
<comment>This option means don&apos;t round</comment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="122"/>
<location filename="../settingsdialog.cpp" line="123"/>
<source>Stay on top when start-up</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="123"/>
<location filename="../settingsdialog.cpp" line="124"/>
<source>Use built-in close window animation</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="124"/>
<location filename="../settingsdialog.cpp" line="125"/>
<source>Use light-color checkerboard</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="125"/>
<location filename="../settingsdialog.cpp" line="126"/>
<source>Loop the loaded gallery</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="126"/>
<source>Double-click behavior</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="127"/>
<source>Mouse wheel behavior</source>
<source>Auto long image mode</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="128"/>
<source>Default window size</source>
<source>Double-click behavior</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="129"/>
<source>Mouse wheel behavior</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="130"/>
<source>Default window size</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="131"/>
<source>HiDPI scale factor rounding policy</source>
<translation type="unfinished"></translation>
</message>
@ -868,7 +878,7 @@
<context>
<name>ShortcutEdit</name>
<message>
<location filename="../shortcutedit.cpp" line="109"/>
<location filename="../shortcutedit.cpp" line="104"/>
<source>No shortcuts</source>
<translation type="unfinished"></translation>
</message>
@ -876,7 +886,7 @@
<context>
<name>ShortcutEditor</name>
<message>
<location filename="../shortcutedit.cpp" line="75"/>
<location filename="../shortcutedit.cpp" line="70"/>
<source>Shortcut #%1</source>
<translation type="unfinished"></translation>
</message>

View File

@ -174,7 +174,7 @@
<context>
<name>GraphicsScene</name>
<message>
<location filename="../mainwindow.cpp" line="276"/>
<location filename="../mainwindow.cpp" line="292"/>
<location filename="../graphicsscene.cpp" line="100"/>
<source>Drag image here</source>
<translation>Trascina qui l&apos;immagine</translation>
@ -209,189 +209,194 @@
<context>
<name>MainWindow</name>
<message>
<location filename="../mainwindow.cpp" line="181"/>
<location filename="../mainwindow.cpp" line="545"/>
<location filename="../mainwindow.cpp" line="190"/>
<location filename="../mainwindow.cpp" line="561"/>
<source>File url list is empty</source>
<translation>L&apos;elenco degli URL dei file è vuoto</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="445"/>
<location filename="../mainwindow.cpp" line="461"/>
<source>&amp;Copy</source>
<translation>&amp;Copia</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="553"/>
<location filename="../mainwindow.cpp" line="569"/>
<source>Image data is invalid</source>
<translation>I dati dell&apos;immagine non sono validi</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="560"/>
<location filename="../mainwindow.cpp" line="576"/>
<source>Not supported mimedata: %1</source>
<translation>Dati mime non supportati: %1</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="759"/>
<location filename="../mainwindow.cpp" line="783"/>
<source>Image From Clipboard</source>
<translation>Immagine dagli appunti</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="777"/>
<location filename="../mainwindow.cpp" line="801"/>
<source>Are you sure you want to move &quot;%1&quot; to recycle bin?</source>
<translation>Sei sicuro di voler spostare &quot;%1&quot; nel cestino?</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="781"/>
<location filename="../mainwindow.cpp" line="805"/>
<source>Failed to move file to trash</source>
<translation>Impossibile spostare il file nel cestino</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="782"/>
<location filename="../mainwindow.cpp" line="806"/>
<source>Move to trash failed, it might caused by file permission issue, file system limitation, or platform limitation.</source>
<translation>Lo spostamento nel cestino non è riuscito, potrebbe essere causato da un problema di autorizzazione del file, da una limitazione del file system o da una limitazione della piattaforma.</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="114"/>
<location filename="../actionmanager.cpp" line="106"/>
<source>Copy P&amp;ixmap</source>
<translation>Copia P&amp;ixmap</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="115"/>
<location filename="../actionmanager.cpp" line="107"/>
<source>Copy &amp;File Path</source>
<translation>Copia &amp;Percorso file</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="133"/>
<location filename="../actionmanager.cpp" line="125"/>
<source>Properties</source>
<translation>Proprietà</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="118"/>
<location filename="../actionmanager.cpp" line="110"/>
<location filename="../aboutdialog.cpp" line="41"/>
<source>Stay on top</source>
<translation>Rimani in cima</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="119"/>
<location filename="../actionmanager.cpp" line="111"/>
<location filename="../aboutdialog.cpp" line="44"/>
<source>Protected mode</source>
<translation>Modalità protetta</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="120"/>
<location filename="../actionmanager.cpp" line="112"/>
<location filename="../aboutdialog.cpp" line="47"/>
<source>Keep transformation</source>
<comment>The &apos;transformation&apos; means the flip/rotation status that currently applied to the image view</comment>
<translation>Mantieni trasformazione</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="99"/>
<location filename="../actionmanager.cpp" line="90"/>
<source>Zoom in</source>
<translation>Zoom avanti</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="100"/>
<location filename="../actionmanager.cpp" line="91"/>
<source>Zoom out</source>
<translation>Zoom indietro</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="108"/>
<location filename="../actionmanager.cpp" line="99"/>
<source>Pause/Resume Animation</source>
<translation>Pausa/Riprendi animazione</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="109"/>
<location filename="../actionmanager.cpp" line="100"/>
<source>Animation Go to Next Frame</source>
<translation>Animazione Vai al fotogramma successivo</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="111"/>
<location filename="../actionmanager.cpp" line="102"/>
<source>Flip &amp;Horizontally</source>
<translation>Capovolgi &amp;Orizzontalmente</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="112"/>
<location filename="../actionmanager.cpp" line="103"/>
<source>Fit to view</source>
<translation>Adatto alla visualizzazione</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="113"/>
<location filename="../actionmanager.cpp" line="104"/>
<source>Fit to width</source>
<translation>Adatta alla larghezza</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="116"/>
<location filename="../actionmanager.cpp" line="105"/>
<source>Fit long image</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="108"/>
<source>&amp;Paste</source>
<translation>&amp;Incolla</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="101"/>
<location filename="../actionmanager.cpp" line="92"/>
<source>Toggle Checkerboard</source>
<translation>Attiva/disattiva scacchiera</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="95"/>
<location filename="../actionmanager.cpp" line="86"/>
<source>&amp;Open...</source>
<translation>&amp;Apri...</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="97"/>
<location filename="../actionmanager.cpp" line="88"/>
<source>Actual size</source>
<translation>Dimensione reale</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="98"/>
<location filename="../actionmanager.cpp" line="89"/>
<source>Toggle maximize</source>
<translation>Attiva massimizzazione</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="102"/>
<location filename="../actionmanager.cpp" line="93"/>
<source>Rotate right</source>
<translation>Ruota a destra</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="103"/>
<location filename="../actionmanager.cpp" line="94"/>
<source>Rotate left</source>
<translation>Ruota a sinistra</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="105"/>
<location filename="../actionmanager.cpp" line="96"/>
<source>Previous image</source>
<translation>Immagine precedente</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="106"/>
<location filename="../actionmanager.cpp" line="97"/>
<source>Next image</source>
<translation>Immagine successiva</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="776"/>
<location filename="../actionmanager.cpp" line="117"/>
<location filename="../mainwindow.cpp" line="800"/>
<location filename="../actionmanager.cpp" line="109"/>
<source>Move to Trash</source>
<translation>Sposta nel cestino</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="121"/>
<location filename="../actionmanager.cpp" line="113"/>
<source>Configure...</source>
<translation>Configura...</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="122"/>
<location filename="../actionmanager.cpp" line="114"/>
<source>Help</source>
<translation>Aiuto</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="125"/>
<location filename="../actionmanager.cpp" line="117"/>
<source>Show in File Explorer</source>
<comment>File Explorer is the name of explorer.exe under Windows</comment>
<translation>Mostra in Esplora file</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="131"/>
<location filename="../actionmanager.cpp" line="123"/>
<source>Show in directory</source>
<translation>Mostra nella directory</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="134"/>
<location filename="../actionmanager.cpp" line="126"/>
<source>Quit</source>
<translation>Esci</translation>
</message>
@ -722,141 +727,146 @@
<context>
<name>SettingsDialog</name>
<message>
<location filename="../settingsdialog.cpp" line="31"/>
<location filename="../settingsdialog.cpp" line="32"/>
<source>Settings</source>
<translation>Impostazioni</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="39"/>
<location filename="../settingsdialog.cpp" line="40"/>
<source>Options</source>
<translation>Opzioni</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="51"/>
<location filename="../settingsdialog.cpp" line="52"/>
<source>Shortcuts</source>
<translation>Scorciatoie</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="61"/>
<location filename="../settingsdialog.cpp" line="62"/>
<source>Editing shortcuts for action &quot;%1&quot;:</source>
<translation>Modifica delle scorciatoie per l&apos;azione &quot;%1&quot;:</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="70"/>
<location filename="../settingsdialog.cpp" line="71"/>
<source>Failed to set shortcuts</source>
<translation>Impossibile impostare le scorciatoie</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="71"/>
<location filename="../settingsdialog.cpp" line="72"/>
<source>Please check if shortcuts are duplicated with existing shortcuts.</source>
<translation>Controlla se i collegamenti sono duplicati con collegamenti esistenti.</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="78"/>
<location filename="../settingsdialog.cpp" line="79"/>
<source>Do nothing</source>
<translation>Non fare nulla</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="79"/>
<location filename="../settingsdialog.cpp" line="80"/>
<source>Close the window</source>
<translation>Chiudi la finestra</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="80"/>
<location filename="../settingsdialog.cpp" line="81"/>
<source>Toggle maximize</source>
<translation>Attiva massimizzazione</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="81"/>
<location filename="../settingsdialog.cpp" line="82"/>
<source>Toggle fullscreen</source>
<translation>Attiva schermo intero</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="85"/>
<location filename="../settingsdialog.cpp" line="86"/>
<source>Zoom in and out</source>
<translation>Zoom avanti e indietro</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="86"/>
<location filename="../settingsdialog.cpp" line="87"/>
<source>View next or previous item</source>
<translation>Visualizza l&apos;elemento successivo o precedente</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="90"/>
<location filename="../settingsdialog.cpp" line="91"/>
<source>Auto size</source>
<translation>Dimensione automatica</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="91"/>
<location filename="../settingsdialog.cpp" line="92"/>
<source>Maximized</source>
<translation>Massimizzato</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="92"/>
<location filename="../settingsdialog.cpp" line="93"/>
<source>Windowed</source>
<translation>Finestrato</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="96"/>
<location filename="../settingsdialog.cpp" line="97"/>
<source>Round (Integer scaling)</source>
<comment>This option means round up for .5 and above</comment>
<translation>Round (ridimensionamento intero)</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="97"/>
<location filename="../settingsdialog.cpp" line="98"/>
<source>Ceil (Integer scaling)</source>
<comment>This option means always round up</comment>
<translation>Ceil (ridimensionamento intero)</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="98"/>
<location filename="../settingsdialog.cpp" line="99"/>
<source>Floor (Integer scaling)</source>
<comment>This option means always round down</comment>
<translation>Floor (ridimensionamento intero)</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="99"/>
<location filename="../settingsdialog.cpp" line="100"/>
<source>Follow system (Fractional scaling)</source>
<comment>This option means don&apos;t round</comment>
<translation>Segui il sistema (scala frazionaria)</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="122"/>
<location filename="../settingsdialog.cpp" line="123"/>
<source>Stay on top when start-up</source>
<translation>Rimani in cima quando si avvia</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="123"/>
<location filename="../settingsdialog.cpp" line="124"/>
<source>Use built-in close window animation</source>
<translation type="unfinished"></translation>
<translation>Utilizza l&apos;animazione di chiusura della finestra integrata</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="124"/>
<location filename="../settingsdialog.cpp" line="125"/>
<source>Use light-color checkerboard</source>
<translation>Utilizzare scacchiera di colore chiaro</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="125"/>
<location filename="../settingsdialog.cpp" line="126"/>
<source>Loop the loaded gallery</source>
<translation type="unfinished"></translation>
<translation>Esegui il loop della galleria caricata</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="126"/>
<location filename="../settingsdialog.cpp" line="127"/>
<source>Auto long image mode</source>
<translation>Modalità immagine lunga automatica</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="128"/>
<source>Double-click behavior</source>
<translation>Comportamento del doppio clic</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="127"/>
<location filename="../settingsdialog.cpp" line="129"/>
<source>Mouse wheel behavior</source>
<translation>Comportamento della rotellina del mouse</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="128"/>
<location filename="../settingsdialog.cpp" line="130"/>
<source>Default window size</source>
<translation>Dimensioni predefinite della finestra</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="129"/>
<location filename="../settingsdialog.cpp" line="131"/>
<source>HiDPI scale factor rounding policy</source>
<translation>Politica di arrotondamento del fattore di scala HiDPI</translation>
</message>
@ -864,7 +874,7 @@
<context>
<name>ShortcutEdit</name>
<message>
<location filename="../shortcutedit.cpp" line="109"/>
<location filename="../shortcutedit.cpp" line="104"/>
<source>No shortcuts</source>
<translation>Nessuna scorciatoia</translation>
</message>
@ -872,7 +882,7 @@
<context>
<name>ShortcutEditor</name>
<message>
<location filename="../shortcutedit.cpp" line="75"/>
<location filename="../shortcutedit.cpp" line="70"/>
<source>Shortcut #%1</source>
<translation>Scorciatoia #%1</translation>
</message>

View File

@ -174,7 +174,7 @@
<context>
<name>GraphicsScene</name>
<message>
<location filename="../mainwindow.cpp" line="276"/>
<location filename="../mainwindow.cpp" line="292"/>
<location filename="../graphicsscene.cpp" line="100"/>
<source>Drag image here</source>
<translation></translation>
@ -209,189 +209,194 @@
<context>
<name>MainWindow</name>
<message>
<location filename="../mainwindow.cpp" line="181"/>
<location filename="../mainwindow.cpp" line="545"/>
<location filename="../mainwindow.cpp" line="190"/>
<location filename="../mainwindow.cpp" line="561"/>
<source>File url list is empty</source>
<translation>urlリストがエンプティーです</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="445"/>
<location filename="../mainwindow.cpp" line="461"/>
<source>&amp;Copy</source>
<translation>(&amp;C)</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="553"/>
<location filename="../mainwindow.cpp" line="569"/>
<source>Image data is invalid</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="560"/>
<location filename="../mainwindow.cpp" line="576"/>
<source>Not supported mimedata: %1</source>
<translation>mimedata: %1</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="759"/>
<location filename="../mainwindow.cpp" line="783"/>
<source>Image From Clipboard</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="777"/>
<location filename="../mainwindow.cpp" line="801"/>
<source>Are you sure you want to move &quot;%1&quot; to recycle bin?</source>
<translation>%1</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="781"/>
<location filename="../mainwindow.cpp" line="805"/>
<source>Failed to move file to trash</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="782"/>
<location filename="../mainwindow.cpp" line="806"/>
<source>Move to trash failed, it might caused by file permission issue, file system limitation, or platform limitation.</source>
<translation></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="114"/>
<location filename="../actionmanager.cpp" line="106"/>
<source>Copy P&amp;ixmap</source>
<translation>(&amp;I)</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="115"/>
<location filename="../actionmanager.cpp" line="107"/>
<source>Copy &amp;File Path</source>
<translation>(&amp;F)</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="133"/>
<location filename="../actionmanager.cpp" line="125"/>
<source>Properties</source>
<translation></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="118"/>
<location filename="../actionmanager.cpp" line="110"/>
<location filename="../aboutdialog.cpp" line="41"/>
<source>Stay on top</source>
<translation></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="119"/>
<location filename="../actionmanager.cpp" line="111"/>
<location filename="../aboutdialog.cpp" line="44"/>
<source>Protected mode</source>
<translation></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="120"/>
<location filename="../actionmanager.cpp" line="112"/>
<location filename="../aboutdialog.cpp" line="47"/>
<source>Keep transformation</source>
<comment>The &apos;transformation&apos; means the flip/rotation status that currently applied to the image view</comment>
<translation></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="99"/>
<location filename="../actionmanager.cpp" line="90"/>
<source>Zoom in</source>
<translation></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="100"/>
<location filename="../actionmanager.cpp" line="91"/>
<source>Zoom out</source>
<translation></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="108"/>
<location filename="../actionmanager.cpp" line="99"/>
<source>Pause/Resume Animation</source>
<translation> / </translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="109"/>
<location filename="../actionmanager.cpp" line="100"/>
<source>Animation Go to Next Frame</source>
<translation></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="111"/>
<location filename="../actionmanager.cpp" line="102"/>
<source>Flip &amp;Horizontally</source>
<translation>(&amp;H)</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="112"/>
<location filename="../actionmanager.cpp" line="103"/>
<source>Fit to view</source>
<translation></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="113"/>
<location filename="../actionmanager.cpp" line="104"/>
<source>Fit to width</source>
<translation></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="116"/>
<location filename="../actionmanager.cpp" line="105"/>
<source>Fit long image</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="108"/>
<source>&amp;Paste</source>
<translation>(&amp;P)</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="101"/>
<location filename="../actionmanager.cpp" line="92"/>
<source>Toggle Checkerboard</source>
<translation></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="95"/>
<location filename="../actionmanager.cpp" line="86"/>
<source>&amp;Open...</source>
<translation>(&amp;O)</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="97"/>
<location filename="../actionmanager.cpp" line="88"/>
<source>Actual size</source>
<translation></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="98"/>
<location filename="../actionmanager.cpp" line="89"/>
<source>Toggle maximize</source>
<translation></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="102"/>
<location filename="../actionmanager.cpp" line="93"/>
<source>Rotate right</source>
<translation></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="103"/>
<location filename="../actionmanager.cpp" line="94"/>
<source>Rotate left</source>
<translation></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="105"/>
<location filename="../actionmanager.cpp" line="96"/>
<source>Previous image</source>
<translation></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="106"/>
<location filename="../actionmanager.cpp" line="97"/>
<source>Next image</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="776"/>
<location filename="../actionmanager.cpp" line="117"/>
<location filename="../mainwindow.cpp" line="800"/>
<location filename="../actionmanager.cpp" line="109"/>
<source>Move to Trash</source>
<translation></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="121"/>
<location filename="../actionmanager.cpp" line="113"/>
<source>Configure...</source>
<translation>...</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="122"/>
<location filename="../actionmanager.cpp" line="114"/>
<source>Help</source>
<translation></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="125"/>
<location filename="../actionmanager.cpp" line="117"/>
<source>Show in File Explorer</source>
<comment>File Explorer is the name of explorer.exe under Windows</comment>
<translation></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="131"/>
<location filename="../actionmanager.cpp" line="123"/>
<source>Show in directory</source>
<translation></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="134"/>
<location filename="../actionmanager.cpp" line="126"/>
<source>Quit</source>
<translation></translation>
</message>
@ -722,141 +727,146 @@
<context>
<name>SettingsDialog</name>
<message>
<location filename="../settingsdialog.cpp" line="31"/>
<location filename="../settingsdialog.cpp" line="32"/>
<source>Settings</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="39"/>
<location filename="../settingsdialog.cpp" line="40"/>
<source>Options</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="51"/>
<location filename="../settingsdialog.cpp" line="52"/>
<source>Shortcuts</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="61"/>
<location filename="../settingsdialog.cpp" line="62"/>
<source>Editing shortcuts for action &quot;%1&quot;:</source>
<translation>%1:</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="70"/>
<location filename="../settingsdialog.cpp" line="71"/>
<source>Failed to set shortcuts</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="71"/>
<location filename="../settingsdialog.cpp" line="72"/>
<source>Please check if shortcuts are duplicated with existing shortcuts.</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="78"/>
<location filename="../settingsdialog.cpp" line="79"/>
<source>Do nothing</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="79"/>
<location filename="../settingsdialog.cpp" line="80"/>
<source>Close the window</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="80"/>
<location filename="../settingsdialog.cpp" line="81"/>
<source>Toggle maximize</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="81"/>
<location filename="../settingsdialog.cpp" line="82"/>
<source>Toggle fullscreen</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="85"/>
<location filename="../settingsdialog.cpp" line="86"/>
<source>Zoom in and out</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="86"/>
<location filename="../settingsdialog.cpp" line="87"/>
<source>View next or previous item</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="90"/>
<location filename="../settingsdialog.cpp" line="91"/>
<source>Auto size</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="91"/>
<location filename="../settingsdialog.cpp" line="92"/>
<source>Maximized</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="92"/>
<location filename="../settingsdialog.cpp" line="93"/>
<source>Windowed</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="96"/>
<location filename="../settingsdialog.cpp" line="97"/>
<source>Round (Integer scaling)</source>
<comment>This option means round up for .5 and above</comment>
<translation> ()</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="97"/>
<location filename="../settingsdialog.cpp" line="98"/>
<source>Ceil (Integer scaling)</source>
<comment>This option means always round up</comment>
<translation> ()</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="98"/>
<location filename="../settingsdialog.cpp" line="99"/>
<source>Floor (Integer scaling)</source>
<comment>This option means always round down</comment>
<translation> ()</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="99"/>
<location filename="../settingsdialog.cpp" line="100"/>
<source>Follow system (Fractional scaling)</source>
<comment>This option means don&apos;t round</comment>
<translation> ()</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="122"/>
<location filename="../settingsdialog.cpp" line="123"/>
<source>Stay on top when start-up</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="123"/>
<location filename="../settingsdialog.cpp" line="124"/>
<source>Use built-in close window animation</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="124"/>
<location filename="../settingsdialog.cpp" line="125"/>
<source>Use light-color checkerboard</source>
<translation>使</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="125"/>
<location filename="../settingsdialog.cpp" line="126"/>
<source>Loop the loaded gallery</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="126"/>
<location filename="../settingsdialog.cpp" line="127"/>
<source>Auto long image mode</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="128"/>
<source>Double-click behavior</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="127"/>
<location filename="../settingsdialog.cpp" line="129"/>
<source>Mouse wheel behavior</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="128"/>
<location filename="../settingsdialog.cpp" line="130"/>
<source>Default window size</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="129"/>
<location filename="../settingsdialog.cpp" line="131"/>
<source>HiDPI scale factor rounding policy</source>
<translation>DPIスケーリングの四捨五入方法</translation>
</message>
@ -864,7 +874,7 @@
<context>
<name>ShortcutEdit</name>
<message>
<location filename="../shortcutedit.cpp" line="109"/>
<location filename="../shortcutedit.cpp" line="104"/>
<source>No shortcuts</source>
<translation></translation>
</message>
@ -872,7 +882,7 @@
<context>
<name>ShortcutEditor</name>
<message>
<location filename="../shortcutedit.cpp" line="75"/>
<location filename="../shortcutedit.cpp" line="70"/>
<source>Shortcut #%1</source>
<translation> #%1</translation>
</message>

View File

@ -174,7 +174,7 @@
<context>
<name>GraphicsScene</name>
<message>
<location filename="../mainwindow.cpp" line="276"/>
<location filename="../mainwindow.cpp" line="292"/>
<location filename="../graphicsscene.cpp" line="100"/>
<source>Drag image here</source>
<translation> </translation>
@ -209,189 +209,194 @@
<context>
<name>MainWindow</name>
<message>
<location filename="../mainwindow.cpp" line="181"/>
<location filename="../mainwindow.cpp" line="545"/>
<location filename="../mainwindow.cpp" line="190"/>
<location filename="../mainwindow.cpp" line="561"/>
<source>File url list is empty</source>
<translation> URL </translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="445"/>
<location filename="../mainwindow.cpp" line="461"/>
<source>&amp;Copy</source>
<translation>(&amp;C)</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="553"/>
<location filename="../mainwindow.cpp" line="569"/>
<source>Image data is invalid</source>
<translation> </translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="560"/>
<location filename="../mainwindow.cpp" line="576"/>
<source>Not supported mimedata: %1</source>
<translation> mimedata: %1</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="759"/>
<location filename="../mainwindow.cpp" line="783"/>
<source>Image From Clipboard</source>
<translation> </translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="777"/>
<location filename="../mainwindow.cpp" line="801"/>
<source>Are you sure you want to move &quot;%1&quot; to recycle bin?</source>
<translation>&quot;%1&quot; ?</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="781"/>
<location filename="../mainwindow.cpp" line="805"/>
<source>Failed to move file to trash</source>
<translation type="unfinished"></translation>
<translation> </translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="782"/>
<location filename="../mainwindow.cpp" line="806"/>
<source>Move to trash failed, it might caused by file permission issue, file system limitation, or platform limitation.</source>
<translation> . , .</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="114"/>
<location filename="../actionmanager.cpp" line="106"/>
<source>Copy P&amp;ixmap</source>
<translation>Pixmap (&amp;I)</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="115"/>
<location filename="../actionmanager.cpp" line="107"/>
<source>Copy &amp;File Path</source>
<translation> (&amp;F)</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="133"/>
<location filename="../actionmanager.cpp" line="125"/>
<source>Properties</source>
<translation></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="118"/>
<location filename="../actionmanager.cpp" line="110"/>
<location filename="../aboutdialog.cpp" line="41"/>
<source>Stay on top</source>
<translation> </translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="119"/>
<location filename="../actionmanager.cpp" line="111"/>
<location filename="../aboutdialog.cpp" line="44"/>
<source>Protected mode</source>
<translation> </translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="120"/>
<location filename="../actionmanager.cpp" line="112"/>
<location filename="../aboutdialog.cpp" line="47"/>
<source>Keep transformation</source>
<comment>The &apos;transformation&apos; means the flip/rotation status that currently applied to the image view</comment>
<translation> </translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="99"/>
<location filename="../actionmanager.cpp" line="90"/>
<source>Zoom in</source>
<translation></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="100"/>
<location filename="../actionmanager.cpp" line="91"/>
<source>Zoom out</source>
<translation></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="108"/>
<location filename="../actionmanager.cpp" line="99"/>
<source>Pause/Resume Animation</source>
<translation type="unfinished"></translation>
<translation> /</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="109"/>
<location filename="../actionmanager.cpp" line="100"/>
<source>Animation Go to Next Frame</source>
<translation type="unfinished"></translation>
<translation> </translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="111"/>
<location filename="../actionmanager.cpp" line="102"/>
<source>Flip &amp;Horizontally</source>
<translation> (&amp;H)</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="112"/>
<location filename="../actionmanager.cpp" line="103"/>
<source>Fit to view</source>
<translation> </translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="113"/>
<location filename="../actionmanager.cpp" line="104"/>
<source>Fit to width</source>
<translation> </translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="116"/>
<location filename="../actionmanager.cpp" line="105"/>
<source>Fit long image</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="108"/>
<source>&amp;Paste</source>
<translation>(&amp;P)</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="101"/>
<location filename="../actionmanager.cpp" line="92"/>
<source>Toggle Checkerboard</source>
<translation> </translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="95"/>
<location filename="../actionmanager.cpp" line="86"/>
<source>&amp;Open...</source>
<translation>(&amp;O)...</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="97"/>
<location filename="../actionmanager.cpp" line="88"/>
<source>Actual size</source>
<translation> </translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="98"/>
<location filename="../actionmanager.cpp" line="89"/>
<source>Toggle maximize</source>
<translation> </translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="102"/>
<location filename="../actionmanager.cpp" line="93"/>
<source>Rotate right</source>
<translation> </translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="103"/>
<location filename="../actionmanager.cpp" line="94"/>
<source>Rotate left</source>
<translation> </translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="105"/>
<location filename="../actionmanager.cpp" line="96"/>
<source>Previous image</source>
<translation> </translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="106"/>
<location filename="../actionmanager.cpp" line="97"/>
<source>Next image</source>
<translation> </translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="776"/>
<location filename="../actionmanager.cpp" line="117"/>
<location filename="../mainwindow.cpp" line="800"/>
<location filename="../actionmanager.cpp" line="109"/>
<source>Move to Trash</source>
<translation> </translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="121"/>
<location filename="../actionmanager.cpp" line="113"/>
<source>Configure...</source>
<translation>...</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="122"/>
<location filename="../actionmanager.cpp" line="114"/>
<source>Help</source>
<translation></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="125"/>
<location filename="../actionmanager.cpp" line="117"/>
<source>Show in File Explorer</source>
<comment>File Explorer is the name of explorer.exe under Windows</comment>
<translation> </translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="131"/>
<location filename="../actionmanager.cpp" line="123"/>
<source>Show in directory</source>
<translation> </translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="134"/>
<location filename="../actionmanager.cpp" line="126"/>
<source>Quit</source>
<translation></translation>
</message>
@ -722,141 +727,146 @@
<context>
<name>SettingsDialog</name>
<message>
<location filename="../settingsdialog.cpp" line="31"/>
<location filename="../settingsdialog.cpp" line="32"/>
<source>Settings</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="39"/>
<location filename="../settingsdialog.cpp" line="40"/>
<source>Options</source>
<translation type="unfinished"></translation>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="51"/>
<location filename="../settingsdialog.cpp" line="52"/>
<source>Shortcuts</source>
<translation type="unfinished"></translation>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="61"/>
<location filename="../settingsdialog.cpp" line="62"/>
<source>Editing shortcuts for action &quot;%1&quot;:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="70"/>
<source>Failed to set shortcuts</source>
<translation type="unfinished"></translation>
<translation> &quot;%1&quot; :</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="71"/>
<source>Please check if shortcuts are duplicated with existing shortcuts.</source>
<translation type="unfinished"></translation>
<source>Failed to set shortcuts</source>
<translation> </translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="78"/>
<location filename="../settingsdialog.cpp" line="72"/>
<source>Please check if shortcuts are duplicated with existing shortcuts.</source>
<translation> .</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="79"/>
<source>Do nothing</source>
<translation> </translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="79"/>
<location filename="../settingsdialog.cpp" line="80"/>
<source>Close the window</source>
<translation> </translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="80"/>
<location filename="../settingsdialog.cpp" line="81"/>
<source>Toggle maximize</source>
<translation> </translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="81"/>
<location filename="../settingsdialog.cpp" line="82"/>
<source>Toggle fullscreen</source>
<translation type="unfinished"></translation>
<translation> </translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="85"/>
<location filename="../settingsdialog.cpp" line="86"/>
<source>Zoom in and out</source>
<translation> </translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="86"/>
<location filename="../settingsdialog.cpp" line="87"/>
<source>View next or previous item</source>
<translation> </translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="90"/>
<location filename="../settingsdialog.cpp" line="91"/>
<source>Auto size</source>
<translation> </translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="91"/>
<location filename="../settingsdialog.cpp" line="92"/>
<source>Maximized</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="92"/>
<location filename="../settingsdialog.cpp" line="93"/>
<source>Windowed</source>
<translation type="unfinished"></translation>
<translation> </translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="96"/>
<location filename="../settingsdialog.cpp" line="97"/>
<source>Round (Integer scaling)</source>
<comment>This option means round up for .5 and above</comment>
<translation> ( )</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="97"/>
<location filename="../settingsdialog.cpp" line="98"/>
<source>Ceil (Integer scaling)</source>
<comment>This option means always round up</comment>
<translation> ( )</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="98"/>
<location filename="../settingsdialog.cpp" line="99"/>
<source>Floor (Integer scaling)</source>
<comment>This option means always round down</comment>
<translation> ( )</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="99"/>
<location filename="../settingsdialog.cpp" line="100"/>
<source>Follow system (Fractional scaling)</source>
<comment>This option means don&apos;t round</comment>
<translation> ( )</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="122"/>
<location filename="../settingsdialog.cpp" line="123"/>
<source>Stay on top when start-up</source>
<translation> </translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="123"/>
<location filename="../settingsdialog.cpp" line="124"/>
<source>Use built-in close window animation</source>
<translation type="unfinished"></translation>
<translation> </translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="124"/>
<location filename="../settingsdialog.cpp" line="125"/>
<source>Use light-color checkerboard</source>
<translation> </translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="125"/>
<location filename="../settingsdialog.cpp" line="126"/>
<source>Loop the loaded gallery</source>
<translation> </translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="127"/>
<source>Auto long image mode</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="126"/>
<location filename="../settingsdialog.cpp" line="128"/>
<source>Double-click behavior</source>
<translation> </translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="127"/>
<location filename="../settingsdialog.cpp" line="129"/>
<source>Mouse wheel behavior</source>
<translation> </translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="128"/>
<location filename="../settingsdialog.cpp" line="130"/>
<source>Default window size</source>
<translation> </translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="129"/>
<location filename="../settingsdialog.cpp" line="131"/>
<source>HiDPI scale factor rounding policy</source>
<translation>HiDPI </translation>
</message>
@ -864,17 +874,17 @@
<context>
<name>ShortcutEdit</name>
<message>
<location filename="../shortcutedit.cpp" line="109"/>
<location filename="../shortcutedit.cpp" line="104"/>
<source>No shortcuts</source>
<translation type="unfinished"></translation>
<translation> </translation>
</message>
</context>
<context>
<name>ShortcutEditor</name>
<message>
<location filename="../shortcutedit.cpp" line="75"/>
<location filename="../shortcutedit.cpp" line="70"/>
<source>Shortcut #%1</source>
<translation type="unfinished"></translation>
<translation> #%1</translation>
</message>
</context>
<context>

View File

@ -178,7 +178,7 @@
<context>
<name>GraphicsScene</name>
<message>
<location filename="../mainwindow.cpp" line="276"/>
<location filename="../mainwindow.cpp" line="292"/>
<location filename="../graphicsscene.cpp" line="100"/>
<source>Drag image here</source>
<translation>Dra bilde hit</translation>
@ -213,189 +213,194 @@
<context>
<name>MainWindow</name>
<message>
<location filename="../mainwindow.cpp" line="181"/>
<location filename="../mainwindow.cpp" line="545"/>
<location filename="../mainwindow.cpp" line="190"/>
<location filename="../mainwindow.cpp" line="561"/>
<source>File url list is empty</source>
<translation>Listen over filnettadresser er ugyldig</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="445"/>
<location filename="../mainwindow.cpp" line="461"/>
<source>&amp;Copy</source>
<translation>&amp;Kopier</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="553"/>
<location filename="../mainwindow.cpp" line="569"/>
<source>Image data is invalid</source>
<translation>Ugyldig bildedata</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="560"/>
<location filename="../mainwindow.cpp" line="576"/>
<source>Not supported mimedata: %1</source>
<translation>Ustøttet MIME-data: %1</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="759"/>
<location filename="../mainwindow.cpp" line="783"/>
<source>Image From Clipboard</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="777"/>
<location filename="../mainwindow.cpp" line="801"/>
<source>Are you sure you want to move &quot;%1&quot; to recycle bin?</source>
<translation>Er du sikker at du vil flytte &quot;%1&quot; til papirkurven?</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="781"/>
<location filename="../mainwindow.cpp" line="805"/>
<source>Failed to move file to trash</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="782"/>
<location filename="../mainwindow.cpp" line="806"/>
<source>Move to trash failed, it might caused by file permission issue, file system limitation, or platform limitation.</source>
<translation>Flytt til papirkurven mislyktes, det kan skyldes filtillatelsesproblem, filsystembegrensning eller plattformbegrensning.</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="114"/>
<location filename="../actionmanager.cpp" line="106"/>
<source>Copy P&amp;ixmap</source>
<translation type="unfinished">Kopier p&amp;ixmap</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="115"/>
<location filename="../actionmanager.cpp" line="107"/>
<source>Copy &amp;File Path</source>
<translation>Kopier &amp;filbane</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="133"/>
<location filename="../actionmanager.cpp" line="125"/>
<source>Properties</source>
<translation>Egenskaper</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="118"/>
<location filename="../actionmanager.cpp" line="110"/>
<location filename="../aboutdialog.cpp" line="41"/>
<source>Stay on top</source>
<translation>Behold øverst</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="119"/>
<location filename="../actionmanager.cpp" line="111"/>
<location filename="../aboutdialog.cpp" line="44"/>
<source>Protected mode</source>
<translation>Beskyttet modus</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="120"/>
<location filename="../actionmanager.cpp" line="112"/>
<location filename="../aboutdialog.cpp" line="47"/>
<source>Keep transformation</source>
<comment>The &apos;transformation&apos; means the flip/rotation status that currently applied to the image view</comment>
<translation>Behold transformasjon</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="99"/>
<location filename="../actionmanager.cpp" line="90"/>
<source>Zoom in</source>
<translation>Førstørr</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="100"/>
<location filename="../actionmanager.cpp" line="91"/>
<source>Zoom out</source>
<translation>Forminsk</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="108"/>
<location filename="../actionmanager.cpp" line="99"/>
<source>Pause/Resume Animation</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="109"/>
<location filename="../actionmanager.cpp" line="100"/>
<source>Animation Go to Next Frame</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="111"/>
<location filename="../actionmanager.cpp" line="102"/>
<source>Flip &amp;Horizontally</source>
<translation>Speilvend &amp;horisontalt</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="112"/>
<location filename="../actionmanager.cpp" line="103"/>
<source>Fit to view</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="113"/>
<location filename="../actionmanager.cpp" line="104"/>
<source>Fit to width</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="116"/>
<location filename="../actionmanager.cpp" line="105"/>
<source>Fit long image</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="108"/>
<source>&amp;Paste</source>
<translation>&amp;Lim inn</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="101"/>
<location filename="../actionmanager.cpp" line="92"/>
<source>Toggle Checkerboard</source>
<translation type="unfinished">Skru av/ rutemønster</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="95"/>
<location filename="../actionmanager.cpp" line="86"/>
<source>&amp;Open...</source>
<translation>&amp;Åpne </translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="97"/>
<location filename="../actionmanager.cpp" line="88"/>
<source>Actual size</source>
<translation>Faktisk størrelse</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="98"/>
<location filename="../actionmanager.cpp" line="89"/>
<source>Toggle maximize</source>
<translation>Maksimering av/</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="102"/>
<location filename="../actionmanager.cpp" line="93"/>
<source>Rotate right</source>
<translation>Roter til høyre</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="103"/>
<location filename="../actionmanager.cpp" line="94"/>
<source>Rotate left</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="105"/>
<location filename="../actionmanager.cpp" line="96"/>
<source>Previous image</source>
<translation>Forrige bilde</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="106"/>
<location filename="../actionmanager.cpp" line="97"/>
<source>Next image</source>
<translation>Neste bilde</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="776"/>
<location filename="../actionmanager.cpp" line="117"/>
<location filename="../mainwindow.cpp" line="800"/>
<location filename="../actionmanager.cpp" line="109"/>
<source>Move to Trash</source>
<translation>Flytt til papirkurven</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="121"/>
<location filename="../actionmanager.cpp" line="113"/>
<source>Configure...</source>
<translation>Sett opp </translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="122"/>
<location filename="../actionmanager.cpp" line="114"/>
<source>Help</source>
<translation>Hjelp</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="125"/>
<location filename="../actionmanager.cpp" line="117"/>
<source>Show in File Explorer</source>
<comment>File Explorer is the name of explorer.exe under Windows</comment>
<translation>Vis i filutforsker</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="131"/>
<location filename="../actionmanager.cpp" line="123"/>
<source>Show in directory</source>
<translation type="unfinished">Vis i mappe</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="134"/>
<location filename="../actionmanager.cpp" line="126"/>
<source>Quit</source>
<translation>Avslutt</translation>
</message>
@ -726,141 +731,146 @@
<context>
<name>SettingsDialog</name>
<message>
<location filename="../settingsdialog.cpp" line="31"/>
<location filename="../settingsdialog.cpp" line="32"/>
<source>Settings</source>
<translation>Innstillinger</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="39"/>
<location filename="../settingsdialog.cpp" line="40"/>
<source>Options</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="51"/>
<location filename="../settingsdialog.cpp" line="52"/>
<source>Shortcuts</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="61"/>
<location filename="../settingsdialog.cpp" line="62"/>
<source>Editing shortcuts for action &quot;%1&quot;:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="70"/>
<location filename="../settingsdialog.cpp" line="71"/>
<source>Failed to set shortcuts</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="71"/>
<location filename="../settingsdialog.cpp" line="72"/>
<source>Please check if shortcuts are duplicated with existing shortcuts.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="78"/>
<location filename="../settingsdialog.cpp" line="79"/>
<source>Do nothing</source>
<translation>Ikke gjør noe</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="79"/>
<location filename="../settingsdialog.cpp" line="80"/>
<source>Close the window</source>
<translation>Lukk vinduet</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="80"/>
<location filename="../settingsdialog.cpp" line="81"/>
<source>Toggle maximize</source>
<translation>Maksimering av/</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="81"/>
<location filename="../settingsdialog.cpp" line="82"/>
<source>Toggle fullscreen</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="85"/>
<location filename="../settingsdialog.cpp" line="86"/>
<source>Zoom in and out</source>
<translation>Zoom inn og ut</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="86"/>
<location filename="../settingsdialog.cpp" line="87"/>
<source>View next or previous item</source>
<translation>Vis neste eller forrige element</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="90"/>
<location filename="../settingsdialog.cpp" line="91"/>
<source>Auto size</source>
<translation type="unfinished">Automatisk størrelse</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="91"/>
<location filename="../settingsdialog.cpp" line="92"/>
<source>Maximized</source>
<translation>Maksimert</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="92"/>
<location filename="../settingsdialog.cpp" line="93"/>
<source>Windowed</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="96"/>
<location filename="../settingsdialog.cpp" line="97"/>
<source>Round (Integer scaling)</source>
<comment>This option means round up for .5 and above</comment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="97"/>
<location filename="../settingsdialog.cpp" line="98"/>
<source>Ceil (Integer scaling)</source>
<comment>This option means always round up</comment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="98"/>
<location filename="../settingsdialog.cpp" line="99"/>
<source>Floor (Integer scaling)</source>
<comment>This option means always round down</comment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="99"/>
<location filename="../settingsdialog.cpp" line="100"/>
<source>Follow system (Fractional scaling)</source>
<comment>This option means don&apos;t round</comment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="122"/>
<location filename="../settingsdialog.cpp" line="123"/>
<source>Stay on top when start-up</source>
<translation>Behold i forgrunnen ved oppstart</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="123"/>
<location filename="../settingsdialog.cpp" line="124"/>
<source>Use built-in close window animation</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="124"/>
<location filename="../settingsdialog.cpp" line="125"/>
<source>Use light-color checkerboard</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="125"/>
<location filename="../settingsdialog.cpp" line="126"/>
<source>Loop the loaded gallery</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="126"/>
<location filename="../settingsdialog.cpp" line="127"/>
<source>Auto long image mode</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="128"/>
<source>Double-click behavior</source>
<translation>Dobbeltklikksoppførsel</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="127"/>
<location filename="../settingsdialog.cpp" line="129"/>
<source>Mouse wheel behavior</source>
<translation>Musehjulsoppførsel</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="128"/>
<location filename="../settingsdialog.cpp" line="130"/>
<source>Default window size</source>
<translation>Forvalgt vindusstørrelse</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="129"/>
<location filename="../settingsdialog.cpp" line="131"/>
<source>HiDPI scale factor rounding policy</source>
<translation type="unfinished"></translation>
</message>
@ -868,7 +878,7 @@
<context>
<name>ShortcutEdit</name>
<message>
<location filename="../shortcutedit.cpp" line="109"/>
<location filename="../shortcutedit.cpp" line="104"/>
<source>No shortcuts</source>
<translation type="unfinished"></translation>
</message>
@ -876,7 +886,7 @@
<context>
<name>ShortcutEditor</name>
<message>
<location filename="../shortcutedit.cpp" line="75"/>
<location filename="../shortcutedit.cpp" line="70"/>
<source>Shortcut #%1</source>
<translation type="unfinished"></translation>
</message>

View File

@ -178,7 +178,7 @@
<context>
<name>GraphicsScene</name>
<message>
<location filename="../mainwindow.cpp" line="276"/>
<location filename="../mainwindow.cpp" line="292"/>
<location filename="../graphicsscene.cpp" line="100"/>
<source>Drag image here</source>
<translation>Sleep een afbeelding hierheen</translation>
@ -213,189 +213,194 @@
<context>
<name>MainWindow</name>
<message>
<location filename="../mainwindow.cpp" line="181"/>
<location filename="../mainwindow.cpp" line="545"/>
<location filename="../mainwindow.cpp" line="190"/>
<location filename="../mainwindow.cpp" line="561"/>
<source>File url list is empty</source>
<translation>De bestandspadlijst is leeg</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="445"/>
<location filename="../mainwindow.cpp" line="461"/>
<source>&amp;Copy</source>
<translation>&amp;Kopiëren</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="553"/>
<location filename="../mainwindow.cpp" line="569"/>
<source>Image data is invalid</source>
<translation>Beschadigde afbeeldingsgegevens</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="560"/>
<location filename="../mainwindow.cpp" line="576"/>
<source>Not supported mimedata: %1</source>
<translation>Niet-ondersteunde mime-gegevens: %1</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="759"/>
<location filename="../mainwindow.cpp" line="783"/>
<source>Image From Clipboard</source>
<translation>Afbeelding van klembord</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="777"/>
<location filename="../mainwindow.cpp" line="801"/>
<source>Are you sure you want to move &quot;%1&quot; to recycle bin?</source>
<translation>Weet u zeker dat u %1 naar de prullenbak wilt verplaatsen?</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="781"/>
<location filename="../mainwindow.cpp" line="805"/>
<source>Failed to move file to trash</source>
<translation>Verplaatsen naar prullenbak mislukt</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="782"/>
<location filename="../mainwindow.cpp" line="806"/>
<source>Move to trash failed, it might caused by file permission issue, file system limitation, or platform limitation.</source>
<translation>Het bestand kan niet naar de prullenbak worden verplaatst, mogelijk door een rechtenprobleem of systeembeperking.</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="114"/>
<location filename="../actionmanager.cpp" line="106"/>
<source>Copy P&amp;ixmap</source>
<translation>P&amp;ixmap kopiëren</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="115"/>
<location filename="../actionmanager.cpp" line="107"/>
<source>Copy &amp;File Path</source>
<translation>&amp;Bestandspad kopiëren</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="133"/>
<location filename="../actionmanager.cpp" line="125"/>
<source>Properties</source>
<translation>Eigenschappen</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="118"/>
<location filename="../actionmanager.cpp" line="110"/>
<location filename="../aboutdialog.cpp" line="41"/>
<source>Stay on top</source>
<translation>Altijd bovenop</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="119"/>
<location filename="../actionmanager.cpp" line="111"/>
<location filename="../aboutdialog.cpp" line="44"/>
<source>Protected mode</source>
<translation>Beschermde modus</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="120"/>
<location filename="../actionmanager.cpp" line="112"/>
<location filename="../aboutdialog.cpp" line="47"/>
<source>Keep transformation</source>
<comment>The &apos;transformation&apos; means the flip/rotation status that currently applied to the image view</comment>
<translation>Bewerkingen onthouden</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="99"/>
<location filename="../actionmanager.cpp" line="90"/>
<source>Zoom in</source>
<translation>Inzoomen</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="100"/>
<location filename="../actionmanager.cpp" line="91"/>
<source>Zoom out</source>
<translation>Uitzoomen</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="108"/>
<location filename="../actionmanager.cpp" line="99"/>
<source>Pause/Resume Animation</source>
<translation>Animatie pauzeren/hervatten</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="109"/>
<location filename="../actionmanager.cpp" line="100"/>
<source>Animation Go to Next Frame</source>
<translation>Ga naar volgend animatieframe</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="111"/>
<location filename="../actionmanager.cpp" line="102"/>
<source>Flip &amp;Horizontally</source>
<translation>&amp;Horizontaal spiegelen</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="112"/>
<location filename="../actionmanager.cpp" line="103"/>
<source>Fit to view</source>
<translation>Inpassen</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="113"/>
<location filename="../actionmanager.cpp" line="104"/>
<source>Fit to width</source>
<translation>Aanpassen aan breedte</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="116"/>
<location filename="../actionmanager.cpp" line="105"/>
<source>Fit long image</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="108"/>
<source>&amp;Paste</source>
<translation>&amp;Plakken</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="101"/>
<location filename="../actionmanager.cpp" line="92"/>
<source>Toggle Checkerboard</source>
<translation>Schaakbordpatroon aan/uit</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="95"/>
<location filename="../actionmanager.cpp" line="86"/>
<source>&amp;Open...</source>
<translation>&amp;Openen</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="97"/>
<location filename="../actionmanager.cpp" line="88"/>
<source>Actual size</source>
<translation>Ware grootte</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="98"/>
<location filename="../actionmanager.cpp" line="89"/>
<source>Toggle maximize</source>
<translation>Maximaliseren aan/uit</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="102"/>
<location filename="../actionmanager.cpp" line="93"/>
<source>Rotate right</source>
<translation>Naar rechts draaien</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="103"/>
<location filename="../actionmanager.cpp" line="94"/>
<source>Rotate left</source>
<translation>Naar links draaien</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="105"/>
<location filename="../actionmanager.cpp" line="96"/>
<source>Previous image</source>
<translation>Vorige afbeelding</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="106"/>
<location filename="../actionmanager.cpp" line="97"/>
<source>Next image</source>
<translation>Volgende afbeelding</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="776"/>
<location filename="../actionmanager.cpp" line="117"/>
<location filename="../mainwindow.cpp" line="800"/>
<location filename="../actionmanager.cpp" line="109"/>
<source>Move to Trash</source>
<translation>Verplaatsen naar prullenbak</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="121"/>
<location filename="../actionmanager.cpp" line="113"/>
<source>Configure...</source>
<translation>Instellen...</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="122"/>
<location filename="../actionmanager.cpp" line="114"/>
<source>Help</source>
<translation>Hulp</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="125"/>
<location filename="../actionmanager.cpp" line="117"/>
<source>Show in File Explorer</source>
<comment>File Explorer is the name of explorer.exe under Windows</comment>
<translation>Tonen in bestandsbeheer</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="131"/>
<location filename="../actionmanager.cpp" line="123"/>
<source>Show in directory</source>
<translation>Tonen in map</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="134"/>
<location filename="../actionmanager.cpp" line="126"/>
<source>Quit</source>
<translation>Afsluiten</translation>
</message>
@ -726,141 +731,146 @@
<context>
<name>SettingsDialog</name>
<message>
<location filename="../settingsdialog.cpp" line="31"/>
<location filename="../settingsdialog.cpp" line="32"/>
<source>Settings</source>
<translation>Instellingen</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="39"/>
<location filename="../settingsdialog.cpp" line="40"/>
<source>Options</source>
<translation>Opties</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="51"/>
<location filename="../settingsdialog.cpp" line="52"/>
<source>Shortcuts</source>
<translation>Sneltoetsen</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="61"/>
<location filename="../settingsdialog.cpp" line="62"/>
<source>Editing shortcuts for action &quot;%1&quot;:</source>
<translation>Bewerken van sneltoetsen voor actie %1:</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="70"/>
<location filename="../settingsdialog.cpp" line="71"/>
<source>Failed to set shortcuts</source>
<translation>Instellen mislukt</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="71"/>
<location filename="../settingsdialog.cpp" line="72"/>
<source>Please check if shortcuts are duplicated with existing shortcuts.</source>
<translation>Controleer of de gekozen sneltoetsen niet al in gebruik zijn.</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="78"/>
<location filename="../settingsdialog.cpp" line="79"/>
<source>Do nothing</source>
<translation>Niets doen</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="79"/>
<location filename="../settingsdialog.cpp" line="80"/>
<source>Close the window</source>
<translation>Venster sluiten</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="80"/>
<location filename="../settingsdialog.cpp" line="81"/>
<source>Toggle maximize</source>
<translation>Maximaliseren/Demaximaliseren</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="81"/>
<location filename="../settingsdialog.cpp" line="82"/>
<source>Toggle fullscreen</source>
<translation>Schermvullende weergave aan/uit</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="85"/>
<location filename="../settingsdialog.cpp" line="86"/>
<source>Zoom in and out</source>
<translation>In-/Uitzoomen</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="86"/>
<location filename="../settingsdialog.cpp" line="87"/>
<source>View next or previous item</source>
<translation>Ga naar volgende of vorige item</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="90"/>
<location filename="../settingsdialog.cpp" line="91"/>
<source>Auto size</source>
<translation>Automatische grootte</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="91"/>
<location filename="../settingsdialog.cpp" line="92"/>
<source>Maximized</source>
<translation>Gemaximaliseerd</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="92"/>
<location filename="../settingsdialog.cpp" line="93"/>
<source>Windowed</source>
<translation>Venster</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="96"/>
<location filename="../settingsdialog.cpp" line="97"/>
<source>Round (Integer scaling)</source>
<comment>This option means round up for .5 and above</comment>
<translation>Rond (geheel getal)</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="97"/>
<location filename="../settingsdialog.cpp" line="98"/>
<source>Ceil (Integer scaling)</source>
<comment>This option means always round up</comment>
<translation>Keil (geheel getal)</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="98"/>
<location filename="../settingsdialog.cpp" line="99"/>
<source>Floor (Integer scaling)</source>
<comment>This option means always round down</comment>
<translation>Grond (geheel getal)</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="99"/>
<location filename="../settingsdialog.cpp" line="100"/>
<source>Follow system (Fractional scaling)</source>
<comment>This option means don&apos;t round</comment>
<translation>Systeeminstelling (fractionele schaal)</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="122"/>
<location filename="../settingsdialog.cpp" line="123"/>
<source>Stay on top when start-up</source>
<translation>Automatisch altijd bovenop</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="123"/>
<location filename="../settingsdialog.cpp" line="124"/>
<source>Use built-in close window animation</source>
<translation type="unfinished"></translation>
<translation>Meegeleverde animatie voor venster sluiten gebruiken</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="124"/>
<location filename="../settingsdialog.cpp" line="125"/>
<source>Use light-color checkerboard</source>
<translation>Licht schaakbordpatroon gebruiken</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="125"/>
<location filename="../settingsdialog.cpp" line="126"/>
<source>Loop the loaded gallery</source>
<translation type="unfinished"></translation>
<translation>Gekozen galerij herhalen</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="126"/>
<location filename="../settingsdialog.cpp" line="127"/>
<source>Auto long image mode</source>
<translation>Automatische langeafbeeldingsmodus</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="128"/>
<source>Double-click behavior</source>
<translation>Dubbelklikgedrag</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="127"/>
<location filename="../settingsdialog.cpp" line="129"/>
<source>Mouse wheel behavior</source>
<translation>Scrollwielgedrag</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="128"/>
<location filename="../settingsdialog.cpp" line="130"/>
<source>Default window size</source>
<translation>Standaard vensterafmetingen</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="129"/>
<location filename="../settingsdialog.cpp" line="131"/>
<source>HiDPI scale factor rounding policy</source>
<translation>HiDPI-schaalfactor - afrondbeleid</translation>
</message>
@ -868,7 +878,7 @@
<context>
<name>ShortcutEdit</name>
<message>
<location filename="../shortcutedit.cpp" line="109"/>
<location filename="../shortcutedit.cpp" line="104"/>
<source>No shortcuts</source>
<translation>Geen sneltoetsen</translation>
</message>
@ -876,7 +886,7 @@
<context>
<name>ShortcutEditor</name>
<message>
<location filename="../shortcutedit.cpp" line="75"/>
<location filename="../shortcutedit.cpp" line="70"/>
<source>Shortcut #%1</source>
<translation>Sneltoets #%1</translation>
</message>

View File

@ -174,7 +174,7 @@
<context>
<name>GraphicsScene</name>
<message>
<location filename="../mainwindow.cpp" line="276"/>
<location filename="../mainwindow.cpp" line="292"/>
<location filename="../graphicsscene.cpp" line="100"/>
<source>Drag image here</source>
<translation type="unfinished"></translation>
@ -197,189 +197,194 @@
<context>
<name>MainWindow</name>
<message>
<location filename="../mainwindow.cpp" line="181"/>
<location filename="../mainwindow.cpp" line="545"/>
<location filename="../mainwindow.cpp" line="190"/>
<location filename="../mainwindow.cpp" line="561"/>
<source>File url list is empty</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="445"/>
<location filename="../mainwindow.cpp" line="461"/>
<source>&amp;Copy</source>
<translation>کاپی کرو</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="553"/>
<location filename="../mainwindow.cpp" line="569"/>
<source>Image data is invalid</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="560"/>
<location filename="../mainwindow.cpp" line="576"/>
<source>Not supported mimedata: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="759"/>
<location filename="../mainwindow.cpp" line="783"/>
<source>Image From Clipboard</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="777"/>
<location filename="../mainwindow.cpp" line="801"/>
<source>Are you sure you want to move &quot;%1&quot; to recycle bin?</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="781"/>
<location filename="../mainwindow.cpp" line="805"/>
<source>Failed to move file to trash</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="782"/>
<location filename="../mainwindow.cpp" line="806"/>
<source>Move to trash failed, it might caused by file permission issue, file system limitation, or platform limitation.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="114"/>
<location filename="../actionmanager.cpp" line="106"/>
<source>Copy P&amp;ixmap</source>
<translation>تصویر دا نقشہ کاپی کرو</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="115"/>
<location filename="../actionmanager.cpp" line="107"/>
<source>Copy &amp;File Path</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="133"/>
<location filename="../actionmanager.cpp" line="125"/>
<source>Properties</source>
<translation>وشیشتاواں</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="118"/>
<location filename="../actionmanager.cpp" line="110"/>
<location filename="../aboutdialog.cpp" line="41"/>
<source>Stay on top</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="119"/>
<location filename="../actionmanager.cpp" line="111"/>
<location filename="../aboutdialog.cpp" line="44"/>
<source>Protected mode</source>
<translation>سرکھیات سیٹنگ</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="120"/>
<location filename="../actionmanager.cpp" line="112"/>
<location filename="../aboutdialog.cpp" line="47"/>
<source>Keep transformation</source>
<comment>The &apos;transformation&apos; means the flip/rotation status that currently applied to the image view</comment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="99"/>
<location filename="../actionmanager.cpp" line="90"/>
<source>Zoom in</source>
<translation>وڈا کرو</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="100"/>
<location filename="../actionmanager.cpp" line="91"/>
<source>Zoom out</source>
<translation>چھوٹا کرو</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="108"/>
<location filename="../actionmanager.cpp" line="99"/>
<source>Pause/Resume Animation</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="109"/>
<location filename="../actionmanager.cpp" line="100"/>
<source>Animation Go to Next Frame</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="111"/>
<location filename="../actionmanager.cpp" line="102"/>
<source>Flip &amp;Horizontally</source>
<translation>لیٹویں اُلٹاؤ</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="112"/>
<location filename="../actionmanager.cpp" line="103"/>
<source>Fit to view</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="113"/>
<location filename="../actionmanager.cpp" line="104"/>
<source>Fit to width</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="116"/>
<location filename="../actionmanager.cpp" line="105"/>
<source>Fit long image</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="108"/>
<source>&amp;Paste</source>
<translation>پیسٹ کرو</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="101"/>
<location filename="../actionmanager.cpp" line="92"/>
<source>Toggle Checkerboard</source>
<translation>چیکبورڈ چالو بدلو</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="95"/>
<location filename="../actionmanager.cpp" line="86"/>
<source>&amp;Open...</source>
<translation>کھُلھو</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="97"/>
<location filename="../actionmanager.cpp" line="88"/>
<source>Actual size</source>
<translation>اصلی اکار</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="98"/>
<location filename="../actionmanager.cpp" line="89"/>
<source>Toggle maximize</source>
<translation>ودھو ودھ بدلو</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="102"/>
<location filename="../actionmanager.cpp" line="93"/>
<source>Rotate right</source>
<translation>سجے گھنماؤ</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="103"/>
<location filename="../actionmanager.cpp" line="94"/>
<source>Rotate left</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="105"/>
<location filename="../actionmanager.cpp" line="96"/>
<source>Previous image</source>
<translation>پچھلی تصویر</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="106"/>
<location filename="../actionmanager.cpp" line="97"/>
<source>Next image</source>
<translation>اگلی تصویر</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="776"/>
<location filename="../actionmanager.cpp" line="117"/>
<location filename="../mainwindow.cpp" line="800"/>
<location filename="../actionmanager.cpp" line="109"/>
<source>Move to Trash</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="121"/>
<location filename="../actionmanager.cpp" line="113"/>
<source>Configure...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="122"/>
<location filename="../actionmanager.cpp" line="114"/>
<source>Help</source>
<translation>مدد</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="125"/>
<location filename="../actionmanager.cpp" line="117"/>
<source>Show in File Explorer</source>
<comment>File Explorer is the name of explorer.exe under Windows</comment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="131"/>
<location filename="../actionmanager.cpp" line="123"/>
<source>Show in directory</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="134"/>
<location filename="../actionmanager.cpp" line="126"/>
<source>Quit</source>
<translation>بند کرو</translation>
</message>
@ -710,141 +715,146 @@
<context>
<name>SettingsDialog</name>
<message>
<location filename="../settingsdialog.cpp" line="31"/>
<location filename="../settingsdialog.cpp" line="32"/>
<source>Settings</source>
<translation>سیٹنگاں</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="39"/>
<location filename="../settingsdialog.cpp" line="40"/>
<source>Options</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="51"/>
<location filename="../settingsdialog.cpp" line="52"/>
<source>Shortcuts</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="61"/>
<location filename="../settingsdialog.cpp" line="62"/>
<source>Editing shortcuts for action &quot;%1&quot;:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="70"/>
<location filename="../settingsdialog.cpp" line="71"/>
<source>Failed to set shortcuts</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="71"/>
<location filename="../settingsdialog.cpp" line="72"/>
<source>Please check if shortcuts are duplicated with existing shortcuts.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="78"/>
<location filename="../settingsdialog.cpp" line="79"/>
<source>Do nothing</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="79"/>
<location filename="../settingsdialog.cpp" line="80"/>
<source>Close the window</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="80"/>
<location filename="../settingsdialog.cpp" line="81"/>
<source>Toggle maximize</source>
<translation type="unfinished">ودھو ودھ بدلو</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="81"/>
<location filename="../settingsdialog.cpp" line="82"/>
<source>Toggle fullscreen</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="85"/>
<location filename="../settingsdialog.cpp" line="86"/>
<source>Zoom in and out</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="86"/>
<location filename="../settingsdialog.cpp" line="87"/>
<source>View next or previous item</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="90"/>
<location filename="../settingsdialog.cpp" line="91"/>
<source>Auto size</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="91"/>
<location filename="../settingsdialog.cpp" line="92"/>
<source>Maximized</source>
<translation>ودھ توں ودھ</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="92"/>
<location filename="../settingsdialog.cpp" line="93"/>
<source>Windowed</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="96"/>
<location filename="../settingsdialog.cpp" line="97"/>
<source>Round (Integer scaling)</source>
<comment>This option means round up for .5 and above</comment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="97"/>
<location filename="../settingsdialog.cpp" line="98"/>
<source>Ceil (Integer scaling)</source>
<comment>This option means always round up</comment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="98"/>
<location filename="../settingsdialog.cpp" line="99"/>
<source>Floor (Integer scaling)</source>
<comment>This option means always round down</comment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="99"/>
<location filename="../settingsdialog.cpp" line="100"/>
<source>Follow system (Fractional scaling)</source>
<comment>This option means don&apos;t round</comment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="122"/>
<location filename="../settingsdialog.cpp" line="123"/>
<source>Stay on top when start-up</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="123"/>
<location filename="../settingsdialog.cpp" line="124"/>
<source>Use built-in close window animation</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="124"/>
<location filename="../settingsdialog.cpp" line="125"/>
<source>Use light-color checkerboard</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="125"/>
<location filename="../settingsdialog.cpp" line="126"/>
<source>Loop the loaded gallery</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="126"/>
<source>Double-click behavior</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="127"/>
<source>Mouse wheel behavior</source>
<source>Auto long image mode</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="128"/>
<source>Default window size</source>
<source>Double-click behavior</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="129"/>
<source>Mouse wheel behavior</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="130"/>
<source>Default window size</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="131"/>
<source>HiDPI scale factor rounding policy</source>
<translation type="unfinished"></translation>
</message>
@ -852,7 +862,7 @@
<context>
<name>ShortcutEdit</name>
<message>
<location filename="../shortcutedit.cpp" line="109"/>
<location filename="../shortcutedit.cpp" line="104"/>
<source>No shortcuts</source>
<translation type="unfinished"></translation>
</message>
@ -860,7 +870,7 @@
<context>
<name>ShortcutEditor</name>
<message>
<location filename="../shortcutedit.cpp" line="75"/>
<location filename="../shortcutedit.cpp" line="70"/>
<source>Shortcut #%1</source>
<translation type="unfinished"></translation>
</message>

View File

@ -178,7 +178,7 @@
<context>
<name>GraphicsScene</name>
<message>
<location filename="../mainwindow.cpp" line="276"/>
<location filename="../mainwindow.cpp" line="292"/>
<location filename="../graphicsscene.cpp" line="100"/>
<source>Drag image here</source>
<translation>Перетащите изображение сюда</translation>
@ -213,189 +213,194 @@
<context>
<name>MainWindow</name>
<message>
<location filename="../mainwindow.cpp" line="181"/>
<location filename="../mainwindow.cpp" line="545"/>
<location filename="../mainwindow.cpp" line="190"/>
<location filename="../mainwindow.cpp" line="561"/>
<source>File url list is empty</source>
<translation>Список URL-адресов файлов пуст</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="445"/>
<location filename="../mainwindow.cpp" line="461"/>
<source>&amp;Copy</source>
<translation>&amp;Скопировать</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="553"/>
<location filename="../mainwindow.cpp" line="569"/>
<source>Image data is invalid</source>
<translation>Параметры изображения недействительны</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="560"/>
<location filename="../mainwindow.cpp" line="576"/>
<source>Not supported mimedata: %1</source>
<translation>Неподдерживаемые mimedata: %1</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="759"/>
<location filename="../mainwindow.cpp" line="783"/>
<source>Image From Clipboard</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="777"/>
<location filename="../mainwindow.cpp" line="801"/>
<source>Are you sure you want to move &quot;%1&quot; to recycle bin?</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="781"/>
<location filename="../mainwindow.cpp" line="805"/>
<source>Failed to move file to trash</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="782"/>
<location filename="../mainwindow.cpp" line="806"/>
<source>Move to trash failed, it might caused by file permission issue, file system limitation, or platform limitation.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="114"/>
<location filename="../actionmanager.cpp" line="106"/>
<source>Copy P&amp;ixmap</source>
<translation>Скопировать P&amp;ixmap</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="115"/>
<location filename="../actionmanager.cpp" line="107"/>
<source>Copy &amp;File Path</source>
<translation>Скопировать &amp;путь к файлу</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="133"/>
<location filename="../actionmanager.cpp" line="125"/>
<source>Properties</source>
<translation>Свойства</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="118"/>
<location filename="../actionmanager.cpp" line="110"/>
<location filename="../aboutdialog.cpp" line="41"/>
<source>Stay on top</source>
<translation>Поверх всех окон</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="119"/>
<location filename="../actionmanager.cpp" line="111"/>
<location filename="../aboutdialog.cpp" line="44"/>
<source>Protected mode</source>
<translation>Защищенный режим</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="120"/>
<location filename="../actionmanager.cpp" line="112"/>
<location filename="../aboutdialog.cpp" line="47"/>
<source>Keep transformation</source>
<comment>The &apos;transformation&apos; means the flip/rotation status that currently applied to the image view</comment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="99"/>
<location filename="../actionmanager.cpp" line="90"/>
<source>Zoom in</source>
<translation>Увеличить</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="100"/>
<location filename="../actionmanager.cpp" line="91"/>
<source>Zoom out</source>
<translation>Уменьшить</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="108"/>
<location filename="../actionmanager.cpp" line="99"/>
<source>Pause/Resume Animation</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="109"/>
<location filename="../actionmanager.cpp" line="100"/>
<source>Animation Go to Next Frame</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="111"/>
<location filename="../actionmanager.cpp" line="102"/>
<source>Flip &amp;Horizontally</source>
<translation>Отразить по &amp;горизонтали</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="112"/>
<location filename="../actionmanager.cpp" line="103"/>
<source>Fit to view</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="113"/>
<location filename="../actionmanager.cpp" line="104"/>
<source>Fit to width</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="116"/>
<location filename="../actionmanager.cpp" line="105"/>
<source>Fit long image</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="108"/>
<source>&amp;Paste</source>
<translation>&amp;Вставить</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="101"/>
<location filename="../actionmanager.cpp" line="92"/>
<source>Toggle Checkerboard</source>
<translation>Переключить фоновый рисунок</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="95"/>
<location filename="../actionmanager.cpp" line="86"/>
<source>&amp;Open...</source>
<translation>&amp;Открыть...</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="97"/>
<location filename="../actionmanager.cpp" line="88"/>
<source>Actual size</source>
<translation>Фактический размер</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="98"/>
<location filename="../actionmanager.cpp" line="89"/>
<source>Toggle maximize</source>
<translation>Переключить окно</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="102"/>
<location filename="../actionmanager.cpp" line="93"/>
<source>Rotate right</source>
<translation>Повернуть вправо</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="103"/>
<location filename="../actionmanager.cpp" line="94"/>
<source>Rotate left</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="105"/>
<location filename="../actionmanager.cpp" line="96"/>
<source>Previous image</source>
<translation>Предыдущее изображение</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="106"/>
<location filename="../actionmanager.cpp" line="97"/>
<source>Next image</source>
<translation>Следующее изображение</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="776"/>
<location filename="../actionmanager.cpp" line="117"/>
<location filename="../mainwindow.cpp" line="800"/>
<location filename="../actionmanager.cpp" line="109"/>
<source>Move to Trash</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="121"/>
<location filename="../actionmanager.cpp" line="113"/>
<source>Configure...</source>
<translation>Параметры...</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="122"/>
<location filename="../actionmanager.cpp" line="114"/>
<source>Help</source>
<translation>Помощь</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="125"/>
<location filename="../actionmanager.cpp" line="117"/>
<source>Show in File Explorer</source>
<comment>File Explorer is the name of explorer.exe under Windows</comment>
<translation>Показать в проводнике</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="131"/>
<location filename="../actionmanager.cpp" line="123"/>
<source>Show in directory</source>
<translation>Показать в папке</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="134"/>
<location filename="../actionmanager.cpp" line="126"/>
<source>Quit</source>
<translation>Выход</translation>
</message>
@ -726,141 +731,146 @@
<context>
<name>SettingsDialog</name>
<message>
<location filename="../settingsdialog.cpp" line="31"/>
<location filename="../settingsdialog.cpp" line="32"/>
<source>Settings</source>
<translation>Параметры</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="39"/>
<location filename="../settingsdialog.cpp" line="40"/>
<source>Options</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="51"/>
<location filename="../settingsdialog.cpp" line="52"/>
<source>Shortcuts</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="61"/>
<location filename="../settingsdialog.cpp" line="62"/>
<source>Editing shortcuts for action &quot;%1&quot;:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="70"/>
<location filename="../settingsdialog.cpp" line="71"/>
<source>Failed to set shortcuts</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="71"/>
<location filename="../settingsdialog.cpp" line="72"/>
<source>Please check if shortcuts are duplicated with existing shortcuts.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="78"/>
<location filename="../settingsdialog.cpp" line="79"/>
<source>Do nothing</source>
<translation>Ничего не делать</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="79"/>
<location filename="../settingsdialog.cpp" line="80"/>
<source>Close the window</source>
<translation>Закрыть окно</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="80"/>
<location filename="../settingsdialog.cpp" line="81"/>
<source>Toggle maximize</source>
<translation>Переключить окно</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="81"/>
<location filename="../settingsdialog.cpp" line="82"/>
<source>Toggle fullscreen</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="85"/>
<location filename="../settingsdialog.cpp" line="86"/>
<source>Zoom in and out</source>
<translation>Увеличение и уменьшение масштаба</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="86"/>
<location filename="../settingsdialog.cpp" line="87"/>
<source>View next or previous item</source>
<translation>Следующее или предыдущее изображение</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="90"/>
<location filename="../settingsdialog.cpp" line="91"/>
<source>Auto size</source>
<translation>Авторазмер</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="91"/>
<location filename="../settingsdialog.cpp" line="92"/>
<source>Maximized</source>
<translation>Максимизировать</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="92"/>
<location filename="../settingsdialog.cpp" line="93"/>
<source>Windowed</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="96"/>
<location filename="../settingsdialog.cpp" line="97"/>
<source>Round (Integer scaling)</source>
<comment>This option means round up for .5 and above</comment>
<translation>Round (целочисленное масштабирование)</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="97"/>
<location filename="../settingsdialog.cpp" line="98"/>
<source>Ceil (Integer scaling)</source>
<comment>This option means always round up</comment>
<translation>Ceil (целочисленное масштабирование)</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="98"/>
<location filename="../settingsdialog.cpp" line="99"/>
<source>Floor (Integer scaling)</source>
<comment>This option means always round down</comment>
<translation>Floor (целочисленное масштабирование)</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="99"/>
<location filename="../settingsdialog.cpp" line="100"/>
<source>Follow system (Fractional scaling)</source>
<comment>This option means don&apos;t round</comment>
<translation>Следовать системе (дробное масштабирование)</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="122"/>
<location filename="../settingsdialog.cpp" line="123"/>
<source>Stay on top when start-up</source>
<translation>Поверх всех окон при запуске</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="123"/>
<location filename="../settingsdialog.cpp" line="124"/>
<source>Use built-in close window animation</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="124"/>
<location filename="../settingsdialog.cpp" line="125"/>
<source>Use light-color checkerboard</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="125"/>
<location filename="../settingsdialog.cpp" line="126"/>
<source>Loop the loaded gallery</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="126"/>
<location filename="../settingsdialog.cpp" line="127"/>
<source>Auto long image mode</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="128"/>
<source>Double-click behavior</source>
<translation>Действие при двойном щелчке</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="127"/>
<location filename="../settingsdialog.cpp" line="129"/>
<source>Mouse wheel behavior</source>
<translation>Действие колеса мыши</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="128"/>
<location filename="../settingsdialog.cpp" line="130"/>
<source>Default window size</source>
<translation>Размер окна по умолчанию</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="129"/>
<location filename="../settingsdialog.cpp" line="131"/>
<source>HiDPI scale factor rounding policy</source>
<translation>Политика округления коэффициента масштабирования HiDPI</translation>
</message>
@ -868,7 +878,7 @@
<context>
<name>ShortcutEdit</name>
<message>
<location filename="../shortcutedit.cpp" line="109"/>
<location filename="../shortcutedit.cpp" line="104"/>
<source>No shortcuts</source>
<translation type="unfinished"></translation>
</message>
@ -876,7 +886,7 @@
<context>
<name>ShortcutEditor</name>
<message>
<location filename="../shortcutedit.cpp" line="75"/>
<location filename="../shortcutedit.cpp" line="70"/>
<source>Shortcut #%1</source>
<translation type="unfinished"></translation>
</message>

View File

@ -178,7 +178,7 @@
<context>
<name>GraphicsScene</name>
<message>
<location filename="../mainwindow.cpp" line="276"/>
<location filename="../mainwindow.cpp" line="292"/>
<location filename="../graphicsscene.cpp" line="100"/>
<source>Drag image here</source>
<translation type="unfinished"></translation>
@ -209,189 +209,194 @@
<context>
<name>MainWindow</name>
<message>
<location filename="../mainwindow.cpp" line="181"/>
<location filename="../mainwindow.cpp" line="545"/>
<location filename="../mainwindow.cpp" line="190"/>
<location filename="../mainwindow.cpp" line="561"/>
<source>File url list is empty</source>
<translation> ... (url) </translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="445"/>
<location filename="../mainwindow.cpp" line="461"/>
<source>&amp;Copy</source>
<translation>&amp;</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="553"/>
<location filename="../mainwindow.cpp" line="569"/>
<source>Image data is invalid</source>
<translation> </translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="560"/>
<location filename="../mainwindow.cpp" line="576"/>
<source>Not supported mimedata: %1</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="759"/>
<location filename="../mainwindow.cpp" line="783"/>
<source>Image From Clipboard</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="777"/>
<location filename="../mainwindow.cpp" line="801"/>
<source>Are you sure you want to move &quot;%1&quot; to recycle bin?</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="781"/>
<location filename="../mainwindow.cpp" line="805"/>
<source>Failed to move file to trash</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="782"/>
<location filename="../mainwindow.cpp" line="806"/>
<source>Move to trash failed, it might caused by file permission issue, file system limitation, or platform limitation.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="118"/>
<location filename="../actionmanager.cpp" line="110"/>
<location filename="../aboutdialog.cpp" line="41"/>
<source>Stay on top</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="119"/>
<location filename="../actionmanager.cpp" line="111"/>
<location filename="../aboutdialog.cpp" line="44"/>
<source>Protected mode</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="120"/>
<location filename="../actionmanager.cpp" line="112"/>
<location filename="../aboutdialog.cpp" line="47"/>
<source>Keep transformation</source>
<comment>The &apos;transformation&apos; means the flip/rotation status that currently applied to the image view</comment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="99"/>
<location filename="../actionmanager.cpp" line="90"/>
<source>Zoom in</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="100"/>
<location filename="../actionmanager.cpp" line="91"/>
<source>Zoom out</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="108"/>
<location filename="../actionmanager.cpp" line="99"/>
<source>Pause/Resume Animation</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="109"/>
<location filename="../actionmanager.cpp" line="100"/>
<source>Animation Go to Next Frame</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="111"/>
<location filename="../actionmanager.cpp" line="102"/>
<source>Flip &amp;Horizontally</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="112"/>
<location filename="../actionmanager.cpp" line="103"/>
<source>Fit to view</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="113"/>
<location filename="../actionmanager.cpp" line="104"/>
<source>Fit to width</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="114"/>
<source>Copy P&amp;ixmap</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="115"/>
<source>Copy &amp;File Path</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="116"/>
<source>&amp;Paste</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="101"/>
<source>Toggle Checkerboard</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="95"/>
<source>&amp;Open...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="97"/>
<source>Actual size</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="98"/>
<source>Toggle maximize</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="102"/>
<source>Rotate right</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="103"/>
<source>Rotate left</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="105"/>
<source>Previous image</source>
<source>Fit long image</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="106"/>
<source>Copy P&amp;ixmap</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="107"/>
<source>Copy &amp;File Path</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="108"/>
<source>&amp;Paste</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="92"/>
<source>Toggle Checkerboard</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="86"/>
<source>&amp;Open...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="88"/>
<source>Actual size</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="89"/>
<source>Toggle maximize</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="93"/>
<source>Rotate right</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="94"/>
<source>Rotate left</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="96"/>
<source>Previous image</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="97"/>
<source>Next image</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="776"/>
<location filename="../actionmanager.cpp" line="117"/>
<location filename="../mainwindow.cpp" line="800"/>
<location filename="../actionmanager.cpp" line="109"/>
<source>Move to Trash</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="121"/>
<location filename="../actionmanager.cpp" line="113"/>
<source>Configure...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="122"/>
<location filename="../actionmanager.cpp" line="114"/>
<source>Help</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="125"/>
<location filename="../actionmanager.cpp" line="117"/>
<source>Show in File Explorer</source>
<comment>File Explorer is the name of explorer.exe under Windows</comment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="131"/>
<location filename="../actionmanager.cpp" line="123"/>
<source>Show in directory</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="133"/>
<location filename="../actionmanager.cpp" line="125"/>
<source>Properties</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="134"/>
<location filename="../actionmanager.cpp" line="126"/>
<source>Quit</source>
<translation type="unfinished"></translation>
</message>
@ -722,141 +727,146 @@
<context>
<name>SettingsDialog</name>
<message>
<location filename="../settingsdialog.cpp" line="31"/>
<location filename="../settingsdialog.cpp" line="32"/>
<source>Settings</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="39"/>
<location filename="../settingsdialog.cpp" line="40"/>
<source>Options</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="51"/>
<location filename="../settingsdialog.cpp" line="52"/>
<source>Shortcuts</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="61"/>
<location filename="../settingsdialog.cpp" line="62"/>
<source>Editing shortcuts for action &quot;%1&quot;:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="70"/>
<location filename="../settingsdialog.cpp" line="71"/>
<source>Failed to set shortcuts</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="71"/>
<location filename="../settingsdialog.cpp" line="72"/>
<source>Please check if shortcuts are duplicated with existing shortcuts.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="78"/>
<location filename="../settingsdialog.cpp" line="79"/>
<source>Do nothing</source>
<translation> </translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="79"/>
<location filename="../settingsdialog.cpp" line="80"/>
<source>Close the window</source>
<translation> </translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="80"/>
<location filename="../settingsdialog.cpp" line="81"/>
<source>Toggle maximize</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="81"/>
<location filename="../settingsdialog.cpp" line="82"/>
<source>Toggle fullscreen</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="85"/>
<location filename="../settingsdialog.cpp" line="86"/>
<source>Zoom in and out</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="86"/>
<location filename="../settingsdialog.cpp" line="87"/>
<source>View next or previous item</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="90"/>
<location filename="../settingsdialog.cpp" line="91"/>
<source>Auto size</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="91"/>
<location filename="../settingsdialog.cpp" line="92"/>
<source>Maximized</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="92"/>
<location filename="../settingsdialog.cpp" line="93"/>
<source>Windowed</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="96"/>
<location filename="../settingsdialog.cpp" line="97"/>
<source>Round (Integer scaling)</source>
<comment>This option means round up for .5 and above</comment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="97"/>
<location filename="../settingsdialog.cpp" line="98"/>
<source>Ceil (Integer scaling)</source>
<comment>This option means always round up</comment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="98"/>
<location filename="../settingsdialog.cpp" line="99"/>
<source>Floor (Integer scaling)</source>
<comment>This option means always round down</comment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="99"/>
<location filename="../settingsdialog.cpp" line="100"/>
<source>Follow system (Fractional scaling)</source>
<comment>This option means don&apos;t round</comment>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="122"/>
<location filename="../settingsdialog.cpp" line="123"/>
<source>Stay on top when start-up</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="123"/>
<location filename="../settingsdialog.cpp" line="124"/>
<source>Use built-in close window animation</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="124"/>
<location filename="../settingsdialog.cpp" line="125"/>
<source>Use light-color checkerboard</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="125"/>
<location filename="../settingsdialog.cpp" line="126"/>
<source>Loop the loaded gallery</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="126"/>
<source>Double-click behavior</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="127"/>
<source>Mouse wheel behavior</source>
<source>Auto long image mode</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="128"/>
<source>Default window size</source>
<source>Double-click behavior</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="129"/>
<source>Mouse wheel behavior</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="130"/>
<source>Default window size</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="131"/>
<source>HiDPI scale factor rounding policy</source>
<translation type="unfinished"></translation>
</message>
@ -864,7 +874,7 @@
<context>
<name>ShortcutEdit</name>
<message>
<location filename="../shortcutedit.cpp" line="109"/>
<location filename="../shortcutedit.cpp" line="104"/>
<source>No shortcuts</source>
<translation type="unfinished"></translation>
</message>
@ -872,7 +882,7 @@
<context>
<name>ShortcutEditor</name>
<message>
<location filename="../shortcutedit.cpp" line="75"/>
<location filename="../shortcutedit.cpp" line="70"/>
<source>Shortcut #%1</source>
<translation type="unfinished"></translation>
</message>

View File

@ -174,7 +174,7 @@
<context>
<name>GraphicsScene</name>
<message>
<location filename="../mainwindow.cpp" line="276"/>
<location filename="../mainwindow.cpp" line="292"/>
<location filename="../graphicsscene.cpp" line="100"/>
<source>Drag image here</source>
<translation> </translation>
@ -197,189 +197,194 @@
<context>
<name>MainWindow</name>
<message>
<location filename="../mainwindow.cpp" line="181"/>
<location filename="../mainwindow.cpp" line="545"/>
<location filename="../mainwindow.cpp" line="190"/>
<location filename="../mainwindow.cpp" line="561"/>
<source>File url list is empty</source>
<translation> ி ி ி </translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="445"/>
<location filename="../mainwindow.cpp" line="461"/>
<source>&amp;Copy</source>
<translation> (&amp;c)</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="553"/>
<location filename="../mainwindow.cpp" line="569"/>
<source>Image data is invalid</source>
<translation> </translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="560"/>
<location filename="../mainwindow.cpp" line="576"/>
<source>Not supported mimedata: %1</source>
<translation> ிி: %1</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="759"/>
<location filename="../mainwindow.cpp" line="783"/>
<source>Image From Clipboard</source>
<translation>ிிிி </translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="777"/>
<location filename="../mainwindow.cpp" line="801"/>
<source>Are you sure you want to move &quot;%1&quot; to recycle bin?</source>
<translation>ி ி &quot;%1&quot; ிி?</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="781"/>
<location filename="../mainwindow.cpp" line="805"/>
<source>Failed to move file to trash</source>
<translation> ி ி</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="782"/>
<location filename="../mainwindow.cpp" line="806"/>
<source>Move to trash failed, it might caused by file permission issue, file system limitation, or platform limitation.</source>
<translation> ி, ி, ி .</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="114"/>
<location filename="../actionmanager.cpp" line="106"/>
<source>Copy P&amp;ixmap</source>
<translation>ி &amp; </translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="115"/>
<location filename="../actionmanager.cpp" line="107"/>
<source>Copy &amp;File Path</source>
<translation> </translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="133"/>
<location filename="../actionmanager.cpp" line="125"/>
<source>Properties</source>
<translation></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="118"/>
<location filename="../actionmanager.cpp" line="110"/>
<location filename="../aboutdialog.cpp" line="41"/>
<source>Stay on top</source>
<translation> </translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="119"/>
<location filename="../actionmanager.cpp" line="111"/>
<location filename="../aboutdialog.cpp" line="44"/>
<source>Protected mode</source>
<translation> </translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="120"/>
<location filename="../actionmanager.cpp" line="112"/>
<location filename="../aboutdialog.cpp" line="47"/>
<source>Keep transformation</source>
<comment>The &apos;transformation&apos; means the flip/rotation status that currently applied to the image view</comment>
<translation> </translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="99"/>
<location filename="../actionmanager.cpp" line="90"/>
<source>Zoom in</source>
<translation>ி</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="100"/>
<location filename="../actionmanager.cpp" line="91"/>
<source>Zoom out</source>
<translation>ிி</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="108"/>
<location filename="../actionmanager.cpp" line="99"/>
<source>Pause/Resume Animation</source>
<translation>ி/ி </translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="109"/>
<location filename="../actionmanager.cpp" line="100"/>
<source>Animation Go to Next Frame</source>
<translation>ி ி </translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="111"/>
<location filename="../actionmanager.cpp" line="102"/>
<source>Flip &amp;Horizontally</source>
<translation>ி </translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="112"/>
<location filename="../actionmanager.cpp" line="103"/>
<source>Fit to view</source>
<translation> </translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="113"/>
<location filename="../actionmanager.cpp" line="104"/>
<source>Fit to width</source>
<translation>ி </translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="116"/>
<location filename="../actionmanager.cpp" line="105"/>
<source>Fit long image</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="108"/>
<source>&amp;Paste</source>
<translation> (&amp;p)</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="101"/>
<location filename="../actionmanager.cpp" line="92"/>
<source>Toggle Checkerboard</source>
<translation> </translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="95"/>
<location filename="../actionmanager.cpp" line="86"/>
<source>&amp;Open...</source>
<translation>&amp; ி ...</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="97"/>
<location filename="../actionmanager.cpp" line="88"/>
<source>Actual size</source>
<translation> </translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="98"/>
<location filename="../actionmanager.cpp" line="89"/>
<source>Toggle maximize</source>
<translation>ி </translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="102"/>
<location filename="../actionmanager.cpp" line="93"/>
<source>Rotate right</source>
<translation> </translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="103"/>
<location filename="../actionmanager.cpp" line="94"/>
<source>Rotate left</source>
<translation> </translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="105"/>
<location filename="../actionmanager.cpp" line="96"/>
<source>Previous image</source>
<translation> </translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="106"/>
<location filename="../actionmanager.cpp" line="97"/>
<source>Next image</source>
<translation> </translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="776"/>
<location filename="../actionmanager.cpp" line="117"/>
<location filename="../mainwindow.cpp" line="800"/>
<location filename="../actionmanager.cpp" line="109"/>
<source>Move to Trash</source>
<translation> </translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="121"/>
<location filename="../actionmanager.cpp" line="113"/>
<source>Configure...</source>
<translation> ...</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="122"/>
<location filename="../actionmanager.cpp" line="114"/>
<source>Help</source>
<translation>ி</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="125"/>
<location filename="../actionmanager.cpp" line="117"/>
<source>Show in File Explorer</source>
<comment>File Explorer is the name of explorer.exe under Windows</comment>
<translation> ி ி</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="131"/>
<location filename="../actionmanager.cpp" line="123"/>
<source>Show in directory</source>
<translation>ி </translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="134"/>
<location filename="../actionmanager.cpp" line="126"/>
<source>Quit</source>
<translation>ி</translation>
</message>
@ -710,141 +715,146 @@
<context>
<name>SettingsDialog</name>
<message>
<location filename="../settingsdialog.cpp" line="31"/>
<location filename="../settingsdialog.cpp" line="32"/>
<source>Settings</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="39"/>
<location filename="../settingsdialog.cpp" line="40"/>
<source>Options</source>
<translation>ி</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="51"/>
<location filename="../settingsdialog.cpp" line="52"/>
<source>Shortcuts</source>
<translation>ி</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="61"/>
<location filename="../settingsdialog.cpp" line="62"/>
<source>Editing shortcuts for action &quot;%1&quot;:</source>
<translation> ி ி &quot;%1&quot;:</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="70"/>
<location filename="../settingsdialog.cpp" line="71"/>
<source>Failed to set shortcuts</source>
<translation>ி ி ி</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="71"/>
<location filename="../settingsdialog.cpp" line="72"/>
<source>Please check if shortcuts are duplicated with existing shortcuts.</source>
<translation> ி ி ி.</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="78"/>
<location filename="../settingsdialog.cpp" line="79"/>
<source>Do nothing</source>
<translation> </translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="79"/>
<location filename="../settingsdialog.cpp" line="80"/>
<source>Close the window</source>
<translation> </translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="80"/>
<location filename="../settingsdialog.cpp" line="81"/>
<source>Toggle maximize</source>
<translation>ி </translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="81"/>
<location filename="../settingsdialog.cpp" line="82"/>
<source>Toggle fullscreen</source>
<translation> ி</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="85"/>
<location filename="../settingsdialog.cpp" line="86"/>
<source>Zoom in and out</source>
<translation> ி ி</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="86"/>
<location filename="../settingsdialog.cpp" line="87"/>
<source>View next or previous item</source>
<translation> ி </translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="90"/>
<location filename="../settingsdialog.cpp" line="91"/>
<source>Auto size</source>
<translation> </translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="91"/>
<location filename="../settingsdialog.cpp" line="92"/>
<source>Maximized</source>
<translation>ி</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="92"/>
<location filename="../settingsdialog.cpp" line="93"/>
<source>Windowed</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="96"/>
<location filename="../settingsdialog.cpp" line="97"/>
<source>Round (Integer scaling)</source>
<comment>This option means round up for .5 and above</comment>
<translation> ( ி)</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="97"/>
<location filename="../settingsdialog.cpp" line="98"/>
<source>Ceil (Integer scaling)</source>
<comment>This option means always round up</comment>
<translation> ( ி)</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="98"/>
<location filename="../settingsdialog.cpp" line="99"/>
<source>Floor (Integer scaling)</source>
<comment>This option means always round down</comment>
<translation>ி ( ி)</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="99"/>
<location filename="../settingsdialog.cpp" line="100"/>
<source>Follow system (Fractional scaling)</source>
<comment>This option means don&apos;t round</comment>
<translation>ிி ி (ி ி)</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="122"/>
<location filename="../settingsdialog.cpp" line="123"/>
<source>Stay on top when start-up</source>
<translation>ி </translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="123"/>
<location filename="../settingsdialog.cpp" line="124"/>
<source>Use built-in close window animation</source>
<translation> ி </translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="124"/>
<location filename="../settingsdialog.cpp" line="125"/>
<source>Use light-color checkerboard</source>
<translation>ி- </translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="125"/>
<location filename="../settingsdialog.cpp" line="126"/>
<source>Loop the loaded gallery</source>
<translation> ி </translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="126"/>
<location filename="../settingsdialog.cpp" line="127"/>
<source>Auto long image mode</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="128"/>
<source>Double-click behavior</source>
<translation> </translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="127"/>
<location filename="../settingsdialog.cpp" line="129"/>
<source>Mouse wheel behavior</source>
<translation>ி </translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="128"/>
<location filename="../settingsdialog.cpp" line="130"/>
<source>Default window size</source>
<translation>ி </translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="129"/>
<location filename="../settingsdialog.cpp" line="131"/>
<source>HiDPI scale factor rounding policy</source>
<translation>HIDPI ி ி ி </translation>
</message>
@ -852,7 +862,7 @@
<context>
<name>ShortcutEdit</name>
<message>
<location filename="../shortcutedit.cpp" line="109"/>
<location filename="../shortcutedit.cpp" line="104"/>
<source>No shortcuts</source>
<translation>ி </translation>
</message>
@ -860,7 +870,7 @@
<context>
<name>ShortcutEditor</name>
<message>
<location filename="../shortcutedit.cpp" line="75"/>
<location filename="../shortcutedit.cpp" line="70"/>
<source>Shortcut #%1</source>
<translation>ி #%1</translation>
</message>

View File

@ -178,7 +178,7 @@
<context>
<name>GraphicsScene</name>
<message>
<location filename="../mainwindow.cpp" line="276"/>
<location filename="../mainwindow.cpp" line="292"/>
<location filename="../graphicsscene.cpp" line="100"/>
<source>Drag image here</source>
<translation>Resmi buraya sürükleyin</translation>
@ -213,189 +213,194 @@
<context>
<name>MainWindow</name>
<message>
<location filename="../mainwindow.cpp" line="181"/>
<location filename="../mainwindow.cpp" line="545"/>
<location filename="../mainwindow.cpp" line="190"/>
<location filename="../mainwindow.cpp" line="561"/>
<source>File url list is empty</source>
<translation>Dosya URL listesi boş</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="445"/>
<location filename="../mainwindow.cpp" line="461"/>
<source>&amp;Copy</source>
<translation>&amp;Kopyala</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="553"/>
<location filename="../mainwindow.cpp" line="569"/>
<source>Image data is invalid</source>
<translation>Resim verisi geçersiz</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="560"/>
<location filename="../mainwindow.cpp" line="576"/>
<source>Not supported mimedata: %1</source>
<translation>Desteklenmeyen dosya türü verisi: %1</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="759"/>
<location filename="../mainwindow.cpp" line="783"/>
<source>Image From Clipboard</source>
<translation>Panodaki Resim</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="777"/>
<location filename="../mainwindow.cpp" line="801"/>
<source>Are you sure you want to move &quot;%1&quot; to recycle bin?</source>
<translation>&quot;%1&quot; ögesini geri dönüşüm kutusuna taşımak istediğinizden emin misiniz?</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="781"/>
<location filename="../mainwindow.cpp" line="805"/>
<source>Failed to move file to trash</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="782"/>
<location filename="../mainwindow.cpp" line="806"/>
<source>Move to trash failed, it might caused by file permission issue, file system limitation, or platform limitation.</source>
<translation>Çöp kutusuna taşıma başarısız oldu, dosya izin sorunu, dosya sistemi sınırlaması veya platform sınırlamasından kaynaklanıyor olabilir.</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="114"/>
<location filename="../actionmanager.cpp" line="106"/>
<source>Copy P&amp;ixmap</source>
<translation>P&amp;ixmap&apos;i Kopyala</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="115"/>
<location filename="../actionmanager.cpp" line="107"/>
<source>Copy &amp;File Path</source>
<translation>&amp;Dosya Yolunu Kopyala</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="133"/>
<location filename="../actionmanager.cpp" line="125"/>
<source>Properties</source>
<translation>Özellikler</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="118"/>
<location filename="../actionmanager.cpp" line="110"/>
<location filename="../aboutdialog.cpp" line="41"/>
<source>Stay on top</source>
<translation>Üstte tut</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="119"/>
<location filename="../actionmanager.cpp" line="111"/>
<location filename="../aboutdialog.cpp" line="44"/>
<source>Protected mode</source>
<translation>Korumalı kip</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="120"/>
<location filename="../actionmanager.cpp" line="112"/>
<location filename="../aboutdialog.cpp" line="47"/>
<source>Keep transformation</source>
<comment>The &apos;transformation&apos; means the flip/rotation status that currently applied to the image view</comment>
<translation>Dönüşümü koru</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="99"/>
<location filename="../actionmanager.cpp" line="90"/>
<source>Zoom in</source>
<translation>Yaklaştır</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="100"/>
<location filename="../actionmanager.cpp" line="91"/>
<source>Zoom out</source>
<translation>Uzaklaştır</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="108"/>
<location filename="../actionmanager.cpp" line="99"/>
<source>Pause/Resume Animation</source>
<translation>Canlandırmayı Duraklat/Sürdür</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="109"/>
<location filename="../actionmanager.cpp" line="100"/>
<source>Animation Go to Next Frame</source>
<translation>Canlandırma Sonraki Kareye Git</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="111"/>
<location filename="../actionmanager.cpp" line="102"/>
<source>Flip &amp;Horizontally</source>
<translation>&amp;Yatay Çevir</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="112"/>
<location filename="../actionmanager.cpp" line="103"/>
<source>Fit to view</source>
<translation>Görünüme sığdır</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="113"/>
<location filename="../actionmanager.cpp" line="104"/>
<source>Fit to width</source>
<translation>Genişliğe sığdır</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="116"/>
<location filename="../actionmanager.cpp" line="105"/>
<source>Fit long image</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="108"/>
<source>&amp;Paste</source>
<translation>Ya&amp;pıştır</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="101"/>
<location filename="../actionmanager.cpp" line="92"/>
<source>Toggle Checkerboard</source>
<translation>Damalı Ekrana Geç</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="95"/>
<location filename="../actionmanager.cpp" line="86"/>
<source>&amp;Open...</source>
<translation>&amp;...</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="97"/>
<location filename="../actionmanager.cpp" line="88"/>
<source>Actual size</source>
<translation>Gerçek boyut</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="98"/>
<location filename="../actionmanager.cpp" line="89"/>
<source>Toggle maximize</source>
<translation>Tam boyuta geç</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="102"/>
<location filename="../actionmanager.cpp" line="93"/>
<source>Rotate right</source>
<translation>Sağa döndür</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="103"/>
<location filename="../actionmanager.cpp" line="94"/>
<source>Rotate left</source>
<translation>Sola döndür</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="105"/>
<location filename="../actionmanager.cpp" line="96"/>
<source>Previous image</source>
<translation>Önceki resim</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="106"/>
<location filename="../actionmanager.cpp" line="97"/>
<source>Next image</source>
<translation>Sonraki resim</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="776"/>
<location filename="../actionmanager.cpp" line="117"/>
<location filename="../mainwindow.cpp" line="800"/>
<location filename="../actionmanager.cpp" line="109"/>
<source>Move to Trash</source>
<translation>Çöp Kutusuna Taşı</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="121"/>
<location filename="../actionmanager.cpp" line="113"/>
<source>Configure...</source>
<translation>Yapılandır...</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="122"/>
<location filename="../actionmanager.cpp" line="114"/>
<source>Help</source>
<translation>Yardım</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="125"/>
<location filename="../actionmanager.cpp" line="117"/>
<source>Show in File Explorer</source>
<comment>File Explorer is the name of explorer.exe under Windows</comment>
<translation>Dosya Gezgini&apos;nde Göster</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="131"/>
<location filename="../actionmanager.cpp" line="123"/>
<source>Show in directory</source>
<translation>Dizinde göster</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="134"/>
<location filename="../actionmanager.cpp" line="126"/>
<source>Quit</source>
<translation>Çıkış</translation>
</message>
@ -726,141 +731,146 @@
<context>
<name>SettingsDialog</name>
<message>
<location filename="../settingsdialog.cpp" line="31"/>
<location filename="../settingsdialog.cpp" line="32"/>
<source>Settings</source>
<translation>Ayarlar</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="39"/>
<location filename="../settingsdialog.cpp" line="40"/>
<source>Options</source>
<translation>Seçenekler</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="51"/>
<location filename="../settingsdialog.cpp" line="52"/>
<source>Shortcuts</source>
<translation>Kısayollar</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="61"/>
<location filename="../settingsdialog.cpp" line="62"/>
<source>Editing shortcuts for action &quot;%1&quot;:</source>
<translation>&quot;%1&quot; için kısayol düzenleniyor:</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="70"/>
<location filename="../settingsdialog.cpp" line="71"/>
<source>Failed to set shortcuts</source>
<translation>Kısayollar ayarlanamadı</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="71"/>
<location filename="../settingsdialog.cpp" line="72"/>
<source>Please check if shortcuts are duplicated with existing shortcuts.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="78"/>
<location filename="../settingsdialog.cpp" line="79"/>
<source>Do nothing</source>
<translation>Hiçbir şey yapma</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="79"/>
<location filename="../settingsdialog.cpp" line="80"/>
<source>Close the window</source>
<translation>Pencereyi kapat</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="80"/>
<location filename="../settingsdialog.cpp" line="81"/>
<source>Toggle maximize</source>
<translation>Tam boyuta geç</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="81"/>
<location filename="../settingsdialog.cpp" line="82"/>
<source>Toggle fullscreen</source>
<translation>Tam ekranı /kapat</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="85"/>
<location filename="../settingsdialog.cpp" line="86"/>
<source>Zoom in and out</source>
<translation>Yaklaştır ve uzaklaştır</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="86"/>
<location filename="../settingsdialog.cpp" line="87"/>
<source>View next or previous item</source>
<translation>Sonraki veya önceki ögeyi görüntüle</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="90"/>
<location filename="../settingsdialog.cpp" line="91"/>
<source>Auto size</source>
<translation>Otomatik boyut</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="91"/>
<location filename="../settingsdialog.cpp" line="92"/>
<source>Maximized</source>
<translation>Tam boyut</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="92"/>
<location filename="../settingsdialog.cpp" line="93"/>
<source>Windowed</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="96"/>
<location filename="../settingsdialog.cpp" line="97"/>
<source>Round (Integer scaling)</source>
<comment>This option means round up for .5 and above</comment>
<translation>Yuvarlak (Tamsayı ölçekleme)</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="97"/>
<location filename="../settingsdialog.cpp" line="98"/>
<source>Ceil (Integer scaling)</source>
<comment>This option means always round up</comment>
<translation>Tavan (Tamsayı ölçekleme)</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="98"/>
<location filename="../settingsdialog.cpp" line="99"/>
<source>Floor (Integer scaling)</source>
<comment>This option means always round down</comment>
<translation>Kat (Tamsayı ölçekleme)</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="99"/>
<location filename="../settingsdialog.cpp" line="100"/>
<source>Follow system (Fractional scaling)</source>
<comment>This option means don&apos;t round</comment>
<translation>Sistemi takip et (Kesirli ölçekleme)</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="122"/>
<location filename="../settingsdialog.cpp" line="123"/>
<source>Stay on top when start-up</source>
<translation>ılışta pencerelerin üstünde kal</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="123"/>
<location filename="../settingsdialog.cpp" line="124"/>
<source>Use built-in close window animation</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="124"/>
<location filename="../settingsdialog.cpp" line="125"/>
<source>Use light-color checkerboard</source>
<translation>ık renk dama tahtası kullan</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="125"/>
<location filename="../settingsdialog.cpp" line="126"/>
<source>Loop the loaded gallery</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="126"/>
<location filename="../settingsdialog.cpp" line="127"/>
<source>Auto long image mode</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="128"/>
<source>Double-click behavior</source>
<translation>Çift tıklama davranışı</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="127"/>
<location filename="../settingsdialog.cpp" line="129"/>
<source>Mouse wheel behavior</source>
<translation>Fare tekeri davranışı</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="128"/>
<location filename="../settingsdialog.cpp" line="130"/>
<source>Default window size</source>
<translation>Öntanımlı pencere boyutu</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="129"/>
<location filename="../settingsdialog.cpp" line="131"/>
<source>HiDPI scale factor rounding policy</source>
<translation>HiDPI ölçek katsayısı yuvarlama ilkesi</translation>
</message>
@ -868,7 +878,7 @@
<context>
<name>ShortcutEdit</name>
<message>
<location filename="../shortcutedit.cpp" line="109"/>
<location filename="../shortcutedit.cpp" line="104"/>
<source>No shortcuts</source>
<translation>Kısayol yok</translation>
</message>
@ -876,7 +886,7 @@
<context>
<name>ShortcutEditor</name>
<message>
<location filename="../shortcutedit.cpp" line="75"/>
<location filename="../shortcutedit.cpp" line="70"/>
<source>Shortcut #%1</source>
<translation>Kısayol #%1</translation>
</message>

View File

@ -174,7 +174,7 @@
<context>
<name>GraphicsScene</name>
<message>
<location filename="../mainwindow.cpp" line="276"/>
<location filename="../mainwindow.cpp" line="292"/>
<location filename="../graphicsscene.cpp" line="100"/>
<source>Drag image here</source>
<translation>Перетягніть зображення сюди</translation>
@ -209,189 +209,194 @@
<context>
<name>MainWindow</name>
<message>
<location filename="../mainwindow.cpp" line="181"/>
<location filename="../mainwindow.cpp" line="545"/>
<location filename="../mainwindow.cpp" line="190"/>
<location filename="../mainwindow.cpp" line="561"/>
<source>File url list is empty</source>
<translation>Список URL-адрес файлів порожній</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="445"/>
<location filename="../mainwindow.cpp" line="461"/>
<source>&amp;Copy</source>
<translation>&amp;Скопіювати</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="553"/>
<location filename="../mainwindow.cpp" line="569"/>
<source>Image data is invalid</source>
<translation>Дані зображення недійсні</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="560"/>
<location filename="../mainwindow.cpp" line="576"/>
<source>Not supported mimedata: %1</source>
<translation>Не підтримується mimedata: %1</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="759"/>
<location filename="../mainwindow.cpp" line="783"/>
<source>Image From Clipboard</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="777"/>
<location filename="../mainwindow.cpp" line="801"/>
<source>Are you sure you want to move &quot;%1&quot; to recycle bin?</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="781"/>
<location filename="../mainwindow.cpp" line="805"/>
<source>Failed to move file to trash</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="782"/>
<location filename="../mainwindow.cpp" line="806"/>
<source>Move to trash failed, it might caused by file permission issue, file system limitation, or platform limitation.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="114"/>
<location filename="../actionmanager.cpp" line="106"/>
<source>Copy P&amp;ixmap</source>
<translation>Скопіювати P&amp;ixmap</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="115"/>
<location filename="../actionmanager.cpp" line="107"/>
<source>Copy &amp;File Path</source>
<translation>Скопіювати &amp;шлях до файлу</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="133"/>
<location filename="../actionmanager.cpp" line="125"/>
<source>Properties</source>
<translation>Властивості</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="118"/>
<location filename="../actionmanager.cpp" line="110"/>
<location filename="../aboutdialog.cpp" line="41"/>
<source>Stay on top</source>
<translation>Поверх всіх вікон</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="119"/>
<location filename="../actionmanager.cpp" line="111"/>
<location filename="../aboutdialog.cpp" line="44"/>
<source>Protected mode</source>
<translation>Захищений режим</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="120"/>
<location filename="../actionmanager.cpp" line="112"/>
<location filename="../aboutdialog.cpp" line="47"/>
<source>Keep transformation</source>
<comment>The &apos;transformation&apos; means the flip/rotation status that currently applied to the image view</comment>
<translation>Зберігати трансформацію</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="99"/>
<location filename="../actionmanager.cpp" line="90"/>
<source>Zoom in</source>
<translation>Збільшити</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="100"/>
<location filename="../actionmanager.cpp" line="91"/>
<source>Zoom out</source>
<translation>Зменшити</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="108"/>
<location filename="../actionmanager.cpp" line="99"/>
<source>Pause/Resume Animation</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="109"/>
<location filename="../actionmanager.cpp" line="100"/>
<source>Animation Go to Next Frame</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="111"/>
<location filename="../actionmanager.cpp" line="102"/>
<source>Flip &amp;Horizontally</source>
<translation>Перевернути по &amp;горизонталі</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="112"/>
<location filename="../actionmanager.cpp" line="103"/>
<source>Fit to view</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="113"/>
<location filename="../actionmanager.cpp" line="104"/>
<source>Fit to width</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="116"/>
<location filename="../actionmanager.cpp" line="105"/>
<source>Fit long image</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="108"/>
<source>&amp;Paste</source>
<translation>&amp;Вставити</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="101"/>
<location filename="../actionmanager.cpp" line="92"/>
<source>Toggle Checkerboard</source>
<translation>Перемкнути шахову дошку</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="95"/>
<location filename="../actionmanager.cpp" line="86"/>
<source>&amp;Open...</source>
<translation>&amp;Відкрити...</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="97"/>
<location filename="../actionmanager.cpp" line="88"/>
<source>Actual size</source>
<translation>Фактичний розмір</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="98"/>
<location filename="../actionmanager.cpp" line="89"/>
<source>Toggle maximize</source>
<translation>Перемкнути на максимум</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="102"/>
<location filename="../actionmanager.cpp" line="93"/>
<source>Rotate right</source>
<translation>Перегорнути праворуч</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="103"/>
<location filename="../actionmanager.cpp" line="94"/>
<source>Rotate left</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="105"/>
<location filename="../actionmanager.cpp" line="96"/>
<source>Previous image</source>
<translation>Попереднє зображення</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="106"/>
<location filename="../actionmanager.cpp" line="97"/>
<source>Next image</source>
<translation>Наступне зображення</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="776"/>
<location filename="../actionmanager.cpp" line="117"/>
<location filename="../mainwindow.cpp" line="800"/>
<location filename="../actionmanager.cpp" line="109"/>
<source>Move to Trash</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="121"/>
<location filename="../actionmanager.cpp" line="113"/>
<source>Configure...</source>
<translation>Налаштувати...</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="122"/>
<location filename="../actionmanager.cpp" line="114"/>
<source>Help</source>
<translation>Допомога</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="125"/>
<location filename="../actionmanager.cpp" line="117"/>
<source>Show in File Explorer</source>
<comment>File Explorer is the name of explorer.exe under Windows</comment>
<translation>Показати у файловому провіднику</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="131"/>
<location filename="../actionmanager.cpp" line="123"/>
<source>Show in directory</source>
<translation>Показати у теці</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="134"/>
<location filename="../actionmanager.cpp" line="126"/>
<source>Quit</source>
<translation>Вийти</translation>
</message>
@ -722,141 +727,146 @@
<context>
<name>SettingsDialog</name>
<message>
<location filename="../settingsdialog.cpp" line="31"/>
<location filename="../settingsdialog.cpp" line="32"/>
<source>Settings</source>
<translation>Налаштування</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="39"/>
<location filename="../settingsdialog.cpp" line="40"/>
<source>Options</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="51"/>
<location filename="../settingsdialog.cpp" line="52"/>
<source>Shortcuts</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="61"/>
<location filename="../settingsdialog.cpp" line="62"/>
<source>Editing shortcuts for action &quot;%1&quot;:</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="70"/>
<location filename="../settingsdialog.cpp" line="71"/>
<source>Failed to set shortcuts</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="71"/>
<location filename="../settingsdialog.cpp" line="72"/>
<source>Please check if shortcuts are duplicated with existing shortcuts.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="78"/>
<location filename="../settingsdialog.cpp" line="79"/>
<source>Do nothing</source>
<translation>Нічого не робити</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="79"/>
<location filename="../settingsdialog.cpp" line="80"/>
<source>Close the window</source>
<translation>Закрити вікно</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="80"/>
<location filename="../settingsdialog.cpp" line="81"/>
<source>Toggle maximize</source>
<translation>Перемкнути на максимум</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="81"/>
<location filename="../settingsdialog.cpp" line="82"/>
<source>Toggle fullscreen</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="85"/>
<location filename="../settingsdialog.cpp" line="86"/>
<source>Zoom in and out</source>
<translation>Збільшення та зменшення</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="86"/>
<location filename="../settingsdialog.cpp" line="87"/>
<source>View next or previous item</source>
<translation>Переглянути наступний або попередній елемент</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="90"/>
<location filename="../settingsdialog.cpp" line="91"/>
<source>Auto size</source>
<translation>Автоматичний розмір</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="91"/>
<location filename="../settingsdialog.cpp" line="92"/>
<source>Maximized</source>
<translation>Максимізувати</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="92"/>
<location filename="../settingsdialog.cpp" line="93"/>
<source>Windowed</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="96"/>
<location filename="../settingsdialog.cpp" line="97"/>
<source>Round (Integer scaling)</source>
<comment>This option means round up for .5 and above</comment>
<translation>Round (цілочисельне масштабування)</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="97"/>
<location filename="../settingsdialog.cpp" line="98"/>
<source>Ceil (Integer scaling)</source>
<comment>This option means always round up</comment>
<translation>Ceil (цілочисельне масштабування)</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="98"/>
<location filename="../settingsdialog.cpp" line="99"/>
<source>Floor (Integer scaling)</source>
<comment>This option means always round down</comment>
<translation>Floor (цілочисельне масштабування)</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="99"/>
<location filename="../settingsdialog.cpp" line="100"/>
<source>Follow system (Fractional scaling)</source>
<comment>This option means don&apos;t round</comment>
<translation>Стежити за системою (дробове масштабування)</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="122"/>
<location filename="../settingsdialog.cpp" line="123"/>
<source>Stay on top when start-up</source>
<translation>Поверх всіх вікон під час запуску</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="123"/>
<location filename="../settingsdialog.cpp" line="124"/>
<source>Use built-in close window animation</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="124"/>
<location filename="../settingsdialog.cpp" line="125"/>
<source>Use light-color checkerboard</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="125"/>
<location filename="../settingsdialog.cpp" line="126"/>
<source>Loop the loaded gallery</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="126"/>
<location filename="../settingsdialog.cpp" line="127"/>
<source>Auto long image mode</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="128"/>
<source>Double-click behavior</source>
<translation>Поведінка при подвійному кліку</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="127"/>
<location filename="../settingsdialog.cpp" line="129"/>
<source>Mouse wheel behavior</source>
<translation>Поведінка колеса миші</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="128"/>
<location filename="../settingsdialog.cpp" line="130"/>
<source>Default window size</source>
<translation>Розмір вікна за замовчуванням</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="129"/>
<location filename="../settingsdialog.cpp" line="131"/>
<source>HiDPI scale factor rounding policy</source>
<translation>Політика округлення коефіцієнта HiDPI</translation>
</message>
@ -864,7 +874,7 @@
<context>
<name>ShortcutEdit</name>
<message>
<location filename="../shortcutedit.cpp" line="109"/>
<location filename="../shortcutedit.cpp" line="104"/>
<source>No shortcuts</source>
<translation type="unfinished"></translation>
</message>
@ -872,7 +882,7 @@
<context>
<name>ShortcutEditor</name>
<message>
<location filename="../shortcutedit.cpp" line="75"/>
<location filename="../shortcutedit.cpp" line="70"/>
<source>Shortcut #%1</source>
<translation type="unfinished"></translation>
</message>

View File

@ -178,7 +178,7 @@
<context>
<name>GraphicsScene</name>
<message>
<location filename="../mainwindow.cpp" line="276"/>
<location filename="../mainwindow.cpp" line="292"/>
<location filename="../graphicsscene.cpp" line="100"/>
<source>Drag image here</source>
<translation></translation>
@ -213,189 +213,194 @@
<context>
<name>MainWindow</name>
<message>
<location filename="../mainwindow.cpp" line="181"/>
<location filename="../mainwindow.cpp" line="545"/>
<location filename="../mainwindow.cpp" line="190"/>
<location filename="../mainwindow.cpp" line="561"/>
<source>File url list is empty</source>
<translation> URL </translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="445"/>
<location filename="../mainwindow.cpp" line="461"/>
<source>&amp;Copy</source>
<translation>(&amp;C)</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="553"/>
<location filename="../mainwindow.cpp" line="569"/>
<source>Image data is invalid</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="560"/>
<location filename="../mainwindow.cpp" line="576"/>
<source>Not supported mimedata: %1</source>
<translation> MimeData %1</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="759"/>
<location filename="../mainwindow.cpp" line="783"/>
<source>Image From Clipboard</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="777"/>
<location filename="../mainwindow.cpp" line="801"/>
<source>Are you sure you want to move &quot;%1&quot; to recycle bin?</source>
<translation>%1</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="781"/>
<location filename="../mainwindow.cpp" line="805"/>
<source>Failed to move file to trash</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="782"/>
<location filename="../mainwindow.cpp" line="806"/>
<source>Move to trash failed, it might caused by file permission issue, file system limitation, or platform limitation.</source>
<translation></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="114"/>
<location filename="../actionmanager.cpp" line="106"/>
<source>Copy P&amp;ixmap</source>
<translation>(&amp;I)</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="115"/>
<location filename="../actionmanager.cpp" line="107"/>
<source>Copy &amp;File Path</source>
<translation>(&amp;F)</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="133"/>
<location filename="../actionmanager.cpp" line="125"/>
<source>Properties</source>
<translation></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="118"/>
<location filename="../actionmanager.cpp" line="110"/>
<location filename="../aboutdialog.cpp" line="41"/>
<source>Stay on top</source>
<translation></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="119"/>
<location filename="../actionmanager.cpp" line="111"/>
<location filename="../aboutdialog.cpp" line="44"/>
<source>Protected mode</source>
<translation></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="120"/>
<location filename="../actionmanager.cpp" line="112"/>
<location filename="../aboutdialog.cpp" line="47"/>
<source>Keep transformation</source>
<comment>The &apos;transformation&apos; means the flip/rotation status that currently applied to the image view</comment>
<translation></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="99"/>
<location filename="../actionmanager.cpp" line="90"/>
<source>Zoom in</source>
<translation></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="100"/>
<location filename="../actionmanager.cpp" line="91"/>
<source>Zoom out</source>
<translation></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="108"/>
<location filename="../actionmanager.cpp" line="99"/>
<source>Pause/Resume Animation</source>
<translation>/</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="109"/>
<location filename="../actionmanager.cpp" line="100"/>
<source>Animation Go to Next Frame</source>
<translation></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="111"/>
<location filename="../actionmanager.cpp" line="102"/>
<source>Flip &amp;Horizontally</source>
<translation>(&amp;H)</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="112"/>
<location filename="../actionmanager.cpp" line="103"/>
<source>Fit to view</source>
<translation></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="113"/>
<location filename="../actionmanager.cpp" line="104"/>
<source>Fit to width</source>
<translation></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="116"/>
<location filename="../actionmanager.cpp" line="105"/>
<source>Fit long image</source>
<translation></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="108"/>
<source>&amp;Paste</source>
<translation>(&amp;P)</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="101"/>
<location filename="../actionmanager.cpp" line="92"/>
<source>Toggle Checkerboard</source>
<translation></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="95"/>
<location filename="../actionmanager.cpp" line="86"/>
<source>&amp;Open...</source>
<translation>(&amp;O)...</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="97"/>
<location filename="../actionmanager.cpp" line="88"/>
<source>Actual size</source>
<translation></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="98"/>
<location filename="../actionmanager.cpp" line="89"/>
<source>Toggle maximize</source>
<translation></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="102"/>
<location filename="../actionmanager.cpp" line="93"/>
<source>Rotate right</source>
<translation></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="103"/>
<location filename="../actionmanager.cpp" line="94"/>
<source>Rotate left</source>
<translation></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="105"/>
<location filename="../actionmanager.cpp" line="96"/>
<source>Previous image</source>
<translation></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="106"/>
<location filename="../actionmanager.cpp" line="97"/>
<source>Next image</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="776"/>
<location filename="../actionmanager.cpp" line="117"/>
<location filename="../mainwindow.cpp" line="800"/>
<location filename="../actionmanager.cpp" line="109"/>
<source>Move to Trash</source>
<translation></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="121"/>
<location filename="../actionmanager.cpp" line="113"/>
<source>Configure...</source>
<translation>...</translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="122"/>
<location filename="../actionmanager.cpp" line="114"/>
<source>Help</source>
<translation></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="125"/>
<location filename="../actionmanager.cpp" line="117"/>
<source>Show in File Explorer</source>
<comment>File Explorer is the name of explorer.exe under Windows</comment>
<translation></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="131"/>
<location filename="../actionmanager.cpp" line="123"/>
<source>Show in directory</source>
<translation></translation>
</message>
<message>
<location filename="../actionmanager.cpp" line="134"/>
<location filename="../actionmanager.cpp" line="126"/>
<source>Quit</source>
<translation>退</translation>
</message>
@ -726,141 +731,146 @@
<context>
<name>SettingsDialog</name>
<message>
<location filename="../settingsdialog.cpp" line="31"/>
<location filename="../settingsdialog.cpp" line="32"/>
<source>Settings</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="39"/>
<location filename="../settingsdialog.cpp" line="40"/>
<source>Options</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="51"/>
<location filename="../settingsdialog.cpp" line="52"/>
<source>Shortcuts</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="61"/>
<location filename="../settingsdialog.cpp" line="62"/>
<source>Editing shortcuts for action &quot;%1&quot;:</source>
<translation>%1</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="70"/>
<location filename="../settingsdialog.cpp" line="71"/>
<source>Failed to set shortcuts</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="71"/>
<location filename="../settingsdialog.cpp" line="72"/>
<source>Please check if shortcuts are duplicated with existing shortcuts.</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="78"/>
<location filename="../settingsdialog.cpp" line="79"/>
<source>Do nothing</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="79"/>
<location filename="../settingsdialog.cpp" line="80"/>
<source>Close the window</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="80"/>
<location filename="../settingsdialog.cpp" line="81"/>
<source>Toggle maximize</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="81"/>
<location filename="../settingsdialog.cpp" line="82"/>
<source>Toggle fullscreen</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="85"/>
<location filename="../settingsdialog.cpp" line="86"/>
<source>Zoom in and out</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="86"/>
<location filename="../settingsdialog.cpp" line="87"/>
<source>View next or previous item</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="90"/>
<location filename="../settingsdialog.cpp" line="91"/>
<source>Auto size</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="91"/>
<location filename="../settingsdialog.cpp" line="92"/>
<source>Maximized</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="92"/>
<location filename="../settingsdialog.cpp" line="93"/>
<source>Windowed</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="96"/>
<location filename="../settingsdialog.cpp" line="97"/>
<source>Round (Integer scaling)</source>
<comment>This option means round up for .5 and above</comment>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="97"/>
<location filename="../settingsdialog.cpp" line="98"/>
<source>Ceil (Integer scaling)</source>
<comment>This option means always round up</comment>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="98"/>
<location filename="../settingsdialog.cpp" line="99"/>
<source>Floor (Integer scaling)</source>
<comment>This option means always round down</comment>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="99"/>
<location filename="../settingsdialog.cpp" line="100"/>
<source>Follow system (Fractional scaling)</source>
<comment>This option means don&apos;t round</comment>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="122"/>
<location filename="../settingsdialog.cpp" line="123"/>
<source>Stay on top when start-up</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="123"/>
<location filename="../settingsdialog.cpp" line="124"/>
<source>Use built-in close window animation</source>
<translation>使</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="124"/>
<location filename="../settingsdialog.cpp" line="125"/>
<source>Use light-color checkerboard</source>
<translation>使</translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="125"/>
<location filename="../settingsdialog.cpp" line="126"/>
<source>Loop the loaded gallery</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="126"/>
<location filename="../settingsdialog.cpp" line="127"/>
<source>Auto long image mode</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="128"/>
<source>Double-click behavior</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="127"/>
<location filename="../settingsdialog.cpp" line="129"/>
<source>Mouse wheel behavior</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="128"/>
<location filename="../settingsdialog.cpp" line="130"/>
<source>Default window size</source>
<translation></translation>
</message>
<message>
<location filename="../settingsdialog.cpp" line="129"/>
<location filename="../settingsdialog.cpp" line="131"/>
<source>HiDPI scale factor rounding policy</source>
<translation>HiDPI </translation>
</message>
@ -868,7 +878,7 @@
<context>
<name>ShortcutEdit</name>
<message>
<location filename="../shortcutedit.cpp" line="109"/>
<location filename="../shortcutedit.cpp" line="104"/>
<source>No shortcuts</source>
<translation></translation>
</message>
@ -876,7 +886,7 @@
<context>
<name>ShortcutEditor</name>
<message>
<location filename="../shortcutedit.cpp" line="75"/>
<location filename="../shortcutedit.cpp" line="70"/>
<source>Shortcut #%1</source>
<translation> %1</translation>
</message>

View File

@ -1,17 +1,18 @@
IDI_ICON1 ICON DISCARDABLE "icons/app-icon.ico"
1 VERSIONINFO
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904E4"
BEGIN
VALUE "FileDescription", "Pineapple Pictures - Image Viewer"
VALUE "LegalCopyright", "MIT/Expat License - Copyright (C) 2024 Gary Wang"
VALUE "ProductName", "Pineapple Pictures"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END
IDI_ICON1 ICON DISCARDABLE "@CMAKE_CURRENT_SOURCE_DIR@/assets/icons/app-icon.ico"
1 VERSIONINFO
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904E4"
BEGIN
VALUE "FileDescription", "Pineapple Pictures - Image Viewer"
VALUE "LegalCopyright", "MIT/Expat License - Copyright (C) 2024 Gary Wang"
VALUE "ProductName", "Pineapple Pictures"
VALUE "ProductVersion", "@PROJECT_VERSION@"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x409, 1200
END
END

View File

@ -1,136 +1,136 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string>
<key>CFBundleGetInfoString</key>
<string>${MACOSX_BUNDLE_INFO_STRING}</string>
<key>CFBundleIconFile</key>
<string>${MACOSX_BUNDLE_ICON_FILE}</string>
<key>CFBundleIdentifier</key>
<string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleLongVersionString</key>
<string>${MACOSX_BUNDLE_LONG_VERSION_STRING}</string>
<key>CFBundleName</key>
<string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>${MACOSX_BUNDLE_BUNDLE_VERSION}</string>
<key>CSResourcesFileMapped</key>
<true/>
<key>NSHumanReadableCopyright</key>
<string>${MACOSX_BUNDLE_COPYRIGHT}</string>
<!-- FIXME: this list can't be automatically generated by Qt's CMake API, don't know why. -->
<key>CFBundleLocalizations</key>
<array>
<string>en</string>
<string>ca</string>
<string>de</string>
<string>es</string>
<string>fr</string>
<string>id</string>
<string>it</string>
<string>ja</string>
<string>ko</string>
<string>nb_NO</string>
<string>nl</string>
<string>pa_PK</string>
<string>ru</string>
<string>si</string>
<string>ta</string>
<string>tr</string>
<string>uk</string>
<string>zh_CN</string>
</array>
<key>CFBundleDocumentTypes</key>
<array>
<!-- JPEG -->
<dict>
<key>CFBundleTypeName</key>
<string>JPEG Image</string>
<key>CFBundleTypeExtensions</key>
<array>
<string>jpg</string>
<string>jpeg</string>
<string>jfif</string>
</array>
<key>CFBundleTypeMIMETypes</key>
<array>
<string>image/jpeg</string>
</array>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
</dict>
<!-- PNG -->
<dict>
<key>CFBundleTypeName</key>
<string>PNG Image</string>
<key>CFBundleTypeExtensions</key>
<array>
<string>png</string>
</array>
<key>CFBundleTypeMIMETypes</key>
<array>
<string>image/png</string>
</array>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
</dict>
<!-- WebP -->
<dict>
<key>CFBundleTypeName</key>
<string>WebP Image</string>
<key>CFBundleTypeExtensions</key>
<array>
<string>webp</string>
</array>
<key>CFBundleTypeMIMETypes</key>
<array>
<string>image/webp</string>
</array>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
</dict>
<!-- GIF -->
<dict>
<key>CFBundleTypeName</key>
<string>GIF Image</string>
<key>CFBundleTypeExtensions</key>
<array>
<string>gif</string>
</array>
<key>CFBundleTypeMIMETypes</key>
<array>
<string>image/gif</string>
</array>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
</dict>
<!-- SVG -->
<dict>
<key>CFBundleTypeName</key>
<string>SVG Image</string>
<key>CFBundleTypeExtensions</key>
<array>
<string>svg</string>
</array>
<key>CFBundleTypeMIMETypes</key>
<array>
<string>image/svg+xml</string>
</array>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
</dict>
</array>
</dict>
</plist>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string>
<key>CFBundleGetInfoString</key>
<string>${MACOSX_BUNDLE_INFO_STRING}</string>
<key>CFBundleIconFile</key>
<string>${MACOSX_BUNDLE_ICON_FILE}</string>
<key>CFBundleIdentifier</key>
<string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleLongVersionString</key>
<string>${MACOSX_BUNDLE_LONG_VERSION_STRING}</string>
<key>CFBundleName</key>
<string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>${MACOSX_BUNDLE_BUNDLE_VERSION}</string>
<key>CSResourcesFileMapped</key>
<true/>
<key>NSHumanReadableCopyright</key>
<string>${MACOSX_BUNDLE_COPYRIGHT}</string>
<!-- FIXME: this list can't be automatically generated by Qt's CMake API, don't know why. -->
<key>CFBundleLocalizations</key>
<array>
<string>en</string>
<string>ca</string>
<string>de</string>
<string>es</string>
<string>fr</string>
<string>id</string>
<string>it</string>
<string>ja</string>
<string>ko</string>
<string>nb_NO</string>
<string>nl</string>
<string>pa_PK</string>
<string>ru</string>
<string>si</string>
<string>ta</string>
<string>tr</string>
<string>uk</string>
<string>zh_CN</string>
</array>
<key>CFBundleDocumentTypes</key>
<array>
<!-- JPEG -->
<dict>
<key>CFBundleTypeName</key>
<string>JPEG Image</string>
<key>CFBundleTypeExtensions</key>
<array>
<string>jpg</string>
<string>jpeg</string>
<string>jfif</string>
</array>
<key>CFBundleTypeMIMETypes</key>
<array>
<string>image/jpeg</string>
</array>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
</dict>
<!-- PNG -->
<dict>
<key>CFBundleTypeName</key>
<string>PNG Image</string>
<key>CFBundleTypeExtensions</key>
<array>
<string>png</string>
</array>
<key>CFBundleTypeMIMETypes</key>
<array>
<string>image/png</string>
</array>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
</dict>
<!-- WebP -->
<dict>
<key>CFBundleTypeName</key>
<string>WebP Image</string>
<key>CFBundleTypeExtensions</key>
<array>
<string>webp</string>
</array>
<key>CFBundleTypeMIMETypes</key>
<array>
<string>image/webp</string>
</array>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
</dict>
<!-- GIF -->
<dict>
<key>CFBundleTypeName</key>
<string>GIF Image</string>
<key>CFBundleTypeExtensions</key>
<array>
<string>gif</string>
</array>
<key>CFBundleTypeMIMETypes</key>
<array>
<string>image/gif</string>
</array>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
</dict>
<!-- SVG -->
<dict>
<key>CFBundleTypeName</key>
<string>SVG Image</string>
<key>CFBundleTypeExtensions</key>
<array>
<string>svg</string>
</array>
<key>CFBundleTypeMIMETypes</key>
<array>
<string>image/svg+xml</string>
</array>
<key>CFBundleTypeRole</key>
<string>Viewer</string>
</dict>
</array>
</dict>
</plist>

View File

@ -80,6 +80,25 @@
</screenshot>
</screenshots>
<releases>
<release type="stable" version="1.1.1" date="2025-08-02T00:00:00Z">
<description>
<p>This release adds the following feature:</p>
<ul>
<li>Click dock icon should show window when it's hidden on macOS</li>
</ul>
<p>This release fixes the following bug:</p>
<ul>
<li>Ensure "Fit by Width" position the view to the beginning of the image</li>
</ul>
<p>This release includes the following changes:</p>
<ul>
<li>Update translations</li>
<li>Update Exiv2 version for Windows binary build</li>
</ul>
<p>With contributions from:</p>
<p>Heimen Stoffels, VenusGirl, தமிழ்நேரம்</p>
</description>
</release>
<release type="stable" version="1.1.0" date="2025-07-06T00:00:00Z">
<description>
<p>This release adds the following features:</p>

View File

@ -1,101 +1,101 @@
# SPDX-FileCopyrightText: 2025 Gary Wang <git@blumia.net>
#
# SPDX-License-Identifier: MIT
QT += core widgets gui svg svgwidgets
TARGET = ppic
TEMPLATE = app
DEFINES += PPIC_VERSION_STRING=\\\"x.y.z\\\"
win32 {
DEFINES += FLAG_PORTABLE_MODE_SUPPORT=1
}
# The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
CONFIG += c++17 lrelease embed_translations
SOURCES += \
app/aboutdialog.cpp \
app/main.cpp \
app/framelesswindow.cpp \
app/mainwindow.cpp \
app/graphicsview.cpp \
app/bottombuttongroup.cpp \
app/graphicsscene.cpp \
app/navigatorview.cpp \
app/opacityhelper.cpp \
app/toolbutton.cpp \
app/settings.cpp \
app/settingsdialog.cpp \
app/metadatamodel.cpp \
app/metadatadialog.cpp \
app/exiv2wrapper.cpp \
app/actionmanager.cpp \
app/playlistmanager.cpp \
app/shortcutedit.cpp \
app/fileopeneventhandler.cpp
HEADERS += \
app/aboutdialog.h \
app/framelesswindow.h \
app/mainwindow.h \
app/graphicsview.h \
app/bottombuttongroup.h \
app/graphicsscene.h \
app/navigatorview.h \
app/opacityhelper.h \
app/toolbutton.h \
app/settings.h \
app/settingsdialog.h \
app/metadatamodel.h \
app/metadatadialog.h \
app/exiv2wrapper.h \
app/actionmanager.h \
app/playlistmanager.h \
app/shortcutedit.h \
app/fileopeneventhandler.h
TRANSLATIONS = \
app/translations/PineapplePictures_en.ts \
app/translations/PineapplePictures_zh_CN.ts \
app/translations/PineapplePictures_de.ts \
app/translations/PineapplePictures_es.ts \
app/translations/PineapplePictures_fr.ts \
app/translations/PineapplePictures_nb_NO.ts \
app/translations/PineapplePictures_nl.ts \
app/translations/PineapplePictures_ru.ts \
app/translations/PineapplePictures_si.ts \
app/translations/PineapplePictures_id.ts
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
RESOURCES += \
assets/resources.qrc
# Generate from svg:
# magick convert -density 512x512 -background none app-icon.svg -define icon:auto-resize app-icon.ico
RC_ICONS = assets/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) 2024 Gary Wang
# MSVC only, since QMake doesn't have a CMAKE_CXX_STANDARD_LIBRARIES or cpp_winlibs similar thing
win32-msvc* {
LIBS += -luser32
}
# SPDX-FileCopyrightText: 2025 Gary Wang <git@blumia.net>
#
# SPDX-License-Identifier: MIT
QT += core widgets gui svg svgwidgets
TARGET = ppic
TEMPLATE = app
DEFINES += PPIC_VERSION_STRING=\\\"x.y.z\\\"
win32 {
DEFINES += FLAG_PORTABLE_MODE_SUPPORT=1
}
# The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
CONFIG += c++17 lrelease embed_translations
SOURCES += \
app/aboutdialog.cpp \
app/main.cpp \
app/framelesswindow.cpp \
app/mainwindow.cpp \
app/graphicsview.cpp \
app/bottombuttongroup.cpp \
app/graphicsscene.cpp \
app/navigatorview.cpp \
app/opacityhelper.cpp \
app/toolbutton.cpp \
app/settings.cpp \
app/settingsdialog.cpp \
app/metadatamodel.cpp \
app/metadatadialog.cpp \
app/exiv2wrapper.cpp \
app/actionmanager.cpp \
app/playlistmanager.cpp \
app/shortcutedit.cpp \
app/fileopeneventhandler.cpp
HEADERS += \
app/aboutdialog.h \
app/framelesswindow.h \
app/mainwindow.h \
app/graphicsview.h \
app/bottombuttongroup.h \
app/graphicsscene.h \
app/navigatorview.h \
app/opacityhelper.h \
app/toolbutton.h \
app/settings.h \
app/settingsdialog.h \
app/metadatamodel.h \
app/metadatadialog.h \
app/exiv2wrapper.h \
app/actionmanager.h \
app/playlistmanager.h \
app/shortcutedit.h \
app/fileopeneventhandler.h
TRANSLATIONS = \
app/translations/PineapplePictures_en.ts \
app/translations/PineapplePictures_zh_CN.ts \
app/translations/PineapplePictures_de.ts \
app/translations/PineapplePictures_es.ts \
app/translations/PineapplePictures_fr.ts \
app/translations/PineapplePictures_nb_NO.ts \
app/translations/PineapplePictures_nl.ts \
app/translations/PineapplePictures_ru.ts \
app/translations/PineapplePictures_si.ts \
app/translations/PineapplePictures_id.ts
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
RESOURCES += \
assets/resources.qrc
# Generate from svg:
# magick convert -density 512x512 -background none app-icon.svg -define icon:auto-resize app-icon.ico
RC_ICONS = assets/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) 2024 Gary Wang
# MSVC only, since QMake doesn't have a CMAKE_CXX_STANDARD_LIBRARIES or cpp_winlibs similar thing
win32-msvc* {
LIBS += -luser32
}