diff --git a/src/SaveLocation.cpp b/src/SaveLocation.cpp index 5cc1d6c..5949f37 100644 --- a/src/SaveLocation.cpp +++ b/src/SaveLocation.cpp @@ -1,69 +1,94 @@ /* ============================================================ * Date : 2010-07-07 * Description : Save location settings dialog. * * Copyright (C) 2010-2012 by Kare Sars * Copyright (C) 2014 by Gregor Mitsch: port to KDE5 frameworks * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License. * along with this program. If not, see * * ============================================================ */ #include "SaveLocation.h" +#include "ui_SaveLocation.h" #include #include #include #include SaveLocation::SaveLocation(QWidget *parent) : QDialog(parent) { - setupUi(this); + m_ui = new Ui_SaveLocation(); + m_ui->setupUi(this); - u_urlRequester->setMode(KFile::Directory); - connect(u_urlRequester, &KUrlRequester::textChanged, this, &SaveLocation::updateGui); - connect(u_imgPrefix, &QLineEdit::textChanged, this, &SaveLocation::updateGui); + m_ui->u_urlRequester->setMode(KFile::Directory); + connect(m_ui->u_urlRequester, &KUrlRequester::textChanged, this, &SaveLocation::updateGui); + connect(m_ui->u_imgPrefix, &QLineEdit::textChanged, this, &SaveLocation::updateGui); #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) connect(u_imgFormat, static_cast(&QComboBox::activated), this, &SaveLocation::updateGui); #else - connect(u_imgFormat, static_cast(&QComboBox::textActivated), this, &SaveLocation::updateGui); + connect(m_ui->u_imgFormat, static_cast(&QComboBox::textActivated), this, &SaveLocation::updateGui); #endif - connect(u_numStartFrom, static_cast(&QSpinBox::valueChanged), this, &SaveLocation::updateGui); + connect(m_ui->u_numStartFrom, static_cast(&QSpinBox::valueChanged), this, &SaveLocation::updateGui); } SaveLocation::~SaveLocation() { } void SaveLocation::updateGui() { - if (sender() != u_numStartFrom) { - u_numStartFrom->setValue(1); // Reset the counter whenever the directory or the prefix is changed + if (sender() != m_ui->u_numStartFrom) { + m_ui->u_numStartFrom->setValue(1); // Reset the counter whenever the directory or the prefix is changed } - const QString name = QString::fromLatin1("%1%2.%3").arg(u_imgPrefix->text()).arg(u_numStartFrom->value(), 4, 10, QLatin1Char('0')).arg(u_imgFormat->currentText()); - QString dir = QDir::cleanPath(u_urlRequester->url().toString()).append(QLatin1Char('/')); //make sure whole value is processed as path to directory - u_resultValue->setText(QUrl(dir).resolved(QUrl(name)).toString(QUrl::PreferLocalFile | QUrl::NormalizePathSegments)); + const QString name = QString::fromLatin1("%1%2.%3") + .arg(m_ui->u_imgPrefix->text()) + .arg(m_ui->u_numStartFrom->value(), 4, 10, QLatin1Char('0')) + .arg(m_ui->u_imgFormat->currentText()); + QString dir = QDir::cleanPath(m_ui->u_urlRequester->url().toString()).append(QLatin1Char('/')); //make sure whole value is processed as path to directory + m_ui->u_resultValue->setText(QUrl(dir).resolved(QUrl(name)).toString(QUrl::PreferLocalFile | QUrl::NormalizePathSegments)); } void SaveLocation::getDir(void) { - const QString newDir = QFileDialog::getExistingDirectory(this, QString(), u_urlRequester->url().toLocalFile()); + const QString newDir = QFileDialog::getExistingDirectory(this, QString(), m_ui->u_urlRequester->url().toLocalFile()); if (!newDir.isEmpty()) { - u_urlRequester->setUrl(QUrl::fromLocalFile(newDir)); + m_ui->u_urlRequester->setUrl(QUrl::fromLocalFile(newDir)); } } + +QUrl SaveLocation::folderUrl() const +{ + QUrl folderUrl = m_ui->u_urlRequester->url(); + folderUrl.setPath(folderUrl.path() + QLatin1Char('/')); + return folderUrl.adjusted(QUrl::NormalizePathSegments); +} + +QString SaveLocation::imagePrefix() const { return m_ui->u_imgPrefix->text(); } +QString SaveLocation::imageFormat() const { return m_ui->u_imgFormat->currentText().toLower(); } +int SaveLocation::startNumber() const { return m_ui->u_numStartFrom->value(); } +int SaveLocation::startNumberMax() const { return m_ui->u_numStartFrom->maximum(); } + + +void SaveLocation::setFolderUrl(const QUrl &url) { m_ui->u_urlRequester->setUrl(url); } +void SaveLocation::setImagePrefix(const QString &prefix) { m_ui->u_imgPrefix->setText(prefix); } +void SaveLocation::setImageFormats(const QStringList &formats) { m_ui->u_imgFormat->addItems(formats); } +void SaveLocation::setImageFormat(const QString &format) { m_ui->u_imgFormat->setCurrentText(format); } +void SaveLocation::setStartNumber(int number) { m_ui->u_numStartFrom->setValue(number); } + diff --git a/src/SaveLocation.h b/src/SaveLocation.h index 20285aa..30fd92b 100644 --- a/src/SaveLocation.h +++ b/src/SaveLocation.h @@ -1,46 +1,63 @@ /* ============================================================ * Date : 2010-07-07 * Description : Save location settings dialog. * * Copyright (C) 2008-2012 by Kåre Särs * Copyright (C) 2014 by Gregor Mitsch: port to KDE5 frameworks * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License. * along with this program. If not, see * * ============================================================ */ #ifndef SAVE_LOCATION_H #define SAVE_LOCATION_H -#include "ui_SaveLocation.h" - #include -class SaveLocation : public QDialog, public Ui_SaveLocation +class Ui_SaveLocation; + +class SaveLocation : public QDialog { Q_OBJECT public: explicit SaveLocation(QWidget *parent = nullptr); ~SaveLocation(); + QUrl folderUrl() const; + QString imagePrefix() const; + QString imageFormat() const; + int startNumber() const; + int startNumberMax() const; + + void setFolderUrl(const QUrl &url); + void setImagePrefix(const QString &prefix); + void setImageFormat(const QString &format); + void setStartNumber(int number); + + void setImageFormats(const QStringList &formats); + private Q_SLOTS: void updateGui(); void getDir(); + +private: + Ui_SaveLocation *m_ui; + }; #endif diff --git a/src/SaveLocation.ui b/src/SaveLocation.ui index a6d7127..8789582 100644 --- a/src/SaveLocation.ui +++ b/src/SaveLocation.ui @@ -1,190 +1,193 @@ SaveLocation 0 0 452 - 162 + 178 0 0 Save Location Save Location: Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - + 0 0 + + KFile::Directory|KFile::ExistingOnly + Name & Format: Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter ####. Start numbering from: Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter 0 999999 Qt::Horizontal 168 20 Example: /home/joe/example.png Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter Qt::Horizontal QDialogButtonBox::Cancel|QDialogButtonBox::Ok KUrlRequester QWidget
kurlrequester.h
u_dialogButtonBox accepted() SaveLocation accept() 200 152 200 86 u_dialogButtonBox rejected() SaveLocation reject() 200 152 200 86
diff --git a/src/settings.ui b/src/settings.ui index 96a39c9..e4d1ab5 100644 --- a/src/settings.ui +++ b/src/settings.ui @@ -1,405 +1,415 @@ SkanliteSettings 0 0 - 436 - 316 + 453 + 370 Settings Image saving Preview before saving: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter showB4Save Save mode: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter saveModeCB Open the save dialog for every image Open the save dialog for the first image only Qt::Horizontal Save Location: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - saveDirLEdit - - - - - - - - - - - 0 - 0 - - - - ... - Name && Format: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter imgPrefix Image ####. Specify save quality: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter setQuality false QFrame::NoFrame QFrame::Plain 0 6 - + + 0 + + + 0 + + + 0 + + 0 100 85 85 Qt::Horizontal % 100 85 Qt::Horizontal + + + + + 0 + 0 + + + + KFile::Directory|KFile::ExistingOnly + + + General Set preview resolution (DPI) false true 50 75 100 150 300 600 Disable automatic selections Qt::Horizontal 40 20 Qt::Horizontal 40 20 Revert scanner options to default values Qt::Vertical 1 1 + + + KUrlRequester + QWidget +
kurlrequester.h
+
+
setQuality toggled(bool) imgQualityFrame setEnabled(bool) 144 172 365 173 horizontalSlider valueChanged(int) imgQuality setValue(int) 303 172 365 173 imgQuality valueChanged(int) horizontalSlider setValue(int) 365 173 303 172 setPreviewDPI toggled(bool) previewDPI setEnabled(bool) 130 14 176 14
diff --git a/src/skanlite.cpp b/src/skanlite.cpp index a9134be..a70c9ed 100644 --- a/src/skanlite.cpp +++ b/src/skanlite.cpp @@ -1,795 +1,783 @@ /* ============================================================ * * Copyright (C) 2007-2012 by Kåre Särs * Copyright (C) 2009 by Arseniy Lartsev * Copyright (C) 2014 by Gregor Mitsch: port to KDE5 frameworks * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License. * along with this program. If not, see * * ============================================================ */ #include "skanlite.h" #include "SaveLocation.h" #include "showimagedialog.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include Skanlite::Skanlite(const QString &device, QWidget *parent) : QDialog(parent) , m_aboutData(nullptr) , m_dbusInterface(this) { QVBoxLayout *mainLayout = new QVBoxLayout(this); QDialogButtonBox *dlgButtonBoxBottom = new QDialogButtonBox(this); dlgButtonBoxBottom->setStandardButtons(QDialogButtonBox::Help | QDialogButtonBox::Close); // was "User2: QPushButton *btnAbout = dlgButtonBoxBottom->addButton(i18n("About"), QDialogButtonBox::ButtonRole::ActionRole); // was "User1": QPushButton *btnSettings = dlgButtonBoxBottom->addButton(i18n("Settings"), QDialogButtonBox::ButtonRole::ActionRole); btnSettings->setIcon(QIcon::fromTheme(QLatin1String("configure"))); m_firstImage = true; m_ksanew = new KSaneIface::KSaneWidget(this); connect(m_ksanew, &KSaneWidget::imageReady, this, &Skanlite::imageReady); connect(m_ksanew, &KSaneWidget::availableDevices, this, &Skanlite::availableDevices); connect(m_ksanew, &KSaneWidget::userMessage, this, &Skanlite::alertUser); connect(m_ksanew, &KSaneWidget::buttonPressed, this, &Skanlite::buttonPressed); connect(m_ksanew, &KSaneWidget::scanDone, [this](){ if (!m_pendingApplyScanOpts.isEmpty()) { applyScannerOptions(m_pendingApplyScanOpts); } }); m_imageSaver = new KSaneImageSaver(this); connect(m_imageSaver, &KSaneImageSaver::imageSaved, this, &Skanlite::imageSaved); mainLayout->addWidget(m_ksanew); mainLayout->addWidget(dlgButtonBoxBottom); m_ksanew->initGetDeviceList(); // read the size here... KConfigGroup window(KSharedConfig::openConfig(), "Window"); QSize rect = window.readEntry("Geometry", QSize(740, 400)); resize(rect); connect(dlgButtonBoxBottom, &QDialogButtonBox::rejected, this, &QDialog::close); connect(this, &QDialog::finished, this, &Skanlite::saveWindowSize); connect(this, &QDialog::finished, this, &Skanlite::saveScannerOptions); connect(btnSettings, &QPushButton::clicked, this, &Skanlite::showSettingsDialog); connect(btnAbout, &QPushButton::clicked, this, &Skanlite::showAboutDialog); connect(dlgButtonBoxBottom, &QDialogButtonBox::helpRequested, this, &Skanlite::showHelp); // // Create the settings dialog // { m_settingsDialog = new QDialog(this); QVBoxLayout *mainLayout = new QVBoxLayout(m_settingsDialog); QWidget *settingsWidget = new QWidget(m_settingsDialog); m_settingsUi.setupUi(settingsWidget); m_settingsUi.revertOptions->setIcon(QIcon::fromTheme(QLatin1String("edit-undo"))); m_saveLocation = new SaveLocation(this); // add the supported image types const QList tmpList = QImageWriter::supportedMimeTypes(); m_filterList.clear(); foreach (auto ba, tmpList) { if (ba.isEmpty()) { continue; } m_filterList.append(QString::fromLatin1(ba)); } qDebug() << m_filterList; // Put first class citizens at first place m_filterList.removeAll(QLatin1String("image/jpeg")); m_filterList.removeAll(QLatin1String("image/tiff")); m_filterList.removeAll(QLatin1String("image/png")); m_filterList.insert(0, QLatin1String("image/png")); m_filterList.insert(1, QLatin1String("image/jpeg")); m_filterList.insert(2, QLatin1String("image/tiff")); m_filter16BitList << QLatin1String("image/png"); //m_filter16BitList << QLatin1String("image/tiff"); // fill m_filterList (...) and m_typeList (list of file suffixes) foreach (QString mimeStr, m_filterList) { QMimeType mimeType = QMimeDatabase().mimeTypeForName(mimeStr); m_filterList.append(mimeType.name()); QStringList fileSuffixes = mimeType.suffixes(); if (fileSuffixes.size() > 0) { m_typeList << fileSuffixes.first(); } } m_settingsUi.imgFormat->addItems(m_typeList); - m_saveLocation->u_imgFormat->addItems(m_typeList); + m_saveLocation->setImageFormats(m_typeList); mainLayout->addWidget(settingsWidget); QDialogButtonBox *dlgButtonBoxBottom = new QDialogButtonBox(this); dlgButtonBoxBottom->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Close); connect(dlgButtonBoxBottom, &QDialogButtonBox::accepted, m_settingsDialog, &QDialog::accept); connect(dlgButtonBoxBottom, &QDialogButtonBox::rejected, m_settingsDialog, &QDialog::reject); mainLayout->addWidget(dlgButtonBoxBottom); m_settingsDialog->setWindowTitle(i18n("Skanlite Settings")); - connect(m_settingsUi.getDirButton, &QPushButton::clicked, this, &Skanlite::getDir); connect(m_settingsUi.revertOptions, &QPushButton::clicked, this, &Skanlite::defaultScannerOptions); readSettings(); // default directory for the save dialog - m_saveLocation->u_urlRequester->setUrl(QUrl::fromUserInput(m_settingsUi.saveDirLEdit->text())); - m_saveLocation->u_imgPrefix->setText(m_settingsUi.imgPrefix->text()); - m_saveLocation->u_imgFormat->setCurrentText(m_settingsUi.imgFormat->currentText()); + m_saveLocation->setFolderUrl(m_settingsUi.saveDirRequester->url()); + m_saveLocation->setImagePrefix(m_settingsUi.imgPrefix->text()); + m_saveLocation->setImageFormat(m_settingsUi.imgFormat->currentText()); } // open the scan device if (m_ksanew->openDevice(device) == false) { QString dev = m_ksanew->selectDevice(nullptr); if (dev.isEmpty()) { // either no scanner was found or then cancel was pressed. exit(0); } if (m_ksanew->openDevice(dev) == false) { // could not open a scanner KMessageBox::sorry(nullptr, i18n("Opening the selected scanner failed.")); exit(1); } else { setWindowTitle(i18nc("@title:window %1 = scanner maker, %2 = scanner model", "%1 %2 - Skanlite", m_ksanew->make(), m_ksanew->model())); m_deviceName = QString::fromLatin1("%1:%2").arg(m_ksanew->make()).arg(m_ksanew->model()); } } else { setWindowTitle(i18nc("@title:window %1 = scanner device", "%1 - Skanlite", device)); m_deviceName = device; } // prepare the Show Image Dialog m_showImgDialog = new ShowImageDialog(this); connect(m_showImgDialog, &ShowImageDialog::saveRequested, this, &Skanlite::saveImage); connect(m_showImgDialog, &ShowImageDialog::rejected, m_ksanew, &KSaneWidget::scanCancel); // save the default sane options for later use m_ksanew->getOptVals(m_defaultScanOpts); // load saved options loadScannerOptions(); m_ksanew->initGetDeviceList(); m_firstImage = true; if (m_dbusInterface.setupDBusInterface()) { // D-Bus related slots connect(&m_dbusInterface, &DBusInterface::requestedScan, m_ksanew, &KSaneWidget::scanFinal); connect(&m_dbusInterface, &DBusInterface::requestedPreview, m_ksanew, &KSaneWidget::startPreviewScan); connect(&m_dbusInterface, &DBusInterface::requestedScanCancel, m_ksanew, &KSaneWidget::scanCancel); connect(&m_dbusInterface, &DBusInterface::requestedSetScannerOptions, this, &Skanlite::setScannerOptions); connect(&m_dbusInterface, &DBusInterface::requestedSetSelection, this, &Skanlite::setSelection); // D-Bus related slots below must be Qt::DirectConnection to simplify return value forwarding via DBusInterface connect(&m_dbusInterface, &DBusInterface::requestedGetScannerOptions, this, &Skanlite::getScannerOptions, Qt::DirectConnection); connect(&m_dbusInterface, &DBusInterface::requestedDefaultScannerOptions, this, &Skanlite::getDefaultScannerOptions, Qt::DirectConnection); connect(&m_dbusInterface, &DBusInterface::requestedDeviceName, this, &Skanlite::getDeviceName, Qt::DirectConnection); connect(&m_dbusInterface, &DBusInterface::requestedSaveScannerOptionsToProfile, this, &Skanlite::saveScannerOptionsToProfile, Qt::DirectConnection); connect(&m_dbusInterface, &DBusInterface::requestedSwitchToProfile, this, &Skanlite::switchToProfile, Qt::DirectConnection); connect(&m_dbusInterface, &DBusInterface::requestedGetSelection, this, &Skanlite::getSelection, Qt::DirectConnection); // D-Bus related signals connect(m_ksanew, &KSaneWidget::scanDone, &m_dbusInterface, &DBusInterface::scanDone); connect(m_ksanew, &KSaneWidget::userMessage, &m_dbusInterface, &DBusInterface::userMessage); connect(m_ksanew, &KSaneWidget::scanProgress, &m_dbusInterface, &DBusInterface::scanProgress); connect(m_ksanew, &KSaneWidget::buttonPressed, &m_dbusInterface, &DBusInterface::buttonPressed); } else { // keep working without dbus } } void Skanlite::showHelp() { KHelpClient::invokeHelp(QLatin1String("index"), QLatin1String("skanlite")); } void Skanlite::setAboutData(KAboutData *aboutData) { m_aboutData = aboutData; } void Skanlite::closeEvent(QCloseEvent *event) { saveWindowSize(); saveScannerOptions(); event->accept(); } void Skanlite::saveWindowSize() { KConfigGroup window(KSharedConfig::openConfig(), "Window"); window.writeEntry("Geometry", size()); window.sync(); } // Pops up message box similar to what perror() would print //************************************************************ static void perrorMessageBox(const QString &text) { if (errno != 0) { KMessageBox::sorry(nullptr, i18n("%1: %2", text, QString::fromLocal8Bit(strerror(errno)))); } else { KMessageBox::sorry(nullptr, text); } } void Skanlite::readSettings(void) { // enable the widgets to allow modifying m_settingsUi.setQuality->setChecked(true); m_settingsUi.setPreviewDPI->setChecked(true); // read the saved parameters KConfigGroup saving(KSharedConfig::openConfig(), "Image Saving"); m_settingsUi.saveModeCB->setCurrentIndex(saving.readEntry("SaveMode", (int)SaveModeManual)); if (m_settingsUi.saveModeCB->currentIndex() != SaveModeAskFirst) { m_firstImage = false; } - m_settingsUi.saveDirLEdit->setText(saving.readEntry("Location", QDir::homePath())); + m_settingsUi.saveDirRequester->setUrl(saving.readEntry("Location", QUrl(QDir::homePath()))); m_settingsUi.imgPrefix->setText(saving.readEntry("NamePrefix", i18nc("prefix for auto naming", "Image-"))); m_settingsUi.imgFormat->setCurrentText(saving.readEntry("ImgFormat", "png")); m_settingsUi.imgQuality->setValue(saving.readEntry("ImgQuality", 90)); m_settingsUi.setQuality->setChecked(saving.readEntry("SetQuality", false)); m_settingsUi.showB4Save->setChecked(saving.readEntry("ShowBeforeSave", true)); KConfigGroup general(KSharedConfig::openConfig(), "General"); //m_settingsUi.previewDPI->setCurrentItem(general.readEntry("PreviewDPI", "100"), true); // FIXME KF5 is the 'true' parameter still needed? m_settingsUi.previewDPI->setCurrentText(general.readEntry("PreviewDPI", "100")); m_settingsUi.setPreviewDPI->setChecked(general.readEntry("SetPreviewDPI", false)); if (m_settingsUi.setPreviewDPI->isChecked()) { m_ksanew->setPreviewResolution(m_settingsUi.previewDPI->currentText().toFloat()); } else { m_ksanew->setPreviewResolution(0.0); } m_settingsUi.u_disableSelections->setChecked(general.readEntry("DisableAutoSelection", false)); m_ksanew->enableAutoSelect(!m_settingsUi.u_disableSelections->isChecked()); } void Skanlite::showSettingsDialog(void) { readSettings(); // show the dialog if (m_settingsDialog->exec()) { // save the settings KConfigGroup saving(KSharedConfig::openConfig(), "Image Saving"); saving.writeEntry("SaveMode", m_settingsUi.saveModeCB->currentIndex()); - saving.writeEntry("Location", m_settingsUi.saveDirLEdit->text()); + saving.writeEntry("Location", m_settingsUi.saveDirRequester->url()); saving.writeEntry("NamePrefix", m_settingsUi.imgPrefix->text()); saving.writeEntry("ImgFormat", m_settingsUi.imgFormat->currentText()); saving.writeEntry("SetQuality", m_settingsUi.setQuality->isChecked()); saving.writeEntry("ImgQuality", m_settingsUi.imgQuality->value()); saving.writeEntry("ShowBeforeSave", m_settingsUi.showB4Save->isChecked()); saving.sync(); KConfigGroup general(KSharedConfig::openConfig(), "General"); general.writeEntry("PreviewDPI", m_settingsUi.previewDPI->currentText()); general.writeEntry("SetPreviewDPI", m_settingsUi.setPreviewDPI->isChecked()); general.writeEntry("DisableAutoSelection", m_settingsUi.u_disableSelections->isChecked()); general.sync(); // the previewDPI has to be set here if (m_settingsUi.setPreviewDPI->isChecked()) { m_ksanew->setPreviewResolution(m_settingsUi.previewDPI->currentText().toFloat()); } else { // 0.0 means default value. m_ksanew->setPreviewResolution(0.0); } m_ksanew->enableAutoSelect(!m_settingsUi.u_disableSelections->isChecked()); // pressing OK in the settings dialog means use those settings. - m_saveLocation->u_urlRequester->setUrl(QUrl::fromUserInput(m_settingsUi.saveDirLEdit->text())); - m_saveLocation->u_imgPrefix->setText(m_settingsUi.imgPrefix->text()); - m_saveLocation->u_imgFormat->setCurrentText(m_settingsUi.imgFormat->currentText()); + m_saveLocation->setFolderUrl(m_settingsUi.saveDirRequester->url()); + m_saveLocation->setImagePrefix(m_settingsUi.imgPrefix->text()); + m_saveLocation->setImageFormat(m_settingsUi.imgFormat->currentText()); m_firstImage = true; } else { //Forget Changes readSettings(); } } void Skanlite::imageReady(QByteArray &data, int w, int h, int bpl, int f) { // save the image data m_data = data; m_width = w; m_height = h; m_bytesPerLine = bpl; m_format = f; if (m_settingsUi.showB4Save->isChecked() == true) { /* copy the image data into m_img and show it*/ m_img = m_ksanew->toQImageSilent(data, w, h, bpl, (KSaneIface::KSaneWidget::ImageFormat)f); m_showImgDialog->setQImage(&m_img); m_showImgDialog->zoom2Fit(); m_showImgDialog->exec(); // save has been done as a result of save or then we got cancel } else { m_img = QImage(); // clear the image to ensure we save the correct one. saveImage(); } } -bool pathExists(const QString& dir, QWidget* parent) +bool pathExists(const QUrl& dirUrl, 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 - QString dir = QDir::cleanPath(m_saveLocation->u_urlRequester->url().url()).append(QLatin1Char('/')); //make sure whole value is processed as path to directory + QUrl dirUrl = m_saveLocation->folderUrl(); while ((m_firstImage && (m_settingsUi.saveModeCB->currentIndex() == SaveModeAskFirst)) || - !pathExists(dir, this)) { + !pathExists(dirUrl, 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('/')); + dirUrl = m_saveLocation->folderUrl(); m_firstImage = false; } - QString prefix = m_saveLocation->u_imgPrefix->text(); - QString imgFormat = m_saveLocation->u_imgFormat->currentText().toLower(); - int fileNumber = m_saveLocation->u_numStartFrom->value(); + QString prefix = m_saveLocation->imagePrefix(); + QString imgFormat = m_saveLocation->imageFormat().toLower(); + int fileNumber = m_saveLocation->startNumber(); QStringList filterList = m_filterList; bool enforceSavingAsPng16bit = false; if ((m_format == KSaneIface::KSaneWidget::FormatRGB_16_C) || - (m_format == KSaneIface::KSaneWidget::FormatGrayScale16)) { + (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.")); } } - //qDebug() << dir << prefix << imgFormat; - // find next available file name for name suggestion QUrl fileUrl; QString fname; - for (int i = fileNumber; i <= m_saveLocation->u_numStartFrom->maximum(); ++i) { + for (int i = fileNumber; i <= m_saveLocation->startNumberMax(); ++i) { fname = QString::fromLatin1("%1%2.%3") .arg(prefix) .arg(i, 4, 10, QLatin1Char('0')) .arg(imgFormat); - fileUrl = QUrl::fromUserInput(QStringLiteral("%1%2").arg(dir, fname)); - //qDebug() << fileUrl; + fileUrl = dirUrl; + fileUrl.setPath(fileUrl.path() + fname); + fileUrl = fileUrl.adjusted(QUrl::NormalizePathSegments); if (fileUrl.isLocalFile()) { if (!QFileInfo(fileUrl.toLocalFile()).exists()) { break; } } else { - KIO::StatJob *statJob = KIO::stat(fileUrl, KIO::StatJob::DestinationSide, 0); + KIO::StatJob *statJob = KIO::statDetails(fileUrl, KIO::StatJob::DestinationSide); KJobWidgets::setWindow(statJob, QApplication::activeWindow()); if (!statJob->exec()) { break; } } } if (m_settingsUi.saveModeCB->currentIndex() == SaveModeManual) { // prepare the save dialog QFileDialog saveDialog(this, i18n("New Image File Name")); saveDialog.setAcceptMode(QFileDialog::AcceptSave); saveDialog.setFileMode(QFileDialog::AnyFile); // ask for a filename if requested. saveDialog.setDirectoryUrl(fileUrl.adjusted(QUrl::RemoveFilename)); saveDialog.selectUrl(fileUrl); // NOTE it is probably a bug that both setDirectoryUrl and selectUrl have // to be set to get remote urls to work QStringList actualFilterList = filterList; QString currentMimeFilter = QLatin1String("image/") + imgFormat; saveDialog.setMimeTypeFilters(actualFilterList); saveDialog.selectMimeTypeFilter(currentMimeFilter); - //qDebug() << fileUrl.url() << fileUrl.toLocalFile() << currentMimeFilter; if (saveDialog.exec() != QFileDialog::Accepted) { return; } fileUrl = saveDialog.selectedUrls()[0]; } m_firstImage = false; // Get the quality int quality = -1; if (m_settingsUi.setQuality->isChecked()) { quality = m_settingsUi.imgQuality->value(); } - //qDebug() << "suffix" << QFileInfo(fileUrl.fileName()).suffix(); QString localName; - QString suffix = QFileInfo(fileUrl.fileName()).suffix(); QString fileFormat; if (suffix.isEmpty()) { fileFormat = QLatin1String("png"); } if (!fileUrl.isLocalFile()) { QTemporaryFile tmp; tmp.open(); if (suffix.isEmpty()) { localName = tmp.fileName(); } else { localName = QStringLiteral("%1.%2").arg(tmp.fileName(), suffix); } tmp.close(); // we just want the filename } else { localName = fileUrl.toLocalFile(); } // Save 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); } } 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); auto uploadJob = KIO::storedPut(&tmpFile, fileUrl, -1); KJobWidgets::setWindow(uploadJob, QApplication::activeWindow()); bool ok = uploadJob->exec(); tmpFile.close(); tmpFile.remove(); if (!ok) { KMessageBox::sorry(nullptr, i18n("Failed to upload image")); } else { emit m_dbusInterface.imageSaved(fileUrl.toString()); } } else { emit m_dbusInterface.imageSaved(localName); } // Save the file base name without number QString baseName = QFileInfo(fileUrl.fileName()).completeBaseName(); while ((!baseName.isEmpty()) && (baseName[baseName.size() - 1].isNumber())) { baseName.remove(baseName.size() - 1, 1); } - m_saveLocation->u_imgPrefix->setText(baseName); + m_saveLocation->setImagePrefix(baseName); // Save the number QString fileNumStr = QFileInfo(fileUrl.fileName()).completeBaseName(); fileNumStr.remove(baseName); int fileNumber = fileNumStr.toInt(); if (fileNumber) { - m_saveLocation->u_numStartFrom->setValue(fileNumber + 1); + m_saveLocation->setStartNumber(fileNumber + 1); } if (m_settingsUi.saveModeCB->currentIndex() == SaveModeManual) { // Save last used dir, prefix and suffix. - m_saveLocation->u_urlRequester->setUrl(KIO::upUrl(fileUrl)); - m_saveLocation->u_imgFormat->setCurrentText(QFileInfo(fileUrl.fileName()).suffix()); - } -} - -void Skanlite::getDir(void) -{ - QString dir = QFileDialog::getExistingDirectory(m_settingsDialog, QString(), m_settingsUi.saveDirLEdit->text()); - if (!dir.isEmpty()) { - m_settingsUi.saveDirLEdit->setText(dir); + m_saveLocation->setFolderUrl(KIO::upUrl(fileUrl)); + m_saveLocation->setImageFormat(QFileInfo(fileUrl.fileName()).suffix()); } } void Skanlite::showAboutDialog(void) { KAboutApplicationDialog(*m_aboutData).exec(); } void writeScannerOptions(const QString &groupName, const QMap &opts) { KConfigGroup options(KSharedConfig::openConfig(), groupName); QMap::const_iterator it = opts.constBegin(); while (it != opts.constEnd()) { options.writeEntry(it.key(), it.value()); ++it; } options.sync(); } void readScannerOptions(const QString &groupName, QMap &opts) { KConfigGroup scannerOptions(KSharedConfig::openConfig(), groupName); opts = scannerOptions.entryMap(); } void Skanlite::saveScannerOptions() { KConfigGroup saving(KSharedConfig::openConfig(), "Image Saving"); - saving.writeEntry("NumberStartsFrom", m_saveLocation->u_numStartFrom->value()); + saving.writeEntry("NumberStartsFrom", m_saveLocation->startNumber()); if (!m_ksanew) { return; } KConfigGroup options(KSharedConfig::openConfig(), QString::fromLatin1("Options For %1").arg(m_deviceName)); QMap opts; m_ksanew->getOptVals(opts); writeScannerOptions(QString::fromLatin1("Options For %1").arg(m_deviceName), opts); } void Skanlite::defaultScannerOptions() { if (!m_ksanew) { return; } applyScannerOptions(m_defaultScanOpts); } void Skanlite::applyScannerOptions(const QMap &opts) { if (m_ksanew->setOptVals(opts) == -1) { m_pendingApplyScanOpts = opts; } else { m_pendingApplyScanOpts.clear(); } } void Skanlite::loadScannerOptions() { KConfigGroup saving(KSharedConfig::openConfig(), "Image Saving"); - m_saveLocation->u_numStartFrom->setValue(saving.readEntry("NumberStartsFrom", 1)); + m_saveLocation->setStartNumber(saving.readEntry("NumberStartsFrom", 1)); if (!m_ksanew) { return; } QMap opts; readScannerOptions(QString::fromLatin1("Options For %1").arg(m_deviceName), opts); applyScannerOptions(opts); } void Skanlite::availableDevices(const QList &deviceList) { for (int i = 0; i < deviceList.size(); ++i) { qDebug() << deviceList.at(i).name; } } void Skanlite::alertUser(int type, const QString &strStatus) { switch (type) { case KSaneWidget::ErrorGeneral: KMessageBox::sorry(nullptr, strStatus, QLatin1String("Skanlite Test")); break; default: KMessageBox::information(nullptr, strStatus, QLatin1String("Skanlite Test")); } } void Skanlite::buttonPressed(const QString &optionName, const QString &optionLabel, bool pressed) { qDebug() << "Button" << optionName << optionLabel << ((pressed) ? "pressed" : "released"); } // D-Bus interface related helper functions QStringList serializeScannerOptions(const QMap &opts) { QStringList sl; QMap::const_iterator it = opts.constBegin(); while (it != opts.constEnd()) { sl.append(it.key() + QLatin1Char('=') + it.value()); ++it; } return sl; } void deserializeScannerOptions(const QStringList &settings, QMap &opts) { foreach (QString s, settings) { int i = s.lastIndexOf(QLatin1Char('=')); opts[s.left(i)] = s.right(s.length()-i-1); } } static const QStringList selectionSettings = { QLatin1String("tl-x"), QLatin1String("tl-y"), QLatin1String("br-x"), QLatin1String("br-y") }; void filterSelectionSettings(QMap &opts) { foreach (QString s, selectionSettings) { opts.remove(s); } } bool containsSelectionSettings(const QMap &opts) { foreach (QString s, selectionSettings) { if (opts.contains(s)) { return true; } } return false; } void Skanlite::processSelectionOptions(QMap &opts, bool ignoreSelection) { if (ignoreSelection) { filterSelectionSettings(opts); } else { if (containsSelectionSettings(opts)) { // make sure we really have selection to apply m_ksanew->setSelection(QPointF(0,0), QPointF(1,1)); // bcs settings have no effect if nothing was selected beforehand (Bug 377009) } } } // D-Bus interface related slots void Skanlite::getScannerOptions() { QMap opts; m_ksanew->getOptVals(opts); m_dbusInterface.setReply(serializeScannerOptions(opts)); } void Skanlite::setScannerOptions(const QStringList &options, bool ignoreSelection) { QMap opts; deserializeScannerOptions(options, opts); processSelectionOptions(opts, ignoreSelection); applyScannerOptions(opts); } void Skanlite::getDefaultScannerOptions() { m_dbusInterface.setReply(serializeScannerOptions(m_defaultScanOpts)); } static const QLatin1String defaultProfileGroup("Options For %1 - Profile %2"); // 1 - device, 2 - arg void Skanlite::saveScannerOptionsToProfile(const QStringList &options, const QString &profile, bool ignoreSelection) { QMap opts; deserializeScannerOptions(options, opts); processSelectionOptions(opts, ignoreSelection); writeScannerOptions(QString(defaultProfileGroup).arg(m_deviceName).arg(profile), opts); } void Skanlite::switchToProfile(const QString &profile, bool ignoreSelection) { QMap opts; readScannerOptions(QString(defaultProfileGroup).arg(m_deviceName).arg(profile), opts); if (opts.empty()) { opts = m_defaultScanOpts; } processSelectionOptions(opts, ignoreSelection); applyScannerOptions(opts); } void Skanlite::getDeviceName() { m_dbusInterface.setReply(QStringList(m_deviceName)); } void Skanlite::getSelection() { QMap opts; m_ksanew->getOptVals(opts); QStringList reply; foreach ( QString key, selectionSettings ) { if (opts.contains(key)) { reply.append(key + QLatin1Char('=') + opts[key]); } } m_dbusInterface.setReply(reply); } void Skanlite::setSelection(const QStringList &options) { // here options contains selection related subset of options setScannerOptions(options, false); } diff --git a/src/skanlite.h b/src/skanlite.h index bbbe4ec..8a06d6c 100644 --- a/src/skanlite.h +++ b/src/skanlite.h @@ -1,122 +1,121 @@ /* ============================================================ * * Copyright (C) 2007-2012 by Kåre Särs * Copyright (C) 2014 by Gregor Mitsch: port to KDE5 frameworks * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License or (at your option) version 3 or any later version * accepted by the membership of KDE e.V. (or its successor approved * by the membership of KDE e.V.), which shall act as a proxy * defined in Section 14 of version 3 of the license. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License. * along with this program. If not, see * * ============================================================ */ #ifndef Skanlite_h #define Skanlite_h #include #include #include #include "ui_settings.h" #include "DBusInterface.h" #include "KSaneImageSaver.h" class ShowImageDialog; class SaveLocation; class KAboutData; using namespace KSaneIface; class Skanlite : public QDialog { Q_OBJECT public: explicit Skanlite(const QString &device, QWidget *parent); void setAboutData(KAboutData *aboutData); private: // Order of items in save mode combo-box enum SaveMode { SaveModeManual = 0, SaveModeAskFirst = 1, }; void readSettings(); void doSaveImage(bool askFilename = true); void loadScannerOptions(); void processSelectionOptions(QMap &opts, bool ignoreSelection); private Q_SLOTS: void showSettingsDialog(); - 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(); void saveScannerOptions(); void defaultScannerOptions(); void applyScannerOptions(const QMap &opts); void availableDevices(const QList &deviceList); void alertUser(int type, const QString &strStatus); void buttonPressed(const QString &optionName, const QString &optionLabel, bool pressed); void showHelp(); // slots to communicate with D-Bus interface void getScannerOptions(); void setScannerOptions(const QStringList &options, bool ignoreSelection); void getDefaultScannerOptions(); void saveScannerOptionsToProfile(const QStringList &options, const QString &profile, bool ignoreSelection); void switchToProfile(const QString &profile, bool ignoreSelection); void getDeviceName(); void getSelection(); void setSelection(const QStringList &options); protected: void closeEvent(QCloseEvent *event) Q_DECL_OVERRIDE; private: KAboutData *m_aboutData; KSaneWidget *m_ksanew = nullptr; KSaneImageSaver *m_imageSaver = nullptr; Ui::SkanliteSettings m_settingsUi; QDialog *m_settingsDialog = nullptr; ShowImageDialog *m_showImgDialog = nullptr; SaveLocation *m_saveLocation = nullptr; QString m_deviceName; QMap m_defaultScanOpts; QMap m_pendingApplyScanOpts; QImage m_img; QByteArray m_data; int m_width; int m_height; int m_bytesPerLine; int m_format; DBusInterface m_dbusInterface; QStringList m_filterList; QStringList m_filter16BitList; QStringList m_typeList; bool m_firstImage; }; #endif