diff --git a/app/generalconfigpage.ui b/app/generalconfigpage.ui
--- a/app/generalconfigpage.ui
+++ b/app/generalconfigpage.ui
@@ -26,7 +26,7 @@
-
-
+
Qt::Vertical
@@ -123,27 +123,63 @@
-
+
+
+ JPEG save quality:
+
+
+
+ -
+
+
+ 1
+
+
+ 100
+
+
+ %
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+ QSizePolicy::Fixed
+
+
+
+ 20
+ 20
+
+
+
+
+ -
Thumbnail actions:
- -
+
-
All buttons
- -
+
-
Show selection button only
- -
+
-
None
diff --git a/app/gvcore.cpp b/app/gvcore.cpp
--- a/app/gvcore.cpp
+++ b/app/gvcore.cpp
@@ -25,13 +25,18 @@
// Qt
#include
#include
+#include
#include
+#include
#include
#include
+#include
+#include
// KDE
-#include
#include
+#include
+#include
#include
#include
@@ -65,32 +70,71 @@
RecentFilesModel* mRecentFilesModel;
QPalette mPalettes[4];
QString mFullScreenPaletteName;
+ const int configFileJPEGQualityValue = GwenviewConfig::jPEGQuality();
bool showSaveAsDialog(const QUrl &url, QUrl* outUrl, QByteArray* format)
{
- DialogGuard dialog(mMainWindow);
- dialog->setAcceptMode(QFileDialog::AcceptSave);
+ // Build the JPEG quality chooser custom widget
+ QWidget* JPEGQualityChooserWidget = new QWidget;
+ JPEGQualityChooserWidget->setVisible(false); // shown only for JPEGs
+
+ QLabel* JPEGQualityChooserLabel = new QLabel;
+ JPEGQualityChooserLabel->setText(i18n("JPEG quality:"));
+ JPEGQualityChooserLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+
+ QSpinBox* JPEGQualityChooserSpinBox = new QSpinBox;
+ JPEGQualityChooserSpinBox->setMinimum(1);
+ JPEGQualityChooserSpinBox->setMaximum(100);
+ JPEGQualityChooserSpinBox->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+ JPEGQualityChooserSpinBox->setSuffix(i18nc("Spinbox suffix; percentage 1 - 100", "%"));
+ JPEGQualityChooserSpinBox->setValue(configFileJPEGQualityValue);
+
+ // Temporarily change JPEG quality value
+ QObject::connect(JPEGQualityChooserSpinBox, QOverload::of(&QSpinBox::valueChanged),
+ JPEGQualityChooserSpinBox, [=](int value) {
+ GwenviewConfig::setJPEGQuality(value);
+ });
+
+ QSpacerItem* horizontalSpacer = new QSpacerItem(1, 1, QSizePolicy::Expanding, QSizePolicy::Fixed);
+
+ QHBoxLayout* JPEGQualityChooserLayout = new QHBoxLayout(JPEGQualityChooserWidget);
+ JPEGQualityChooserLayout->setContentsMargins(0,0,0,0);
+ JPEGQualityChooserLayout->addWidget(JPEGQualityChooserLabel);
+ JPEGQualityChooserLayout->addWidget(JPEGQualityChooserSpinBox);
+ JPEGQualityChooserLayout->addItem(horizontalSpacer);
+
+ // Set up the dialog
+ DialogGuard dialog(mMainWindow);
+ KFileWidget* fileWidget = dialog->fileWidget();
+ dialog->setCustomWidget(JPEGQualityChooserWidget);
+ dialog->setOperationMode(KFileWidget::Saving);
dialog->setWindowTitle(i18nc("@title:window", "Save Image"));
// Temporary workaround for selectUrl() not setting the
// initial directory to url (removed in D4193)
- dialog->setDirectoryUrl(url.adjusted(QUrl::RemoveFilename));
- dialog->selectUrl(url);
+ dialog->setUrl(url.adjusted(QUrl::RemoveFilename));
+ fileWidget->setSelectedUrl(url);
QStringList supportedMimetypes;
for (const QByteArray &mimeName : QImageWriter::supportedMimeTypes()) {
supportedMimetypes.append(QString::fromLocal8Bit(mimeName));
}
- dialog->setMimeTypeFilters(supportedMimetypes);
- dialog->selectMimeTypeFilter(MimeTypeUtils::urlMimeType(url));
+ fileWidget->setMimeFilter(supportedMimetypes,
+ MimeTypeUtils::urlMimeType(url));
+
+ // Only show the JPEG quality chooser when saving a JPEG image
+ QObject::connect(fileWidget, &KFileWidget::filterChanged,
+ JPEGQualityChooserWidget, [=](const QString &filter) {
+ JPEGQualityChooserWidget->setVisible(filter.contains(QStringLiteral("jpeg")));
+ });
// Show dialog
do {
if (!dialog->exec()) {
return false;
}
- QList files = dialog->selectedUrls();
+ QList files = fileWidget->selectedUrls();
if (files.isEmpty()) {
return false;
}
@@ -109,7 +153,7 @@
);
} while (true);
- *outUrl = dialog->selectedUrls().first();
+ *outUrl = fileWidget->selectedUrls().first();
return true;
}
@@ -361,9 +405,16 @@
return;
}
+ if (format == "jpg") {
+ // Gwenview code assumes JPEG images have "jpeg" format, so if the
+ // dialog returned the format "jpg", use "jpeg" instead
+ // This does not affect the actual filename extension
+ format = "jpeg";
+ }
+
// Start save
Document::Ptr doc = DocumentFactory::instance()->load(url);
- KJob* job = doc->save(saveAsUrl, format.data());
+ KJob* job = doc->save(saveAsUrl, format);
if (!job) {
const QString name = saveAsUrl.fileName().isEmpty() ? saveAsUrl.toDisplayString() : saveAsUrl.fileName();
const QString msg = xi18nc("@info", "Saving %1 failed:%2",
@@ -383,6 +434,12 @@
void GvCore::slotSaveResult(KJob* _job)
{
+ // Regardless of job result, reset JPEG config value if it was changed by
+ // the Save As dialog
+ if (GwenviewConfig::jPEGQuality() != d->configFileJPEGQualityValue) {
+ GwenviewConfig::setJPEGQuality(d->configFileJPEGQualityValue);
+ }
+
SaveJob* job = static_cast(_job);
QUrl oldUrl = job->oldUrl();
QUrl newUrl = job->newUrl();
diff --git a/lib/document/documentloadedimpl.cpp b/lib/document/documentloadedimpl.cpp
--- a/lib/document/documentloadedimpl.cpp
+++ b/lib/document/documentloadedimpl.cpp
@@ -33,6 +33,7 @@
// Local
#include "documentjob.h"
+#include "gwenviewconfig.h"
#include "imageutils.h"
#include "savejob.h"
@@ -81,6 +82,11 @@
bool DocumentLoadedImpl::saveInternal(QIODevice* device, const QByteArray& format)
{
QImageWriter writer(device, format);
+ // If we're saving a non-JPEG image as a JPEG, respect the quality setting
+ if (format == QStringLiteral("jpeg")) {
+ writer.setQuality(GwenviewConfig::jPEGQuality());
+ }
+ writer.setQuality(GwenviewConfig::jPEGQuality());
bool ok = writer.write(document()->image());
if (ok) {
setDocumentFormat(format);
diff --git a/lib/gwenviewconfig.kcfg b/lib/gwenviewconfig.kcfg
--- a/lib/gwenviewconfig.kcfg
+++ b/lib/gwenviewconfig.kcfg
@@ -57,6 +57,10 @@
false
+
+ 90
+
+
diff --git a/lib/jpegcontent.cpp b/lib/jpegcontent.cpp
--- a/lib/jpegcontent.cpp
+++ b/lib/jpegcontent.cpp
@@ -185,6 +185,7 @@
{
QBuffer buffer;
QImageWriter writer(&buffer, "jpeg");
+ writer.setQuality(GwenviewConfig::jPEGQuality());
if (!writer.write(mImage)) {
mErrorString = writer.errorString();
return false;