Verified Commit c3b9e549 authored by Antonio Prcela's avatar Antonio Prcela 🏞
Browse files

Show estimated file size in the resize image dialog

Automatically calculate the expected file size for the image with
the new size. Calculation is based on the assumption that the
image format won't be changed and for lossy images it uses
the value set in 'Lossy image save quality'.

BUG: 433740
parent cce25ca4
......@@ -231,6 +231,7 @@ void ImageOpsContextManagerItem::resizeImage()
dialog->setAttribute(Qt::WA_DeleteOnClose);
dialog->setModal(true);
dialog->setOriginalSize(doc->size());
dialog->setCurrentImageUrl(doc->url());
connect(dialog, &QDialog::accepted, this, [this, dialog]() {
applyImageOperation(new ResizeImageOperation(dialog->size()));
});
......
......@@ -22,14 +22,19 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA
#include "resizeimagedialog.h"
// Qt
#include <QBuffer>
#include <QDialogButtonBox>
#include <QFileInfo>
#include <QPushButton>
#include <QTimer>
// KF
#include <KFormat>
#include <KGuiItem>
#include <KLocalizedString>
// Local
#include <lib/gwenviewconfig.h>
#include <ui_resizeimagewidget.h>
namespace Gwenview
......@@ -67,11 +72,23 @@ ResizeImageDialog::ResizeImageDialog(QWidget *parent)
setWindowTitle(content->windowTitle());
d->mWidthSpinBox->setFocus();
d->mEstimatedSizeLabel->setToolTip(i18nc("@action",
"Assuming that the image format won't be changed and\nfor lossy images using the "
"value set in 'Lossy image save quality'."));
connect(d->mWidthSpinBox, QOverload<int>::of(&QSpinBox::valueChanged), this, &ResizeImageDialog::slotWidthChanged);
connect(d->mHeightSpinBox, QOverload<int>::of(&QSpinBox::valueChanged), this, &ResizeImageDialog::slotHeightChanged);
connect(d->mWidthPercentSpinBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &ResizeImageDialog::slotWidthPercentChanged);
connect(d->mHeightPercentSpinBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &ResizeImageDialog::slotHeightPercentChanged);
connect(d->mWidthSpinBox, &QSpinBox::editingFinished, this, &ResizeImageDialog::slotCalculateImageSize);
connect(d->mHeightSpinBox, &QSpinBox::editingFinished, this, &ResizeImageDialog::slotCalculateImageSize);
connect(d->mWidthPercentSpinBox, &QSpinBox::editingFinished, this, &ResizeImageDialog::slotCalculateImageSize);
connect(d->mHeightPercentSpinBox, &QSpinBox::editingFinished, this, &ResizeImageDialog::slotCalculateImageSize);
connect(d->mKeepAspectCheckBox, &QCheckBox::toggled, this, &ResizeImageDialog::slotKeepAspectChanged);
QTimer *timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, QOverload<>::of(&ResizeImageDialog::slotCalculateImageSize));
timer->start(2000);
}
ResizeImageDialog::~ResizeImageDialog()
......@@ -88,6 +105,16 @@ void ResizeImageDialog::setOriginalSize(const QSize &size)
d->mHeightSpinBox->setValue(size.height());
}
void ResizeImageDialog::setCurrentImageUrl(QUrl imageUrl)
{
mCurrentImageUrl = imageUrl;
// mCurrentSize->setText has to be set after the mCurrentImageUrl has been set, otherwise it's -1
QFileInfo fileInfo(mCurrentImageUrl.toLocalFile());
d->mCurrentSize->setText(KFormat().formatByteSize(fileInfo.size()));
mValueChanged = false;
}
QSize ResizeImageDialog::size() const
{
return QSize(d->mWidthSpinBox->value(), d->mHeightSpinBox->value());
......@@ -95,6 +122,7 @@ QSize ResizeImageDialog::size() const
void ResizeImageDialog::slotWidthChanged(int width)
{
mValueChanged = true;
// Update width percentage to match width, only if this was a manual adjustment
if (!d->mUpdateFromSizeOrPercentage && !d->mUpdateFromRatio) {
d->mUpdateFromSizeOrPercentage = true;
......@@ -114,6 +142,7 @@ void ResizeImageDialog::slotWidthChanged(int width)
void ResizeImageDialog::slotHeightChanged(int height)
{
mValueChanged = true;
// Update height percentage to match height, only if this was a manual adjustment
if (!d->mUpdateFromSizeOrPercentage && !d->mUpdateFromRatio) {
d->mUpdateFromSizeOrPercentage = true;
......@@ -133,6 +162,7 @@ void ResizeImageDialog::slotHeightChanged(int height)
void ResizeImageDialog::slotWidthPercentChanged(double widthPercent)
{
mValueChanged = true;
// Update width to match width percentage, only if this was a manual adjustment
if (!d->mUpdateFromSizeOrPercentage && !d->mUpdateFromRatio) {
d->mUpdateFromSizeOrPercentage = true;
......@@ -152,6 +182,7 @@ void ResizeImageDialog::slotWidthPercentChanged(double widthPercent)
void ResizeImageDialog::slotHeightPercentChanged(double heightPercent)
{
mValueChanged = true;
// Update height to match height percentage, only if this was a manual adjustment
if (!d->mUpdateFromSizeOrPercentage && !d->mUpdateFromRatio) {
d->mUpdateFromSizeOrPercentage = true;
......@@ -179,4 +210,49 @@ void ResizeImageDialog::slotKeepAspectChanged(bool value)
}
}
void ResizeImageDialog::slotCalculateImageSize()
{
qint64 size = calculateEstimatedImageSize();
if (size == -1) {
return;
} else if (size == -2) {
d->mEstimatedSize->setText(i18n("error"));
} else {
d->mEstimatedSize->setText(KFormat().formatByteSize(size));
}
}
qint64 ResizeImageDialog::calculateEstimatedImageSize()
{
if (mValueChanged) {
QImage image(mCurrentImageUrl.toLocalFile());
if (image.isNull()) {
return -2;
}
QByteArray ba;
QBuffer buffer(&ba);
QFileInfo fileInfo(mCurrentImageUrl.toLocalFile());
QString suffix = fileInfo.suffix();
buffer.open(QIODevice::ReadWrite);
image = image.scaled(size(), Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
if (QString::compare(suffix, "jpg", Qt::CaseInsensitive) == 0 || QString::compare(suffix, "jpeg", Qt::CaseInsensitive) == 0
|| QString::compare(suffix, "avif", Qt::CaseInsensitive) == 0 || QString::compare(suffix, "heic", Qt::CaseInsensitive) == 0
|| QString::compare(suffix, "webp", Qt::CaseInsensitive) == 0) {
image.save(&buffer, suffix.toStdString().c_str(), GwenviewConfig::jPEGQuality());
} else {
image.save(&buffer, suffix.toStdString().c_str());
}
qint64 size = buffer.size();
buffer.close();
mValueChanged = false;
return size;
}
return -1;
}
} // namespace
......@@ -25,6 +25,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Cambridge, MA 02110-1301, USA
// Qt
#include <QDialog>
#include <QUrl>
// KF
......@@ -41,6 +42,7 @@ public:
~ResizeImageDialog() override;
void setOriginalSize(const QSize &);
void setCurrentImageUrl(QUrl);
QSize size() const;
private Q_SLOTS:
......@@ -49,9 +51,14 @@ private Q_SLOTS:
void slotWidthPercentChanged(double);
void slotHeightPercentChanged(double);
void slotKeepAspectChanged(bool);
void slotCalculateImageSize();
qint64 calculateEstimatedImageSize();
private:
ResizeImageDialogPrivate *const d;
QUrl mCurrentImageUrl;
bool mValueChanged = false;
};
} // namespace
......
......@@ -6,44 +6,51 @@
<rect>
<x>0</x>
<y>0</y>
<width>302</width>
<height>158</height>
<width>311</width>
<height>212</height>
</rect>
</property>
<property name="windowTitle">
<string>Resize Image</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="1" column="0">
<widget class="QLabel" name="label">
<item row="7" column="0" colspan="2">
<widget class="QLabel" name="mEstimatedSizeLabel">
<property name="text">
<string>Current size:</string>
<string notr="true">Estimated new file size:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QSpinBox" name="mWidthSpinBox">
<item row="0" column="1">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Width</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="suffix">
<string> px</string>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>99999</number>
</widget>
</item>
<item row="0" column="3">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Height</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QLabel" name="label_4">
<item row="2" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string notr="true"></string>
<string>New size:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>mWidthSpinBox</cstring>
</property>
</widget>
</item>
......@@ -73,18 +80,24 @@
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QLabel" name="mOriginalHeightLabel">
<property name="text">
<string/>
<item row="2" column="3">
<widget class="QSpinBox" name="mHeightSpinBox">
<property name="suffix">
<string> px</string>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>99999</number>
</property>
</widget>
</item>
<item row="2" column="3">
<widget class="QSpinBox" name="mHeightSpinBox">
<item row="2" column="1">
<widget class="QSpinBox" name="mWidthSpinBox">
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="suffix">
<string> px</string>
</property>
......@@ -96,6 +109,16 @@
</property>
</widget>
</item>
<item row="6" column="0" colspan="2">
<widget class="QLabel" name="mCurrentSizeLabel">
<property name="text">
<string notr="true">Current file size:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLabel" name="mOriginalWidthLabel">
<property name="text">
......@@ -109,16 +132,57 @@
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_2">
<item row="3" column="2">
<widget class="QLabel" name="label_7">
<property name="text">
<string>New size:</string>
<string notr="true"></string>
</property>
</widget>
</item>
<item row="4" column="1" colspan="3">
<widget class="QCheckBox" name="mKeepAspectCheckBox">
<property name="text">
<string>Keep aspect ratio</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QLabel" name="label_4">
<property name="text">
<string notr="true"></string>
</property>
</widget>
</item>
<item row="1" column="3">
<widget class="QLabel" name="mOriginalHeightLabel">
<property name="text">
<string/>
</property>
<property name="textInteractionFlags">
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByMouse</set>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Current size:</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="buddy">
<cstring>mWidthSpinBox</cstring>
</widget>
</item>
<item row="7" column="3">
<widget class="QLabel" name="mEstimatedSize">
<property name="text">
<string notr="true"/>
</property>
<property name="alignment">
<set>Qt::AlignJustify|Qt::AlignVCenter</set>
</property>
</widget>
</item>
......@@ -141,39 +205,28 @@
</property>
</widget>
</item>
<item row="4" column="1" colspan="3">
<widget class="QCheckBox" name="mKeepAspectCheckBox">
<property name="text">
<string>Keep aspect ratio</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QLabel" name="label_7">
<item row="6" column="3">
<widget class="QLabel" name="mCurrentSize">
<property name="text">
<string notr="true"></string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Width</string>
<string notr="true"/>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
<set>Qt::AlignJustify|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item row="0" column="3">
<widget class="QLabel" name="label_5">
<property name="text">
<string>Height</string>
</property>
</widget>
<item row="5" column="0">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>0</width>
<height>18</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment