diff --git a/src/KSaneImageSaver.h b/src/KSaneImageSaver.h --- a/src/KSaneImageSaver.h +++ b/src/KSaneImageSaver.h @@ -34,27 +34,20 @@ { Q_OBJECT public: - explicit KSaneImageSaver(QObject *parent = 0); + explicit KSaneImageSaver(QObject *parent = nullptr); ~KSaneImageSaver(); - bool savePng(const QString &name, const QByteArray &data, int width, int height, int format, int dpi); - - bool savePngSync(const QString &name, const QByteArray &data, int width, int height, int format, int dpi); - - bool saveTiff(const QString &name, const QByteArray &data, int width, int height, int format); - - bool saveTiffSync(const QString &name, const QByteArray &data, int width, int height, int format); - + bool saveQImage(const QUrl &url, const QString &name, const QByteArray &data, int width, int height, int bpl, int dpi, int format, const QString& fileFormat, int quality); + bool save16BitPng(const QUrl &url, const QString &name, const QByteArray &data, int width, int height, int bpl, int dpi, int format, const QString& fileFormat, int quality); Q_SIGNALS: - void imageSaved(bool success); + void imageSaved(const QUrl &url, const QString &name, bool success); protected: void run() Q_DECL_OVERRIDE; private: struct Private; Private *const d; - }; #endif diff --git a/src/KSaneImageSaver.cpp b/src/KSaneImageSaver.cpp --- a/src/KSaneImageSaver.cpp +++ b/src/KSaneImageSaver.cpp @@ -30,27 +30,28 @@ #include #include +#include struct KSaneImageSaver::Private { - enum ImageType { - ImageTypePNG, - ImageTypeTIFF - }; - bool m_savedOk; QMutex m_runMutex; - KSaneImageSaver *q; + QUrl m_url; QString m_name; QByteArray m_data; int m_width; int m_height; - int m_format; + int m_bpl; int m_dpi; - ImageType m_type; + int m_format; + QString m_fileFormat; + int m_quality; + bool m_savingAsPng16; - bool savePng(); - bool saveTiff(); + KSaneImageSaver *q; + + bool saveQImage(); + bool save16BitPng(); }; // ------------------------------------------------------------------------ @@ -65,80 +66,65 @@ delete d; } -bool KSaneImageSaver::savePng(const QString &name, const QByteArray &data, int width, int height, int format, int dpi) +bool KSaneImageSaver::saveQImage(const QUrl &url, const QString &name, const QByteArray &data, int width, int height, int bpl, int dpi, int format, const QString& fileFormat, int quality) { if (!d->m_runMutex.tryLock()) { return false; } + d->m_url = url; d->m_name = name; d->m_data = data; d->m_width = width; d->m_height = height; - d->m_format = format; + d->m_bpl = bpl; d->m_dpi = dpi; - d->m_type = Private::ImageTypePNG; + d->m_format = format; + d->m_fileFormat = fileFormat; + d->m_quality = quality; + d->m_savingAsPng16 = false; start(); return true; } -bool KSaneImageSaver::savePngSync(const QString &name, const QByteArray &data, int width, int height, int format, int dpi) -{ - if (!savePng(name, data, width, height, format, dpi)) { - qDebug() << "fail"; - return false; - } - wait(); - return d->m_savedOk; -} - -bool KSaneImageSaver::saveTiff(const QString &name, const QByteArray &data, int width, int height, int format) +bool KSaneImageSaver::save16BitPng(const QUrl &url, const QString &name, const QByteArray &data, int width, int height, int bpl, int dpi, int format, const QString& fileFormat, int quality) { if (!d->m_runMutex.tryLock()) { return false; } + d->m_url = url; d->m_name = name; d->m_data = data; d->m_width = width; d->m_height = height; + d->m_bpl = bpl; + d->m_dpi = dpi; d->m_format = format; - d->m_type = Private::ImageTypeTIFF; - - qDebug() << "saving Tiff images is not yet supported"; - d->m_runMutex.unlock(); - return false; -} + d->m_fileFormat = fileFormat; + d->m_quality = quality; + d->m_savingAsPng16 = true; -bool KSaneImageSaver::saveTiffSync(const QString &name, const QByteArray &data, int width, int height, int format) -{ - if (!saveTiff(name, data, width, height, format)) { - return false; - } - wait(); - return d->m_savedOk; + start(); + return true; } void KSaneImageSaver::run() { - if (d->m_type == Private::ImageTypeTIFF) { - d->m_savedOk = d->saveTiff(); - emit imageSaved(d->m_savedOk); - } - else { - d->m_savedOk = d->savePng(); - emit imageSaved(d->m_savedOk); - } + d->m_savedOk = d->m_savingAsPng16 ? d->save16BitPng() : d->saveQImage(); + emit imageSaved(d->m_url, d->m_name, d->m_savedOk); + d->m_runMutex.unlock(); } -bool KSaneImageSaver::Private::saveTiff() +bool KSaneImageSaver::Private::saveQImage() { - return false; + QImage img = KSaneIface::KSaneWidget::toQImageSilent(m_data, m_width, m_height, m_bpl, m_dpi, (KSaneIface::KSaneWidget::ImageFormat) m_format); + return img.save(m_name, qPrintable(m_fileFormat), m_quality); } -bool KSaneImageSaver::Private::savePng() +bool KSaneImageSaver::Private::save16BitPng() { FILE *file; png_structp png_ptr; diff --git a/src/skanlite.h b/src/skanlite.h --- a/src/skanlite.h +++ b/src/skanlite.h @@ -31,6 +31,7 @@ #include "ui_settings.h" #include "DBusInterface.h" +#include "KSaneImageSaver.h" class ShowImageDialog; class SaveLocation; @@ -64,6 +65,7 @@ void getDir(); void imageReady(QByteArray &, int, int, int, int); void saveImage(); + void imageSaved(const QUrl &url, const QString &name, bool success); void showAboutDialog(); void saveWindowSize(); @@ -93,6 +95,7 @@ private: KAboutData *m_aboutData; KSaneWidget *m_ksanew = nullptr; + KSaneImageSaver *m_imageSaver = nullptr; Ui::SkanliteSettings m_settingsUi; QDialog *m_settingsDialog = nullptr; ShowImageDialog *m_showImgDialog = nullptr; diff --git a/src/skanlite.cpp b/src/skanlite.cpp --- a/src/skanlite.cpp +++ b/src/skanlite.cpp @@ -24,7 +24,6 @@ #include "skanlite.h" -#include "KSaneImageSaver.h" #include "SaveLocation.h" #include "showimagedialog.h" @@ -79,6 +78,9 @@ connect(m_ksanew, &KSaneWidget::userMessage, this, &Skanlite::alertUser); connect(m_ksanew, &KSaneWidget::buttonPressed, this, &Skanlite::buttonPressed); + m_imageSaver = new KSaneImageSaver(this); + connect(m_imageSaver, &KSaneImageSaver::imageSaved, this, &Skanlite::imageSaved); + mainLayout->addWidget(m_ksanew); mainLayout->addWidget(dlgButtonBoxBottom); @@ -372,25 +374,48 @@ } } +bool pathExists(const QString& dir, QWidget* parent) +{ + // propose directory creation if doesn't exists + QUrl dirUrl(dir); + if (dirUrl.isLocalFile()) { + QDir path(dirUrl.toLocalFile()); + if (!path.exists()) { + if (KMessageBox::questionYesNo(parent, i18n("Directory doesn't exist, do you wish to create it?")) == KMessageBox::ButtonCode::Yes ) { + if (!path.mkpath(QLatin1String("."))) { + KMessageBox::error(parent, i18n("Could not create directory %1", path.path())); + return false; + } + } + } + } + return true; +} + void Skanlite::saveImage() { // ask the first time if we are in "ask on first" mode - if ((m_settingsUi.saveModeCB->currentIndex() == SaveModeAskFirst) && m_firstImage) { + QString dir = QDir::cleanPath(m_saveLocation->u_urlRequester->url().url()).append(QLatin1Char('/')); //make sure whole value is processed as path to directory + + while ((m_firstImage && (m_settingsUi.saveModeCB->currentIndex() == SaveModeAskFirst)) || + !pathExists(dir, this)) { if (m_saveLocation->exec() != QFileDialog::Accepted) { m_ksanew->scanCancel(); // In case we are cancelling a document feeder scan return; } + dir = QDir::cleanPath(m_saveLocation->u_urlRequester->url().url()).append(QLatin1Char('/')); m_firstImage = false; } - QString dir = QDir::cleanPath(m_saveLocation->u_urlRequester->url().url()).append(QLatin1Char('/')); //make sure whole value is processed as path to directory QString prefix = m_saveLocation->u_imgPrefix->text(); QString imgFormat = m_saveLocation->u_imgFormat->currentText().toLower(); int fileNumber = m_saveLocation->u_numStartFrom->value(); QStringList filterList = m_filterList; + bool enforceSavingAsPng16bit = false; if ((m_format == KSaneIface::KSaneWidget::FormatRGB_16_C) || (m_format == KSaneIface::KSaneWidget::FormatGrayScale16)) { filterList = m_filter16BitList; + enforceSavingAsPng16bit = true; if (imgFormat != QLatin1String("png")) { imgFormat = QLatin1String("png"); KMessageBox::information(this, i18n("The image will be saved in the PNG format, as Skanlite only supports saving 16 bit color images in the PNG format.")); @@ -487,9 +512,9 @@ QString localName; QString suffix = QFileInfo(fileUrl.fileName()).suffix(); - const char *fileFormat = nullptr; + QString fileFormat; if (suffix.isEmpty()) { - fileFormat = "png"; + fileFormat = QLatin1String("png"); } if (!fileUrl.isLocalFile()) { @@ -507,32 +532,25 @@ localName = fileUrl.toLocalFile(); } + // Save - if ((m_format == KSaneIface::KSaneWidget::FormatRGB_16_C) || - (m_format == KSaneIface::KSaneWidget::FormatGrayScale16)) { - KSaneImageSaver saver; - if (saver.savePngSync(localName, m_data, m_width, m_height, m_format, m_ksanew->currentDPI())) { - m_showImgDialog->close(); // closing the window if it is closed should not be a problem. - } - else { - perrorMessageBox(i18n("Failed to save image")); - return; - } + if (enforceSavingAsPng16bit) { + m_imageSaver->save16BitPng(fileUrl, localName, m_data, m_width, m_height, m_bytesPerLine, (int) m_ksanew->currentDPI(), m_format, fileFormat, quality); + } else { + m_imageSaver->saveQImage(fileUrl, localName, m_data, m_width, m_height, m_bytesPerLine, (int) m_ksanew->currentDPI(), m_format, fileFormat, quality); } - else { - // create the image if needed. - if (m_img.width() < 1) { - m_img = m_ksanew->toQImage(m_data, m_width, m_height, m_bytesPerLine, (KSaneIface::KSaneWidget::ImageFormat)m_format); - } - if (m_img.save(localName, fileFormat, quality)) { - m_showImgDialog->close(); // calling close() on a closed window does nothing. - } - else { - perrorMessageBox(i18n("Failed to save image")); - return; - } +} + +void Skanlite::imageSaved(const QUrl &fileUrl, const QString &localName, bool success) +{ + if (!success) { + perrorMessageBox(i18n("Failed to save image")); + return; } + m_showImgDialog->close(); // calling close() on a closed window does nothing. + + if (!fileUrl.isLocalFile()) { QFile tmpFile(localName); tmpFile.open(QIODevice::ReadOnly); @@ -542,7 +560,7 @@ tmpFile.close(); tmpFile.remove(); if (!ok) { - KMessageBox::sorry(0, i18n("Failed to upload image")); + KMessageBox::sorry(nullptr, i18n("Failed to upload image")); } else { emit m_dbusInterface.imageSaved(fileUrl.toString()); @@ -562,7 +580,7 @@ // Save the number QString fileNumStr = QFileInfo(fileUrl.fileName()).completeBaseName(); fileNumStr.remove(baseName); - fileNumber = fileNumStr.toInt(); + int fileNumber = fileNumStr.toInt(); if (fileNumber) { m_saveLocation->u_numStartFrom->setValue(fileNumber + 1); }