Changeset View
Changeset View
Standalone View
Standalone View
src/skanlite.cpp
Show All 18 Lines | |||||
19 | * | 19 | * | ||
20 | * You should have received a copy of the GNU General Public License. | 20 | * You should have received a copy of the GNU General Public License. | ||
21 | * along with this program. If not, see <http://www.gnu.org/licenses/> | 21 | * along with this program. If not, see <http://www.gnu.org/licenses/> | ||
22 | * | 22 | * | ||
23 | * ============================================================ */ | 23 | * ============================================================ */ | ||
24 | 24 | | |||
25 | #include "skanlite.h" | 25 | #include "skanlite.h" | ||
26 | 26 | | |||
27 | #include "KSaneImageSaver.h" | | |||
28 | #include "SaveLocation.h" | 27 | #include "SaveLocation.h" | ||
29 | #include "showimagedialog.h" | 28 | #include "showimagedialog.h" | ||
30 | 29 | | |||
31 | #include <QApplication> | 30 | #include <QApplication> | ||
32 | #include <QScrollArea> | 31 | #include <QScrollArea> | ||
33 | #include <QStringList> | 32 | #include <QStringList> | ||
34 | #include <QFileDialog> | 33 | #include <QFileDialog> | ||
35 | #include <QUrl> | 34 | #include <QUrl> | ||
Show All 38 Lines | 62 | { | |||
74 | m_firstImage = true; | 73 | m_firstImage = true; | ||
75 | 74 | | |||
76 | m_ksanew = new KSaneIface::KSaneWidget(this); | 75 | m_ksanew = new KSaneIface::KSaneWidget(this); | ||
77 | connect(m_ksanew, &KSaneWidget::imageReady, this, &Skanlite::imageReady); | 76 | connect(m_ksanew, &KSaneWidget::imageReady, this, &Skanlite::imageReady); | ||
78 | connect(m_ksanew, &KSaneWidget::availableDevices, this, &Skanlite::availableDevices); | 77 | connect(m_ksanew, &KSaneWidget::availableDevices, this, &Skanlite::availableDevices); | ||
79 | connect(m_ksanew, &KSaneWidget::userMessage, this, &Skanlite::alertUser); | 78 | connect(m_ksanew, &KSaneWidget::userMessage, this, &Skanlite::alertUser); | ||
80 | connect(m_ksanew, &KSaneWidget::buttonPressed, this, &Skanlite::buttonPressed); | 79 | connect(m_ksanew, &KSaneWidget::buttonPressed, this, &Skanlite::buttonPressed); | ||
81 | 80 | | |||
81 | m_imageSaver = new KSaneImageSaver(this); | ||||
82 | connect(m_imageSaver, &KSaneImageSaver::imageSaved, this, &Skanlite::imageSaved); | ||||
83 | | ||||
82 | mainLayout->addWidget(m_ksanew); | 84 | mainLayout->addWidget(m_ksanew); | ||
83 | mainLayout->addWidget(dlgButtonBoxBottom); | 85 | mainLayout->addWidget(dlgButtonBoxBottom); | ||
84 | 86 | | |||
85 | m_ksanew->initGetDeviceList(); | 87 | m_ksanew->initGetDeviceList(); | ||
86 | 88 | | |||
87 | // read the size here... | 89 | // read the size here... | ||
88 | KConfigGroup window(KSharedConfig::openConfig(), "Window"); | 90 | KConfigGroup window(KSharedConfig::openConfig(), "Window"); | ||
89 | QSize rect = window.readEntry("Geometry", QSize(740, 400)); | 91 | QSize rect = window.readEntry("Geometry", QSize(740, 400)); | ||
▲ Show 20 Lines • Show All 277 Lines • ▼ Show 20 Line(s) | 363 | if (m_settingsUi.showB4Save->isChecked() == true) { | |||
367 | // save has been done as a result of save or then we got cancel | 369 | // save has been done as a result of save or then we got cancel | ||
368 | } | 370 | } | ||
369 | else { | 371 | else { | ||
370 | m_img = QImage(); // clear the image to ensure we save the correct one. | 372 | m_img = QImage(); // clear the image to ensure we save the correct one. | ||
371 | saveImage(); | 373 | saveImage(); | ||
372 | } | 374 | } | ||
373 | } | 375 | } | ||
374 | 376 | | |||
377 | bool pathExists(const QString& dir, QWidget* parent) | ||||
378 | { | ||||
379 | // propose directory creation if doesn't exists | ||||
380 | QUrl dirUrl(dir); | ||||
pino: toLocalFile(), otherwise the result is wrong on Windows (in case you care) | |||||
381 | if (dirUrl.isLocalFile()) { | ||||
382 | QDir path(dirUrl.toLocalFile()); | ||||
383 | if (!path.exists()) { | ||||
384 | if (KMessageBox::questionYesNo(parent, i18n("Directory doesn't exist, do you wish to create it?")) == KMessageBox::ButtonCode::Yes ) { | ||||
385 | if (!path.mkpath(QLatin1String("."))) { | ||||
386 | KMessageBox::error(parent, i18n("Could not create directory %1", path.path())); | ||||
387 | return false; | ||||
388 | } | ||||
389 | } | ||||
390 | } | ||||
391 | } | ||||
392 | return true; | ||||
Is this processEvents() really needed? processEvents() should be avoided... You cannot guarantee what state you are in when you come back from processEvents(). Your object might be deleted. Besides hasn't the event handler just been running during KMessageBox::questionYesNo() and in m_saveLocation->exec()? (In the dialogs, you have at least the dialog preventing UI interaction with the parent window.) sars: Is this processEvents() really needed? processEvents() should be avoided... You cannot… | |||||
393 | } | ||||
394 | | ||||
375 | void Skanlite::saveImage() | 395 | void Skanlite::saveImage() | ||
376 | { | 396 | { | ||
377 | // ask the first time if we are in "ask on first" mode | 397 | // ask the first time if we are in "ask on first" mode | ||
378 | if ((m_settingsUi.saveModeCB->currentIndex() == SaveModeAskFirst) && m_firstImage) { | 398 | QString dir = QDir::cleanPath(m_saveLocation->u_urlRequester->url().url()).append(QLatin1Char('/')); //make sure whole value is processed as path to directory | ||
399 | | ||||
400 | while ((m_firstImage && (m_settingsUi.saveModeCB->currentIndex() == SaveModeAskFirst)) || | ||||
401 | !pathExists(dir, this)) { | ||||
379 | if (m_saveLocation->exec() != QFileDialog::Accepted) { | 402 | if (m_saveLocation->exec() != QFileDialog::Accepted) { | ||
380 | m_ksanew->scanCancel(); // In case we are cancelling a document feeder scan | 403 | m_ksanew->scanCancel(); // In case we are cancelling a document feeder scan | ||
381 | return; | 404 | return; | ||
382 | } | 405 | } | ||
406 | dir = QDir::cleanPath(m_saveLocation->u_urlRequester->url().url()).append(QLatin1Char('/')); | ||||
383 | m_firstImage = false; | 407 | m_firstImage = false; | ||
384 | } | 408 | } | ||
385 | 409 | | |||
386 | QString dir = QDir::cleanPath(m_saveLocation->u_urlRequester->url().url()).append(QLatin1Char('/')); //make sure whole value is processed as path to directory | | |||
387 | QString prefix = m_saveLocation->u_imgPrefix->text(); | 410 | QString prefix = m_saveLocation->u_imgPrefix->text(); | ||
388 | QString imgFormat = m_saveLocation->u_imgFormat->currentText().toLower(); | 411 | QString imgFormat = m_saveLocation->u_imgFormat->currentText().toLower(); | ||
389 | int fileNumber = m_saveLocation->u_numStartFrom->value(); | 412 | int fileNumber = m_saveLocation->u_numStartFrom->value(); | ||
390 | QStringList filterList = m_filterList; | 413 | QStringList filterList = m_filterList; | ||
414 | bool enforceSavingAsPng16bit = false; | ||||
sars: enforceSavingAsPng16bit to keep the same variable-naming standard :) | |||||
391 | if ((m_format == KSaneIface::KSaneWidget::FormatRGB_16_C) || | 415 | if ((m_format == KSaneIface::KSaneWidget::FormatRGB_16_C) || | ||
392 | (m_format == KSaneIface::KSaneWidget::FormatGrayScale16)) { | 416 | (m_format == KSaneIface::KSaneWidget::FormatGrayScale16)) { | ||
393 | filterList = m_filter16BitList; | 417 | filterList = m_filter16BitList; | ||
418 | enforceSavingAsPng16bit = true; | ||||
394 | if (imgFormat != QLatin1String("png")) { | 419 | if (imgFormat != QLatin1String("png")) { | ||
395 | imgFormat = QLatin1String("png"); | 420 | imgFormat = QLatin1String("png"); | ||
396 | 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.")); | 421 | 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.")); | ||
397 | } | 422 | } | ||
398 | } | 423 | } | ||
399 | 424 | | |||
400 | //qDebug() << dir << prefix << imgFormat; | 425 | //qDebug() << dir << prefix << imgFormat; | ||
401 | 426 | | |||
▲ Show 20 Lines • Show All 80 Lines • ▼ Show 20 Line(s) | |||||
482 | if (m_settingsUi.setQuality->isChecked()) { | 507 | if (m_settingsUi.setQuality->isChecked()) { | ||
483 | quality = m_settingsUi.imgQuality->value(); | 508 | quality = m_settingsUi.imgQuality->value(); | ||
484 | } | 509 | } | ||
485 | 510 | | |||
486 | //qDebug() << "suffix" << QFileInfo(fileUrl.fileName()).suffix(); | 511 | //qDebug() << "suffix" << QFileInfo(fileUrl.fileName()).suffix(); | ||
487 | QString localName; | 512 | QString localName; | ||
488 | 513 | | |||
489 | QString suffix = QFileInfo(fileUrl.fileName()).suffix(); | 514 | QString suffix = QFileInfo(fileUrl.fileName()).suffix(); | ||
490 | const char *fileFormat = nullptr; | 515 | QString fileFormat; | ||
491 | if (suffix.isEmpty()) { | 516 | if (suffix.isEmpty()) { | ||
492 | fileFormat = "png"; | 517 | fileFormat = QLatin1String("png"); | ||
493 | } | 518 | } | ||
494 | 519 | | |||
495 | if (!fileUrl.isLocalFile()) { | 520 | if (!fileUrl.isLocalFile()) { | ||
496 | QTemporaryFile tmp; | 521 | QTemporaryFile tmp; | ||
497 | tmp.open(); | 522 | tmp.open(); | ||
498 | if (suffix.isEmpty()) { | 523 | if (suffix.isEmpty()) { | ||
499 | localName = tmp.fileName(); | 524 | localName = tmp.fileName(); | ||
500 | } | 525 | } | ||
501 | else { | 526 | else { | ||
502 | localName = QStringLiteral("%1.%2").arg(tmp.fileName(), suffix); | 527 | localName = QStringLiteral("%1.%2").arg(tmp.fileName(), suffix); | ||
503 | } | 528 | } | ||
504 | tmp.close(); // we just want the filename | 529 | tmp.close(); // we just want the filename | ||
505 | } | 530 | } | ||
506 | else { | 531 | else { | ||
507 | localName = fileUrl.toLocalFile(); | 532 | localName = fileUrl.toLocalFile(); | ||
508 | } | 533 | } | ||
509 | 534 | | |||
535 | | ||||
510 | // Save | 536 | // Save | ||
511 | if ((m_format == KSaneIface::KSaneWidget::FormatRGB_16_C) || | 537 | if (enforceSavingAsPng16bit) { | ||
512 | (m_format == KSaneIface::KSaneWidget::FormatGrayScale16)) { | 538 | m_imageSaver->save16BitPng(fileUrl, localName, m_data, m_width, m_height, m_bytesPerLine, (int) m_ksanew->currentDPI(), m_format, fileFormat, quality); | ||
513 | KSaneImageSaver saver; | 539 | } else { | ||
514 | if (saver.savePngSync(localName, m_data, m_width, m_height, m_format, m_ksanew->currentDPI())) { | 540 | m_imageSaver->saveQImage(fileUrl, localName, m_data, m_width, m_height, m_bytesPerLine, (int) m_ksanew->currentDPI(), m_format, fileFormat, quality); | ||
515 | m_showImgDialog->close(); // closing the window if it is closed should not be a problem. | | |||
516 | } | 541 | } | ||
This if() statement could theoretically reduce some overall processing time, but I do think that the time to move the data to the disk might be the real bottle neck (m_img.save(...)) so this could give you a UI freeze. So skip this if() and just do the else :) sars: This if() statement could theoretically reduce some overall processing time, but I do think… | |||||
517 | else { | | |||
518 | perrorMessageBox(i18n("Failed to save image")); | | |||
519 | return; | | |||
520 | } | | |||
521 | } | | |||
522 | else { | | |||
523 | // create the image if needed. | | |||
524 | if (m_img.width() < 1) { | | |||
525 | m_img = m_ksanew->toQImage(m_data, m_width, m_height, m_bytesPerLine, (KSaneIface::KSaneWidget::ImageFormat)m_format); | | |||
526 | } | | |||
527 | if (m_img.save(localName, fileFormat, quality)) { | | |||
528 | m_showImgDialog->close(); // calling close() on a closed window does nothing. | | |||
529 | } | 542 | } | ||
530 | else { | 543 | | ||
544 | void Skanlite::imageSaved(const QUrl &fileUrl, const QString &localName, bool success) | ||||
545 | { | ||||
546 | if (!success) { | ||||
531 | perrorMessageBox(i18n("Failed to save image")); | 547 | perrorMessageBox(i18n("Failed to save image")); | ||
532 | return; | 548 | return; | ||
533 | } | 549 | } | ||
534 | } | 550 | | ||
551 | m_showImgDialog->close(); // calling close() on a closed window does nothing. | ||||
552 | | ||||
535 | 553 | | |||
536 | if (!fileUrl.isLocalFile()) { | 554 | if (!fileUrl.isLocalFile()) { | ||
537 | QFile tmpFile(localName); | 555 | QFile tmpFile(localName); | ||
538 | tmpFile.open(QIODevice::ReadOnly); | 556 | tmpFile.open(QIODevice::ReadOnly); | ||
539 | auto uploadJob = KIO::storedPut(&tmpFile, fileUrl, -1); | 557 | auto uploadJob = KIO::storedPut(&tmpFile, fileUrl, -1); | ||
540 | KJobWidgets::setWindow(uploadJob, QApplication::activeWindow()); | 558 | KJobWidgets::setWindow(uploadJob, QApplication::activeWindow()); | ||
541 | bool ok = uploadJob->exec(); | 559 | bool ok = uploadJob->exec(); | ||
542 | tmpFile.close(); | 560 | tmpFile.close(); | ||
543 | tmpFile.remove(); | 561 | tmpFile.remove(); | ||
544 | if (!ok) { | 562 | if (!ok) { | ||
545 | KMessageBox::sorry(0, i18n("Failed to upload image")); | 563 | KMessageBox::sorry(nullptr, i18n("Failed to upload image")); | ||
546 | } | 564 | } | ||
547 | else { | 565 | else { | ||
548 | emit m_dbusInterface.imageSaved(fileUrl.toString()); | 566 | emit m_dbusInterface.imageSaved(fileUrl.toString()); | ||
549 | } | 567 | } | ||
550 | } | 568 | } | ||
551 | else { | 569 | else { | ||
552 | emit m_dbusInterface.imageSaved(localName); | 570 | emit m_dbusInterface.imageSaved(localName); | ||
553 | } | 571 | } | ||
554 | 572 | | |||
555 | // Save the file base name without number | 573 | // Save the file base name without number | ||
556 | QString baseName = QFileInfo(fileUrl.fileName()).completeBaseName(); | 574 | QString baseName = QFileInfo(fileUrl.fileName()).completeBaseName(); | ||
557 | while ((!baseName.isEmpty()) && (baseName[baseName.size() - 1].isNumber())) { | 575 | while ((!baseName.isEmpty()) && (baseName[baseName.size() - 1].isNumber())) { | ||
558 | baseName.remove(baseName.size() - 1, 1); | 576 | baseName.remove(baseName.size() - 1, 1); | ||
559 | } | 577 | } | ||
560 | m_saveLocation->u_imgPrefix->setText(baseName); | 578 | m_saveLocation->u_imgPrefix->setText(baseName); | ||
561 | 579 | | |||
562 | // Save the number | 580 | // Save the number | ||
563 | QString fileNumStr = QFileInfo(fileUrl.fileName()).completeBaseName(); | 581 | QString fileNumStr = QFileInfo(fileUrl.fileName()).completeBaseName(); | ||
564 | fileNumStr.remove(baseName); | 582 | fileNumStr.remove(baseName); | ||
565 | fileNumber = fileNumStr.toInt(); | 583 | int fileNumber = fileNumStr.toInt(); | ||
566 | if (fileNumber) { | 584 | if (fileNumber) { | ||
567 | m_saveLocation->u_numStartFrom->setValue(fileNumber + 1); | 585 | m_saveLocation->u_numStartFrom->setValue(fileNumber + 1); | ||
568 | } | 586 | } | ||
569 | 587 | | |||
570 | if (m_settingsUi.saveModeCB->currentIndex() == SaveModeManual) { | 588 | if (m_settingsUi.saveModeCB->currentIndex() == SaveModeManual) { | ||
571 | // Save last used dir, prefix and suffix. | 589 | // Save last used dir, prefix and suffix. | ||
572 | m_saveLocation->u_urlRequester->setUrl(KIO::upUrl(fileUrl)); | 590 | m_saveLocation->u_urlRequester->setUrl(KIO::upUrl(fileUrl)); | ||
573 | m_saveLocation->u_imgFormat->setCurrentText(QFileInfo(fileUrl.fileName()).suffix()); | 591 | m_saveLocation->u_imgFormat->setCurrentText(QFileInfo(fileUrl.fileName()).suffix()); | ||
▲ Show 20 Lines • Show All 216 Lines • Show Last 20 Lines |
toLocalFile(), otherwise the result is wrong on Windows (in case you care)