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,72 @@ RecentFilesModel* mRecentFilesModel; QPalette mPalettes[4]; QString mFullScreenPaletteName; + int configFileJPEGQualityValue; 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", "%")); + configFileJPEGQualityValue = GwenviewConfig::jPEGQuality(); + 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 +154,7 @@ ); } while (true); - *outUrl = dialog->selectedUrls().first(); + *outUrl = fileWidget->selectedUrls().first(); return true; } @@ -361,9 +406,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 +435,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,10 @@ 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()); + } 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;