Improve support for saving QImage to QSaveFile

When saving to a QIODevice, QImage and QImageWriter will automatically
deduct the file format from the filename if it determines that the
device is a QFile. That did not work for a QSaveFile device. Fix by
using the common ancestor, QFileDevice, in the implementation.

Fixes: QTBUG-89022
Pick-to: 6.2
Change-Id: Ie01d80df4f29ca0d4ff30bf7e1b77605293c070e
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
This commit is contained in:
Eirik Aavitsland 2021-07-13 17:14:11 +02:00
parent a7564e2657
commit f0510d5bd2
2 changed files with 60 additions and 5 deletions

View File

@ -153,7 +153,7 @@ static QImageIOHandler *createWriteHandlerHelper(QIODevice *device,
// if there's no format, see if \a device is a file, and if so, find // if there's no format, see if \a device is a file, and if so, find
// the file suffix and find support for that format among our plugins. // the file suffix and find support for that format among our plugins.
// this allows plugins to override our built-in handlers. // this allows plugins to override our built-in handlers.
if (QFile *file = qobject_cast<QFile *>(device)) { if (QFileDevice *file = qobject_cast<QFileDevice *>(device)) {
if (!(suffix = QFileInfo(file->fileName()).suffix().toLower().toLatin1()).isEmpty()) { if (!(suffix = QFileInfo(file->fileName()).suffix().toLower().toLatin1()).isEmpty()) {
#ifndef QT_NO_IMAGEFORMATPLUGIN #ifndef QT_NO_IMAGEFORMATPLUGIN
const int index = keyMap.key(QString::fromLatin1(suffix), -1); const int index = keyMap.key(QString::fromLatin1(suffix), -1);
@ -428,17 +428,17 @@ void QImageWriter::setFileName(const QString &fileName)
} }
/*! /*!
If the currently assigned device is a QFile, or if setFileName() If the currently assigned device is a file, or if setFileName()
has been called, this function returns the name of the file has been called, this function returns the name of the file
QImageWriter writes to. Otherwise (i.e., if no device has been QImageWriter writes to. Otherwise (i.e., if no device has been
assigned or the device is not a QFile), an empty QString is assigned or the device is not a file), an empty QString is
returned. returned.
\sa setFileName(), setDevice() \sa setFileName(), setDevice()
*/ */
QString QImageWriter::fileName() const QString QImageWriter::fileName() const
{ {
QFile *file = qobject_cast<QFile *>(d->device); QFileDevice *file = qobject_cast<QFileDevice *>(d->device);
return file ? file->fileName() : QString(); return file ? file->fileName() : QString();
} }
@ -719,7 +719,7 @@ bool QImageWriter::write(const QImage &image)
if (!d->handler->write(img)) if (!d->handler->write(img))
return false; return false;
if (QFile *file = qobject_cast<QFile *>(d->device)) if (QFileDevice *file = qobject_cast<QFileDevice *>(d->device))
file->flush(); file->flush();
return true; return true;
} }

View File

@ -36,6 +36,7 @@
#include <QSet> #include <QSet>
#include <QTemporaryDir> #include <QTemporaryDir>
#include <QTemporaryFile> #include <QTemporaryFile>
#include <QSaveFile>
#ifdef Q_OS_UNIX // for geteuid() #ifdef Q_OS_UNIX // for geteuid()
# include <sys/types.h> # include <sys/types.h>
@ -75,6 +76,7 @@ private slots:
void saveWithNoFormat(); void saveWithNoFormat();
void saveToTemporaryFile(); void saveToTemporaryFile();
void saveToSaveFile();
void writeEmpty(); void writeEmpty();
@ -530,6 +532,59 @@ void tst_QImageWriter::saveToTemporaryFile()
} }
} }
void tst_QImageWriter::saveToSaveFile()
{
QImage image(prefix + "kollada.png");
QVERIFY(!image.isNull());
{
// Check canWrite
QImageWriter writer;
QSaveFile file(writePrefix + "savefile0.png");
writer.setDevice(&file);
QVERIFY2(writer.canWrite(), qPrintable(writer.errorString()));
}
QString fileName1(writePrefix + "savefile1.garble");
{
// Check failing canWrite
QVERIFY(!QFileInfo(fileName1).exists());
QImageWriter writer;
QSaveFile file(fileName1);
writer.setDevice(&file);
QVERIFY(!writer.canWrite());
QCOMPARE(writer.error(), QImageWriter::UnsupportedFormatError);
}
QVERIFY(!QFileInfo(fileName1).exists());
QString fileName2(writePrefix + "savefile2.png");
{
QImageWriter writer;
QSaveFile file(fileName2);
writer.setDevice(&file);
QCOMPARE(writer.fileName(), fileName2);
QVERIFY2(writer.write(image), qPrintable(writer.errorString()));
QVERIFY(file.commit());
}
{
QImage tmp;
QVERIFY(tmp.load(fileName2, "PNG"));
QCOMPARE(tmp, image);
}
QString fileName3(writePrefix + "savefile3.png");
{
QSaveFile file(fileName3);
QVERIFY(image.save(&file));
QVERIFY(file.commit());
}
{
QImage tmp;
QVERIFY(tmp.load(fileName3, "PNG"));
QCOMPARE(tmp, image);
}
}
void tst_QImageWriter::writeEmpty() void tst_QImageWriter::writeEmpty()
{ {
// check writing a null QImage errors gracefully // check writing a null QImage errors gracefully