diff --git a/src/ksanewidget_p.cpp b/src/ksanewidget_p.cpp index e3d6f58..b41690d 100644 --- a/src/ksanewidget_p.cpp +++ b/src/ksanewidget_p.cpp @@ -1,1176 +1,1176 @@ /* ============================================================ * * This file is part of the KDE project * * Date : 2007-09-13 * Description : Sane interface for KDE * * Copyright (C) 2007-2008 by Kare Sars * Copyright (C) 2007-2008 by Gilles Caulier * Copyright (C) 2014 by Gregor Mitsch: port to KDE5 frameworks * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 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 6 of version 3 of the license. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program. If not, see . * * ============================================================ */ #include "ksanewidget_p.h" #include #include #include #include #include #include #include #include #define SCALED_PREVIEW_MAX_SIDE 400 static const int ActiveSelection = 100000; namespace KSaneIface { KSaneWidgetPrivate::KSaneWidgetPrivate(KSaneWidget *parent): q(parent) { // Device independent UI variables m_optsTabWidget = nullptr; m_basicOptsTab = nullptr; m_otherOptsTab = nullptr; m_zInBtn = nullptr; m_zOutBtn = nullptr; m_zSelBtn = nullptr; m_zFitBtn = nullptr; m_clearSelBtn = nullptr; m_prevBtn = nullptr; m_scanBtn = nullptr; m_cancelBtn = nullptr; m_previewViewer = nullptr; m_autoSelect = true; m_selIndex = ActiveSelection; m_warmingUp = nullptr; m_progressBar = nullptr; // scanning variables m_isPreview = false; m_saneHandle = nullptr; m_previewThread = nullptr; m_scanThread = nullptr; m_splitGamChB = nullptr; m_commonGamma = nullptr; m_previewDPI = 0; m_invertColors = nullptr; m_previewWidth = 0; m_previewHeight = 0; clearDeviceOptions(); m_findDevThread = FindSaneDevicesThread::getInstance(); connect(m_findDevThread, SIGNAL(finished()), this, SLOT(devListUpdated())); connect(m_findDevThread, SIGNAL(finished()), this, SLOT(signalDevListUpdate())); m_auth = KSaneAuth::getInstance(); m_optionPollTmr.setInterval(100); connect(&m_optionPollTmr, SIGNAL(timeout()), this, SLOT(pollPollOptions())); } void KSaneWidgetPrivate::clearDeviceOptions() { m_optSource = nullptr; m_colorOpts = nullptr; m_optNegative = nullptr; m_optFilmType = nullptr; m_optMode = nullptr; m_optDepth = nullptr; m_optRes = nullptr; m_optResX = nullptr; m_optResY = nullptr; m_optTlX = nullptr; m_optTlY = nullptr; m_optBrX = nullptr; m_optBrY = nullptr; m_optGamR = nullptr; m_optGamG = nullptr; m_optGamB = nullptr; m_optPreview = nullptr; m_optWaitForBtn = nullptr; m_scanOngoing = false; m_closeDevicePending = false; // delete all the options in the list. while (!m_optList.isEmpty()) { delete m_optList.takeFirst(); } m_pollList.clear(); m_optionPollTmr.stop(); // remove the remaining layouts/widgets and read thread delete m_basicOptsTab; m_basicOptsTab = nullptr; delete m_otherOptsTab; m_otherOptsTab = nullptr; delete m_previewThread; m_previewThread = nullptr; delete m_scanThread; m_scanThread = nullptr; m_devName.clear(); } void KSaneWidgetPrivate::devListUpdated() { if (m_vendor.isEmpty()) { const QList list = m_findDevThread->devicesList(); if (list.size() == 0) { return; } for (int i = 0; i < list.size(); ++i) { const KSaneWidget::DeviceInfo info = list.at(i); qDebug() << info.name; if (info.name == m_devName) { m_vendor = info.vendor; m_model = info.model; break; } } } } void KSaneWidgetPrivate::signalDevListUpdate() { emit(q->availableDevices(m_findDevThread->devicesList())); } KSaneWidget::ImageFormat KSaneWidgetPrivate::getImgFormat(SANE_Parameters ¶ms) { switch (params.format) { case SANE_FRAME_GRAY: switch (params.depth) { case 1: return KSaneWidget::FormatBlackWhite; case 8: return KSaneWidget::FormatGrayScale8; case 16: return KSaneWidget::FormatGrayScale16; default: return KSaneWidget::FormatNone; } case SANE_FRAME_RGB: case SANE_FRAME_RED: case SANE_FRAME_GREEN: case SANE_FRAME_BLUE: switch (params.depth) { case 8: return KSaneWidget::FormatRGB_8_C; case 16: return KSaneWidget::FormatRGB_16_C; default: return KSaneWidget::FormatNone; } } return KSaneWidget::FormatNone; } int KSaneWidgetPrivate::getBytesPerLines(SANE_Parameters ¶ms) { switch (getImgFormat(params)) { case KSaneWidget::FormatBlackWhite: case KSaneWidget::FormatGrayScale8: case KSaneWidget::FormatGrayScale16: return params.bytes_per_line; case KSaneWidget::FormatRGB_8_C: return params.pixels_per_line * 3; case KSaneWidget::FormatRGB_16_C: return params.pixels_per_line * 6; case KSaneWidget::FormatNone: case KSaneWidget::FormatBMP: // to remove warning (BMP is omly valid in the twain wrapper) return 0; } return 0; } KSaneOption *KSaneWidgetPrivate::getOption(const QString &name) { int i; for (i = 0; i < m_optList.size(); ++i) { KSaneOption * option = m_optList.at(i); if (option->name() == name) { return option; } } return nullptr; } void KSaneWidgetPrivate::createOptInterface() { m_basicOptsTab = new QWidget; m_basicScrollA->setWidget(m_basicOptsTab); QVBoxLayout *basic_layout = new QVBoxLayout(m_basicOptsTab); KSaneOption *option; // Scan Source if ((option = getOption(QStringLiteral(SANE_NAME_SCAN_SOURCE))) != nullptr) { m_optSource = option; option->createWidget(m_basicOptsTab); basic_layout->addWidget(option->widget()); connect(m_optSource, SIGNAL(valueChanged()), this, SLOT(checkInvert()), Qt::QueuedConnection); } // film-type (note: No translation) if ((option = getOption(QStringLiteral("film-type"))) != nullptr) { m_optFilmType = option; option->createWidget(m_basicOptsTab); basic_layout->addWidget(option->widget()); connect(m_optFilmType, SIGNAL(valueChanged()), this, SLOT(checkInvert()), Qt::QueuedConnection); } else if ((option = getOption(QStringLiteral(SANE_NAME_NEGATIVE))) != nullptr) { m_optNegative = option; option->createWidget(m_basicOptsTab); basic_layout->addWidget(option->widget()); } // Scan mode if ((option = getOption(QStringLiteral(SANE_NAME_SCAN_MODE))) != nullptr) { m_optMode = option; option->createWidget(m_basicOptsTab); basic_layout->addWidget(option->widget()); } // Bitdepth if ((option = getOption(QStringLiteral(SANE_NAME_BIT_DEPTH))) != nullptr) { m_optDepth = option; option->createWidget(m_basicOptsTab); basic_layout->addWidget(option->widget()); } // Threshold if ((option = getOption(QStringLiteral(SANE_NAME_THRESHOLD))) != nullptr) { option->createWidget(m_basicOptsTab); basic_layout->addWidget(option->widget()); } // Resolution if ((option = getOption(QStringLiteral(SANE_NAME_SCAN_RESOLUTION))) != nullptr) { m_optRes = option; option->createWidget(m_basicOptsTab); basic_layout->addWidget(option->widget()); } // These two next resolution options are a bit tricky. if ((option = getOption(QStringLiteral(SANE_NAME_SCAN_X_RESOLUTION))) != nullptr) { m_optResX = option; if (!m_optRes) { m_optRes = m_optResX; } option->createWidget(m_basicOptsTab); basic_layout->addWidget(option->widget()); } if ((option = getOption(QStringLiteral(SANE_NAME_SCAN_Y_RESOLUTION))) != nullptr) { m_optResY = option; option->createWidget(m_basicOptsTab); basic_layout->addWidget(option->widget()); } // save a pointer to the preview option if possible if ((option = getOption(QStringLiteral(SANE_NAME_PREVIEW))) != nullptr) { m_optPreview = option; } // save a pointer to the "wait-for-button" option if possible (Note: No translation) if ((option = getOption(QStringLiteral("wait-for-button"))) != nullptr) { m_optWaitForBtn = option; } // scan area (Do not add the widgets) if ((option = getOption(QStringLiteral(SANE_NAME_SCAN_TL_X))) != nullptr) { m_optTlX = option; connect(option, SIGNAL(fValueRead(float)), this, SLOT(setTLX(float))); } if ((option = getOption(QStringLiteral(SANE_NAME_SCAN_TL_Y))) != nullptr) { m_optTlY = option; connect(option, SIGNAL(fValueRead(float)), this, SLOT(setTLY(float))); } if ((option = getOption(QStringLiteral(SANE_NAME_SCAN_BR_X))) != nullptr) { m_optBrX = option; connect(option, SIGNAL(fValueRead(float)), this, SLOT(setBRX(float))); } if ((option = getOption(QStringLiteral(SANE_NAME_SCAN_BR_Y))) != nullptr) { m_optBrY = option; connect(option, SIGNAL(fValueRead(float)), this, SLOT(setBRY(float))); } // Color Options Frame m_colorOpts = new QWidget(m_basicOptsTab); basic_layout->addWidget(m_colorOpts); QVBoxLayout *color_lay = new QVBoxLayout(m_colorOpts); color_lay->setContentsMargins(0, 0, 0, 0); // Add Color correction to the color "frame" if ((option = getOption(QStringLiteral(SANE_NAME_BRIGHTNESS))) != nullptr) { option->createWidget(m_colorOpts); color_lay->addWidget(option->widget()); } if ((option = getOption(QStringLiteral(SANE_NAME_CONTRAST))) != nullptr) { option->createWidget(m_colorOpts); color_lay->addWidget(option->widget()); } // Add gamma tables to the color "frame" QWidget *gamma_frm = new QWidget(m_colorOpts); color_lay->addWidget(gamma_frm); QVBoxLayout *gam_frm_l = new QVBoxLayout(gamma_frm); gam_frm_l->setContentsMargins(0, 0, 0, 0); if ((option = getOption(QStringLiteral(SANE_NAME_GAMMA_VECTOR_R))) != nullptr) { m_optGamR = option; option->createWidget(gamma_frm); gam_frm_l->addWidget(option->widget()); } if ((option = getOption(QStringLiteral(SANE_NAME_GAMMA_VECTOR_G))) != nullptr) { m_optGamG = option; option->createWidget(gamma_frm); gam_frm_l->addWidget(option->widget()); } if ((option = getOption(QStringLiteral(SANE_NAME_GAMMA_VECTOR_B))) != nullptr) { m_optGamB = option; option->createWidget(gamma_frm); gam_frm_l->addWidget(option->widget()); } if ((m_optGamR != nullptr) && (m_optGamG != nullptr) && (m_optGamB != nullptr)) { LabeledGamma *gamma = reinterpret_cast(m_optGamR->widget()); - m_commonGamma = new LabeledGamma(m_colorOpts, i18n(SANE_TITLE_GAMMA_VECTOR), gamma->size()); + m_commonGamma = new LabeledGamma(m_colorOpts, i18n(SANE_TITLE_GAMMA_VECTOR), gamma->size(), gamma->maxValue()); color_lay->addWidget(m_commonGamma); m_commonGamma->setToolTip(i18n(SANE_DESC_GAMMA_VECTOR)); connect(m_commonGamma, SIGNAL(gammaChanged(int,int,int)), m_optGamR->widget(), SLOT(setValues(int,int,int))); connect(m_commonGamma, SIGNAL(gammaChanged(int,int,int)), m_optGamG->widget(), SLOT(setValues(int,int,int))); connect(m_commonGamma, SIGNAL(gammaChanged(int,int,int)), m_optGamB->widget(), SLOT(setValues(int,int,int))); m_splitGamChB = new LabeledCheckbox(m_colorOpts, i18n("Separate color intensity tables")); color_lay->addWidget(m_splitGamChB); connect(m_splitGamChB, SIGNAL(toggled(bool)), gamma_frm, SLOT(setVisible(bool))); connect(m_splitGamChB, SIGNAL(toggled(bool)), m_commonGamma, SLOT(setHidden(bool))); gamma_frm->hide(); } if ((option = getOption(QStringLiteral(SANE_NAME_BLACK_LEVEL))) != nullptr) { option->createWidget(m_colorOpts); color_lay->addWidget(option->widget()); } if ((option = getOption(QStringLiteral(SANE_NAME_WHITE_LEVEL))) != nullptr) { option->createWidget(m_colorOpts); color_lay->addWidget(option->widget()); } m_invertColors = new LabeledCheckbox(m_colorOpts, i18n("Invert colors")); color_lay->addWidget(m_invertColors); m_invertColors->setChecked(false); connect(m_invertColors, SIGNAL(toggled(bool)), this, SLOT(invertPreview())); // add a stretch to the end to keep the parameters at the top basic_layout->addStretch(); // Remaining (un known) options go to the "Other Options" m_otherOptsTab = new QWidget; m_otherScrollA->setWidget(m_otherOptsTab); QVBoxLayout *other_layout = new QVBoxLayout(m_otherOptsTab); // add the remaining parameters for (int i = 0; i < m_optList.size(); ++i) { KSaneOption *option = m_optList.at(i); if ((option->widget() == nullptr) && (option->name() != QStringLiteral(SANE_NAME_SCAN_TL_X)) && (option->name() != QStringLiteral(SANE_NAME_SCAN_TL_Y)) && (option->name() != QStringLiteral(SANE_NAME_SCAN_BR_X)) && (option->name() != QStringLiteral(SANE_NAME_SCAN_BR_Y)) && (option->name() != QStringLiteral(SANE_NAME_PREVIEW)) && (option->hasGui())) { option->createWidget(m_otherOptsTab); other_layout->addWidget(option->widget()); } } // add a stretch to the end to keep the parameters at the top other_layout->addStretch(); // calculate label widths int labelWidth = 0; KSaneOptionWidget *tmpOption; // Basic Options for (int i = 0; i < basic_layout->count(); ++i) { if (basic_layout->itemAt(i) && basic_layout->itemAt(i)->widget()) { tmpOption = qobject_cast(basic_layout->itemAt(i)->widget()); if (tmpOption) { labelWidth = qMax(labelWidth, tmpOption->labelWidthHint()); } } } // Color Options for (int i = 0; i < basic_layout->count(); ++i) { if (basic_layout->itemAt(i) && basic_layout->itemAt(i)->widget()) { tmpOption = qobject_cast(basic_layout->itemAt(i)->widget()); if (tmpOption) { labelWidth = qMax(labelWidth, tmpOption->labelWidthHint()); } } } // Set label widths for (int i = 0; i < basic_layout->count(); ++i) { if (basic_layout->itemAt(i) && basic_layout->itemAt(i)->widget()) { tmpOption = qobject_cast(basic_layout->itemAt(i)->widget()); if (tmpOption) { tmpOption->setLabelWidth(labelWidth); } } } for (int i = 0; i < color_lay->count(); ++i) { if (color_lay->itemAt(i) && color_lay->itemAt(i)->widget()) { tmpOption = qobject_cast(color_lay->itemAt(i)->widget()); if (tmpOption) { tmpOption->setLabelWidth(labelWidth); } } } // Other Options labelWidth = 0; for (int i = 0; i < other_layout->count(); ++i) { if (other_layout->itemAt(i) && other_layout->itemAt(i)->widget()) { tmpOption = qobject_cast(other_layout->itemAt(i)->widget()); if (tmpOption) { labelWidth = qMax(labelWidth, tmpOption->labelWidthHint()); } } } for (int i = 0; i < other_layout->count(); ++i) { if (other_layout->itemAt(i) && other_layout->itemAt(i)->widget()) { tmpOption = qobject_cast(other_layout->itemAt(i)->widget()); if (tmpOption) { tmpOption->setLabelWidth(labelWidth); } } } // encsure that we do not get a scrollbar at the bottom of the option of the options int min_width = m_basicOptsTab->sizeHint().width(); if (min_width < m_otherOptsTab->sizeHint().width()) { min_width = m_otherOptsTab->sizeHint().width(); } m_optsTabWidget->setMinimumWidth(min_width + m_basicScrollA->verticalScrollBar()->sizeHint().width() + 5); } void KSaneWidgetPrivate::setDefaultValues() { KSaneOption *option; // Try to get Color mode by default if ((option = getOption(QStringLiteral(SANE_NAME_SCAN_MODE))) != nullptr) { option->setValue(i18n(SANE_VALUE_SCAN_MODE_COLOR)); } // Try to set 8 bit color if ((option = getOption(QStringLiteral(SANE_NAME_BIT_DEPTH))) != nullptr) { option->setValue(8); } // Try to set Scan resolution to 600 DPI if (m_optRes != nullptr) { m_optRes->setValue(600); } } void KSaneWidgetPrivate::scheduleValReload() { m_readValsTmr.start(5); } void KSaneWidgetPrivate::optReload() { int i; for (i = 0; i < m_optList.size(); ++i) { m_optList.at(i)->readOption(); // Also read the values m_optList.at(i)->readValue(); } // Gamma table special case if (m_optGamR && m_optGamG && m_optGamB) { m_commonGamma->setHidden(m_optGamR->state() == KSaneOption::STATE_HIDDEN); m_splitGamChB->setHidden(m_optGamR->state() == KSaneOption::STATE_HIDDEN); } // estimate the preview size and create an empty image // this is done so that you can select scan area without // having to scan a preview. updatePreviewSize(); // ensure that we do not get a scrollbar at the bottom of the option of the options int min_width = m_basicOptsTab->sizeHint().width(); if (min_width < m_otherOptsTab->sizeHint().width()) { min_width = m_otherOptsTab->sizeHint().width(); } m_optsTabWidget->setMinimumWidth(min_width + m_basicScrollA->verticalScrollBar()->sizeHint().width() + 5); m_previewViewer->zoom2Fit(); } void KSaneWidgetPrivate::valReload() { int i; QString tmp; for (i = 0; i < m_optList.size(); ++i) { m_optList.at(i)->readValue(); } } void KSaneWidgetPrivate::handleSelection(float tl_x, float tl_y, float br_x, float br_y) { if ((m_optTlX == nullptr) || (m_optTlY == nullptr) || (m_optBrX == nullptr) || (m_optBrY == nullptr)) { // clear the selection since we can not set one m_previewViewer->setTLX(0); m_previewViewer->setTLY(0); m_previewViewer->setBRX(0); m_previewViewer->setBRY(0); return; } float max_x, max_y; if ((m_previewImg.width() == 0) || (m_previewImg.height() == 0)) { return; } m_optBrX->getMaxValue(max_x); m_optBrY->getMaxValue(max_y); float ftl_x = tl_x * max_x; float ftl_y = tl_y * max_y; float fbr_x = br_x * max_x; float fbr_y = br_y * max_y; m_optTlX->setValue(ftl_x); m_optTlY->setValue(ftl_y); m_optBrX->setValue(fbr_x); m_optBrY->setValue(fbr_y); } void KSaneWidgetPrivate::setTLX(float ftlx) { // ignore this during an active scan if (m_previewThread->isRunning()) { return; } if (m_scanThread->isRunning()) { return; } if (m_scanOngoing) { return; } float max, ratio; //qDebug() << "setTLX " << ftlx; m_optBrX->getMaxValue(max); ratio = ftlx / max; //qDebug() << " -> " << ratio; m_previewViewer->setTLX(ratio); } void KSaneWidgetPrivate::setTLY(float ftly) { // ignore this during an active scan if (m_previewThread->isRunning()) { return; } if (m_scanThread->isRunning()) { return; } if (m_scanOngoing) { return; } float max, ratio; //qDebug() << "setTLY " << ftly; m_optBrY->getMaxValue(max); ratio = ftly / max; //qDebug() << " -> " << ratio; m_previewViewer->setTLY(ratio); } void KSaneWidgetPrivate::setBRX(float fbrx) { // ignore this during an active scan if (m_previewThread->isRunning()) { return; } if (m_scanThread->isRunning()) { return; } if (m_scanOngoing) { return; } float max, ratio; //qDebug() << "setBRX " << fbrx; m_optBrX->getMaxValue(max); ratio = fbrx / max; //qDebug() << " -> " << ratio; m_previewViewer->setBRX(ratio); } void KSaneWidgetPrivate::setBRY(float fbry) { // ignore this during an active scan if (m_previewThread->isRunning()) { return; } if (m_scanThread->isRunning()) { return; } if (m_scanOngoing) { return; } float max, ratio; //qDebug() << "setBRY " << fbry; m_optBrY->getMaxValue(max); ratio = fbry / max; //qDebug() << " -> " << ratio; m_previewViewer->setBRY(ratio); } void KSaneWidgetPrivate::updatePreviewSize() { float max_x = 0, max_y = 0; float ratio; int x, y; // check if an update is necessary if (m_optBrX != nullptr) { m_optBrX->getMaxValue(max_x); } if (m_optBrY != nullptr) { m_optBrY->getMaxValue(max_y); } if ((max_x == m_previewWidth) && (max_y == m_previewHeight)) { //qDebug() << "no preview size change"; return; } // The preview size has changed m_previewWidth = max_x; m_previewHeight = max_y; // set the scan area to the whole area m_previewViewer->clearSelections(); if (m_optTlX != nullptr) { m_optTlX->setValue(0); } if (m_optTlY != nullptr) { m_optTlY->setValue(0); } if (m_optBrX != nullptr) { m_optBrX->setValue(max_x); } if (m_optBrY != nullptr) { m_optBrY->setValue(max_y); } // create a "scaled" image of the preview ratio = max_x / max_y; if (ratio < 1) { x = SCALED_PREVIEW_MAX_SIDE; y = (int)(SCALED_PREVIEW_MAX_SIDE / ratio); } else { y = SCALED_PREVIEW_MAX_SIDE; x = (int)(SCALED_PREVIEW_MAX_SIDE / ratio); } m_previewImg = QImage(x, y, QImage::Format_RGB32); m_previewImg.fill(0xFFFFFFFF); // set the new image m_previewViewer->setQImage(&m_previewImg); } void KSaneWidgetPrivate::startPreviewScan() { if (m_scanOngoing) { return; } m_scanOngoing = true; SANE_Status status; float max_x, max_y; float dpi; // store the current settings of parameters to be changed if (m_optDepth != nullptr) { m_optDepth->storeCurrentData(); } if (m_optRes != nullptr) { m_optRes->storeCurrentData(); } if (m_optResX != nullptr) { m_optResX->storeCurrentData(); } if (m_optResY != nullptr) { m_optResY->storeCurrentData(); } if (m_optPreview != nullptr) { m_optPreview->storeCurrentData(); } // check if we can modify the selection if ((m_optTlX != nullptr) && (m_optTlY != nullptr) && (m_optBrX != nullptr) && (m_optBrY != nullptr)) { // get maximums m_optBrX->getMaxValue(max_x); m_optBrY->getMaxValue(max_y); // select the whole area m_optTlX->setValue(0); m_optTlY->setValue(0); m_optBrX->setValue(max_x); m_optBrY->setValue(max_y); } else { // no use to try auto selections if you can not use them m_autoSelect = false; } if (m_optRes != nullptr) { if (m_previewDPI >= 25.0) { m_optRes->setValue(m_previewDPI); if ((m_optResY != nullptr) && (m_optRes->name() == QStringLiteral(SANE_NAME_SCAN_X_RESOLUTION))) { m_optResY->setValue(m_previewDPI); } } else { // set the resopution to getMinValue and increase if necessary SANE_Parameters params; m_optRes->getMinValue(dpi); do { m_optRes->setValue(dpi); if ((m_optResY != nullptr) && (m_optRes->name() == QStringLiteral(SANE_NAME_SCAN_X_RESOLUTION))) { m_optResY->setValue(dpi); } //check what image size we would get in a scan status = sane_get_parameters(m_saneHandle, ¶ms); if (status != SANE_STATUS_GOOD) { qDebug() << "sane_get_parameters=" << sane_strstatus(status); previewScanDone(); return; } if (dpi > 600) { break; } // Increase the dpi value dpi += 25.0; } while ((params.pixels_per_line < 300) || ((params.lines > 0) && (params.lines < 300))); if (params.pixels_per_line == 0) { // This is a security measure for broken backends m_optRes->getMinValue(dpi); m_optRes->setValue(dpi); qDebug() << "Setting minimum DPI value for a broken back-end"; } } } // set preview option to true if possible if (m_optPreview != nullptr) { m_optPreview->setValue(SANE_TRUE); } // execute valReload if there is a pending value reload while (m_readValsTmr.isActive()) { m_readValsTmr.stop(); valReload(); } // clear the preview m_previewViewer->clearHighlight(); m_previewViewer->clearSelections(); m_previewImg.fill(0xFFFFFFFF); updatePreviewSize(); setBusy(true); m_progressBar->setValue(0); m_isPreview = true; m_previewThread->setPreviewInverted(m_invertColors->isChecked()); m_previewThread->start(); m_updProgressTmr.start(); } void KSaneWidgetPrivate::previewScanDone() { // even if the scan is finished successfully we need to call sane_cancel() sane_cancel(m_saneHandle); if (m_closeDevicePending) { setBusy(false); sane_close(m_saneHandle); m_saneHandle = nullptr; clearDeviceOptions(); emit(q->scanDone(KSaneWidget::NoError, QStringLiteral(""))); return; } // restore the original settings of the changed parameters if (m_optDepth != nullptr) { m_optDepth->restoreSavedData(); } if (m_optRes != nullptr) { m_optRes->restoreSavedData(); } if (m_optResX != nullptr) { m_optResX->restoreSavedData(); } if (m_optResY != nullptr) { m_optResY->restoreSavedData(); } if (m_optPreview != nullptr) { m_optPreview->restoreSavedData(); } m_previewViewer->setQImage(&m_previewImg); m_previewViewer->zoom2Fit(); if ((m_previewThread->saneStatus() != SANE_STATUS_GOOD) && (m_previewThread->saneStatus() != SANE_STATUS_EOF)) { alertUser(KSaneWidget::ErrorGeneral, i18n(sane_strstatus(m_previewThread->saneStatus()))); } else if (m_autoSelect) { m_previewViewer->findSelections(); } setBusy(false); m_scanOngoing = false; m_updProgressTmr.stop(); emit(q->scanDone(KSaneWidget::NoError, QStringLiteral(""))); return; } void KSaneWidgetPrivate::startFinalScan() { if (m_scanOngoing) { return; } m_scanOngoing = true; m_isPreview = false; float x1 = 0, y1 = 0, x2 = 0, y2 = 0, max_x, max_y; m_selIndex = 0; if ((m_optTlX != nullptr) && (m_optTlY != nullptr) && (m_optBrX != nullptr) && (m_optBrY != nullptr)) { // get maximums m_optBrX->getMaxValue(max_x); m_optBrY->getMaxValue(max_y); // reead the selection from the viewer m_previewViewer->selectionAt(m_selIndex, x1, y1, x2, y2); m_previewViewer->setHighlightArea(x1, y1, x2, y2); m_selIndex++; // calculate the option values x1 *= max_x; y1 *= max_y; x2 *= max_x; y2 *= max_y; // now set the selection m_optTlX->setValue(x1); m_optTlY->setValue(y1); m_optBrX->setValue(x2); m_optBrY->setValue(y2); } // execute a pending value reload while (m_readValsTmr.isActive()) { m_readValsTmr.stop(); valReload(); } setBusy(true); m_updProgressTmr.start(); m_scanThread->setImageInverted(m_invertColors->isChecked()); m_scanThread->start(); } void KSaneWidgetPrivate::oneFinalScanDone() { m_updProgressTmr.stop(); updateProgress(); if (m_closeDevicePending) { setBusy(false); sane_close(m_saneHandle); m_saneHandle = nullptr; clearDeviceOptions(); return; } if (m_scanThread->frameStatus() == KSaneScanThread::READ_READY) { // scan finished OK SANE_Parameters params = m_scanThread->saneParameters(); int lines = params.lines; if (lines == -1) { // this is probably a handscanner -> calculate the size from the read data int bytesPerLine = qMax(getBytesPerLines(params), 1); // ensure no div by 0 lines = m_scanData.size() / bytesPerLine; } emit(q->imageReady(m_scanData, params.pixels_per_line, lines, getBytesPerLines(params), (int)getImgFormat(params))); // now check if we should have automatic ADF batch scaning if (m_optSource) { QString source; m_optSource->getValue(source); if (source.contains(QStringLiteral("Automatic Document Feeder")) || source.contains(QStringLiteral("ADF"))) { // in batch mode only one area can be scanned per page //qDebug() << "source == " << source; m_updProgressTmr.start(); m_scanThread->start(); return; } } // Check if we have a "wait for button" batch scanning if (m_optWaitForBtn) { qDebug() << m_optWaitForBtn->name(); QString wait; m_optWaitForBtn->getValue(wait); qDebug() << "wait ==" << wait; if (wait == QStringLiteral("true")) { // in batch mode only one area can be scanned per page //qDebug() << "source == \"Automatic Document Feeder\""; m_updProgressTmr.start(); m_scanThread->start(); return; } } // not batch scan, call sane_cancel to be able to change parameters. sane_cancel(m_saneHandle); //qDebug() << "index=" << m_selIndex << "size=" << m_previewViewer->selListSize(); // check if we have multiple selections. if (m_previewViewer->selListSize() > m_selIndex) { if ((m_optTlX != nullptr) && (m_optTlY != nullptr) && (m_optBrX != nullptr) && (m_optBrY != nullptr)) { float x1 = 0, y1 = 0, x2 = 0, y2 = 0, max_x, max_y; // get maximums m_optBrX->getMaxValue(max_x); m_optBrY->getMaxValue(max_y); // read the selection from the viewer m_previewViewer->selectionAt(m_selIndex, x1, y1, x2, y2); // set the highlight m_previewViewer->setHighlightArea(x1, y1, x2, y2); // calculate the option values x1 *= max_x; y1 *= max_y; x2 *= max_x; y2 *= max_y; // now set the selection m_optTlX->setValue(x1); m_optTlY->setValue(y1); m_optBrX->setValue(x2); m_optBrY->setValue(y2); m_selIndex++; // execute a pending value reload while (m_readValsTmr.isActive()) { m_readValsTmr.stop(); valReload(); } m_updProgressTmr.start(); m_scanThread->start(); return; } } emit(q->scanDone(KSaneWidget::NoError, QStringLiteral(""))); } else { switch (m_scanThread->saneStatus()) { case SANE_STATUS_GOOD: case SANE_STATUS_CANCELLED: case SANE_STATUS_EOF: break; case SANE_STATUS_NO_DOCS: emit(q->scanDone(KSaneWidget::Information, i18n(sane_strstatus(m_scanThread->saneStatus())))); alertUser(KSaneWidget::Information, i18n(sane_strstatus(m_scanThread->saneStatus()))); break; case SANE_STATUS_UNSUPPORTED: case SANE_STATUS_IO_ERROR: case SANE_STATUS_NO_MEM: case SANE_STATUS_INVAL: case SANE_STATUS_JAMMED: case SANE_STATUS_COVER_OPEN: case SANE_STATUS_DEVICE_BUSY: case SANE_STATUS_ACCESS_DENIED: emit(q->scanDone(KSaneWidget::ErrorGeneral, i18n(sane_strstatus(m_scanThread->saneStatus())))); alertUser(KSaneWidget::ErrorGeneral, i18n(sane_strstatus(m_scanThread->saneStatus()))); break; } } sane_cancel(m_saneHandle); // clear the highlight m_previewViewer->setHighlightArea(0, 0, 1, 1); setBusy(false); m_scanOngoing = false; } void KSaneWidgetPrivate::setBusy(bool busy) { if (busy) { m_warmingUp->show(); m_activityFrame->hide(); m_btnFrame->hide(); m_optionPollTmr.stop(); emit(q->scanProgress(0)); } else { m_warmingUp->hide(); m_activityFrame->hide(); m_btnFrame->show(); if (m_pollList.size() > 0) { m_optionPollTmr.start(); } emit(q->scanProgress(100)); } m_optsTabWidget->setDisabled(busy); m_previewViewer->setDisabled(busy); m_scanBtn->setFocus(Qt::OtherFocusReason); } void KSaneWidgetPrivate::checkInvert() { if (!m_optSource) { return; } if (!m_optFilmType) { return; } if (m_scanOngoing) { return; } QString source; QString filmtype; m_optSource->getValue(source); m_optFilmType->getValue(filmtype); if ((source.contains(i18nc("This is compared to the option string returned by sane", "Transparency"), Qt::CaseInsensitive)) && (filmtype.contains(i18nc("This is compared to the option string returned by sane", "Negative"), Qt::CaseInsensitive))) { m_invertColors->setChecked(true); } else { m_invertColors->setChecked(false); } } void KSaneWidgetPrivate::invertPreview() { m_previewImg.invertPixels(); m_previewViewer->updateImage(); } void KSaneWidgetPrivate::updateProgress() { int progress; if (m_isPreview) { progress = m_previewThread->scanProgress(); if (m_previewThread->saneStartDone()) { if (!m_progressBar->isVisible() || m_previewThread->imageResized()) { m_warmingUp->hide(); m_activityFrame->show(); // the image size might have changed m_previewThread->imgMutex.lock(); m_previewViewer->setQImage(&m_previewImg); m_previewViewer->zoom2Fit(); m_previewThread->imgMutex.unlock(); } else { m_previewThread->imgMutex.lock(); m_previewViewer->updateImage(); m_previewThread->imgMutex.unlock(); } } } else { if (!m_progressBar->isVisible() && (m_scanThread->saneStartDone())) { m_warmingUp->hide(); m_activityFrame->show(); } progress = m_scanThread->scanProgress(); m_previewViewer->setHighlightShown(progress); } m_progressBar->setValue(progress); emit(q->scanProgress(progress)); } void KSaneWidgetPrivate::alertUser(int type, const QString &strStatus) { if (q->receivers(SIGNAL(userMessage(int,QString))) == 0) { switch (type) { case KSaneWidget::ErrorGeneral: QMessageBox::critical(nullptr, i18nc("@title:window", "General Error"), strStatus); break; default: QMessageBox::information(nullptr, i18nc("@title:window", "Information"), strStatus); break; } } else { emit(q->userMessage(type, strStatus)); } } void KSaneWidgetPrivate::pollPollOptions() { for (int i = 1; i < m_pollList.size(); ++i) { m_pollList.at(i)->readValue(); } } } // NameSpace KSaneIface diff --git a/src/options/ksaneoptgamma.cpp b/src/options/ksaneoptgamma.cpp index ec67f1f..cee571e 100644 --- a/src/options/ksaneoptgamma.cpp +++ b/src/options/ksaneoptgamma.cpp @@ -1,132 +1,134 @@ /* ============================================================ * * This file is part of the KDE project * * Date : 2009-01-31 * Description : Sane interface for KDE * * Copyright (C) 2009 by Kare Sars * Copyright (C) 2014 by Gregor Mitsch: port to KDE5 frameworks * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 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 6 of version 3 of the license. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program. If not, see . * * ============================================================ */ #include "ksaneoptgamma.h" #include "labeledgamma.h" #include #include namespace KSaneIface { KSaneOptGamma::KSaneOptGamma(const SANE_Handle handle, const int index) : KSaneOption(handle, index), m_gamma(nullptr) { } void KSaneOptGamma::createWidget(QWidget *parent) { if (m_widget) { return; } readOption(); if (!m_optDesc) { qDebug() << "This is a bug"; m_widget = new KSaneOptionWidget(parent, QStringLiteral("")); return; } - m_widget = m_gamma = new LabeledGamma(parent, sane_i18n(m_optDesc->title), - m_optDesc->size / sizeof(SANE_Word)); + m_widget = m_gamma = new LabeledGamma(parent, + sane_i18n(m_optDesc->title), + m_optDesc->size / sizeof(SANE_Word), + m_optDesc->constraint.range->max); connect(m_gamma, &LabeledGamma::gammaTableChanged, this, &KSaneOptGamma::gammaTableChanged); if (strcmp(m_optDesc->name, SANE_NAME_GAMMA_VECTOR_R) == 0) { m_gamma->setColor(Qt::red); } if (strcmp(m_optDesc->name, SANE_NAME_GAMMA_VECTOR_G) == 0) { m_gamma->setColor(Qt::green); } if (strcmp(m_optDesc->name, SANE_NAME_GAMMA_VECTOR_B) == 0) { m_gamma->setColor(Qt::blue); } m_widget->setToolTip(sane_i18n(m_optDesc->desc)); updateVisibility(); readValue(); } void KSaneOptGamma::gammaTableChanged(const QVector &gam_tbl) { QVector copy = gam_tbl; writeData(copy.data()); } void KSaneOptGamma::readValue() { // Unfortunately gamma table to brigthness, contrast and gamma is // not easy nor fast.. ergo not done } bool KSaneOptGamma::getValue(float &) { return false; } bool KSaneOptGamma::setValue(float) { return false; } bool KSaneOptGamma::getValue(QString &val) { if (!m_gamma) { return false; } if (state() == STATE_HIDDEN) { return false; } int bri; int con; int gam; m_gamma->getValues(bri, con, gam); val = QString().sprintf("%d:%d:%d", bri, con, gam); return true; } bool KSaneOptGamma::setValue(const QString &val) { if (!m_gamma) { return false; } if (state() == STATE_HIDDEN) { return false; } m_gamma->setValues(val); return true; } bool KSaneOptGamma::hasGui() { return true; } } // NameSpace KSaneIface diff --git a/src/widgets/gammadisp.cpp b/src/widgets/gammadisp.cpp index a539452..3e1a4f3 100644 --- a/src/widgets/gammadisp.cpp +++ b/src/widgets/gammadisp.cpp @@ -1,90 +1,90 @@ /* ============================================================ * * This file is part of the KDE project * * Date : 2007-09-13 * Description : Sane interface for KDE * * Copyright (C) 2007-2008 by Kare Sars * Copyright (C) 2014 by Gregor Mitsch: port to KDE5 frameworks * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 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 6 of version 3 of the license. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program. If not, see . * * ============================================================ */ // Local includes #include "gammadisp.h" // Qt includes #include namespace KSaneIface { -GammaDisp::GammaDisp(QWidget *parent, QVector *tbl) - : QWidget(parent) -{ - gam_tbl = tbl; - gam_color.setRgb(0, 0, 0); -} +GammaDisp::GammaDisp(QWidget *parent, QVector *tbl, int maxValue) +: QWidget(parent) +, m_gammaTable(tbl) +, m_gammaColor(QColor::fromRgb(0,0,0)) +, m_maxValue(maxValue) +{} QSize GammaDisp::minimumSizeHint() const { return QSize(75, 75); } QSize GammaDisp::sizeHint() const { return QSize(75, 75); } void GammaDisp::setColor(const QColor &color) { - gam_color = color; + m_gammaColor = color; } void GammaDisp::resizeEvent(QResizeEvent *) { repaint(); } void GammaDisp::paintEvent(QPaintEvent *) { /* QMemArray rects = event->region().rects(); for (int i = 0; i < (int)rects.size(); i++) { bitBlt(this, rects[i].topLeft(), &pixmap, rects[i]); }*/ QPointF p1, p2; QPainter painter(this); painter.fillRect(rect(), QBrush(Qt::white)); - double xscale = (double)(size().width() - 1) / (double)gam_tbl->size(); - double yscale = (double)(size().height() - 1) / (double)gam_tbl->size(); + double xscale = (double)(size().width() - 1) / (double)m_gammaTable->size(); + double yscale = (double)(size().height() - 1) / (double)m_maxValue; - painter.setPen(gam_color); - for (int i = 0; i < gam_tbl->size() - 1; i++) { + painter.setPen(m_gammaColor); + for (int i = 0; i < m_gammaTable->size() - 1; i++) { p1.setX(i * xscale); - p1.setY(size().height() - 1 - (gam_tbl->at(i) * yscale)); + p1.setY(size().height() - 1 - (m_gammaTable->at(i) * yscale)); p2.setX((i + 1)*xscale); - p2.setY(size().height() - 1 - (gam_tbl->at(i + 1) * yscale)); + p2.setY(size().height() - 1 - (m_gammaTable->at(i + 1) * yscale)); painter.drawLine(p1, p2); } } } // NameSpace KSaneIface diff --git a/src/widgets/gammadisp.h b/src/widgets/gammadisp.h index 8248bc1..e41937a 100644 --- a/src/widgets/gammadisp.h +++ b/src/widgets/gammadisp.h @@ -1,76 +1,77 @@ /* ============================================================ * * This file is part of the KDE project * * Date : 2007-09-13 * Description : Sane interface for KDE * * Copyright (C) 2007-2008 by Kare Sars * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 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 6 of version 3 of the license. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program. If not, see . * * ============================================================ */ #ifndef GAMMA_DISP_H #define GAMMA_DISP_H // Qt includes #include /** *@author Kåre Särs * * This is the widget that displays the gamma table. */ namespace KSaneIface { class GammaDisp : public QWidget { Q_OBJECT public: /** * Create a gamma display. * \param parent parent widget */ - GammaDisp(QWidget *parent, QVector *tbl); + GammaDisp(QWidget *parent, QVector *tbl, int maxValue); ~GammaDisp() {} QSize sizeHint() const override; QSize minimumSizeHint() const override; void setColor(const QColor &color); protected: void paintEvent(QPaintEvent *) override; void resizeEvent(QResizeEvent *) override; private: - QVector *gam_tbl; - QColor gam_color; + QVector *m_gammaTable; + QColor m_gammaColor; + int m_maxValue; }; } // NameSpace KSaneIface #endif // GAMMA_DISP_H diff --git a/src/widgets/labeledgamma.cpp b/src/widgets/labeledgamma.cpp index de2e97e..32f433f 100644 --- a/src/widgets/labeledgamma.cpp +++ b/src/widgets/labeledgamma.cpp @@ -1,211 +1,217 @@ /* ============================================================ * * This file is part of the KDE project * * Date : 2007-09-13 * Description : Sane interface for KDE * * Copyright (C) 2007-2011 by Kare Sars * Copyright (C) 2014 by Gregor Mitsch: port to KDE5 frameworks * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 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 6 of version 3 of the license. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program. If not, see . * * ============================================================ */ // Local includes #include "labeledgamma.h" #include #include #include namespace KSaneIface { -LabeledGamma::LabeledGamma(QWidget *parent, const QString &text, int size) +LabeledGamma::LabeledGamma(QWidget *parent, const QString &text, int size, int max) : KSaneOptionWidget(parent, text) { - m_bri_slider = new LabeledSlider(this, i18n("Brightness"), -50, 50, 1); - m_bri_slider->setValue(0); + m_brightSlider = new LabeledSlider(this, i18n("Brightness"), -50, 50, 1); + m_brightSlider->setValue(0); - m_con_slider = new LabeledSlider(this, i18n("Contrast"), -50, 50, 1); - m_con_slider->setValue(0); + m_contrastSlider = new LabeledSlider(this, i18n("Contrast"), -50, 50, 1); + m_contrastSlider->setValue(0); - m_gam_slider = new LabeledSlider(this, i18n("Gamma"), 30, 300, 1); - m_gam_slider->setValue(100); + m_gammaSlider = new LabeledSlider(this, i18n("Gamma"), 30, 300, 1); + m_gammaSlider->setValue(100); // Calculate the size of the widgets in the sliders - int labelMax = m_bri_slider->labelWidthHint(); - labelMax = qMax(labelMax, m_con_slider->labelWidthHint()); - labelMax = qMax(labelMax, m_gam_slider->labelWidthHint()); + int labelMax = m_brightSlider->labelWidthHint(); + labelMax = qMax(labelMax, m_contrastSlider->labelWidthHint()); + labelMax = qMax(labelMax, m_gammaSlider->labelWidthHint()); // set the calculated widths - m_bri_slider->setLabelWidth(labelMax); - m_con_slider->setLabelWidth(labelMax); - m_gam_slider->setLabelWidth(labelMax); + m_brightSlider->setLabelWidth(labelMax); + m_contrastSlider->setLabelWidth(labelMax); + m_gammaSlider->setLabelWidth(labelMax); - m_gam_tbl.resize(size); - for (int i = 0; i < m_gam_tbl.size(); i++) { - m_gam_tbl[i] = i; + m_gammaTable.resize(size); + for (int i = 0; i < m_gammaTable.size(); i++) { + m_gammaTable[i] = i; } - m_max_val = size - 1; // assume a gamma table 0 -> max + m_maxValue = max; - m_gamma_disp = new GammaDisp(this, &m_gam_tbl); + m_gammaDisplay = new GammaDisp(this, &m_gammaTable, m_maxValue); QGroupBox *groupBox = new QGroupBox(text, this); QGridLayout *gr_lay = new QGridLayout(groupBox); - gr_lay->addWidget(m_bri_slider, 0, 0); - gr_lay->addWidget(m_con_slider, 1, 0); - gr_lay->addWidget(m_gam_slider, 2, 0); - gr_lay->addWidget(m_gamma_disp, 0, 1, 3, 1); + gr_lay->addWidget(m_brightSlider, 0, 0); + gr_lay->addWidget(m_contrastSlider, 1, 0); + gr_lay->addWidget(m_gammaSlider, 2, 0); + gr_lay->addWidget(m_gammaDisplay, 0, 1, 3, 1); m_label->hide(); m_layout->addWidget(groupBox, 1, 0, 1, 3); - connect(m_bri_slider, &LabeledSlider::valueChanged, this, &LabeledGamma::calculateGT); - connect(m_con_slider, &LabeledSlider::valueChanged, this, &LabeledGamma::calculateGT); - connect(m_gam_slider, &LabeledSlider::valueChanged, this, &LabeledGamma::calculateGT); + connect(m_brightSlider, &LabeledSlider::valueChanged, this, &LabeledGamma::calculateGT); + connect(m_contrastSlider, &LabeledSlider::valueChanged, this, &LabeledGamma::calculateGT); + connect(m_gammaSlider, &LabeledSlider::valueChanged, this, &LabeledGamma::calculateGT); } LabeledGamma::~LabeledGamma() { } void LabeledGamma::setColor(const QColor &color) { - if (m_gamma_disp != nullptr) { - m_gamma_disp->setColor(color); + if (m_gammaDisplay != nullptr) { + m_gammaDisplay->setColor(color); } } void LabeledGamma::setValues(int bri, int con, int gam) { - m_bri_slider->blockSignals(true); - m_con_slider->blockSignals(true); - m_gam_slider->blockSignals(true); + m_brightSlider->blockSignals(true); + m_contrastSlider->blockSignals(true); + m_gammaSlider->blockSignals(true); - m_bri_slider->setValue(bri); - m_con_slider->setValue(con); - m_gam_slider->setValue(gam); + m_brightSlider->setValue(bri); + m_contrastSlider->setValue(con); + m_gammaSlider->setValue(gam); calculateGT(); - m_bri_slider->blockSignals(false); - m_con_slider->blockSignals(false); - m_gam_slider->blockSignals(false); + m_brightSlider->blockSignals(false); + m_contrastSlider->blockSignals(false); + m_gammaSlider->blockSignals(false); } void LabeledGamma::setValues(const QString &values) { - m_bri_slider->blockSignals(true); - m_con_slider->blockSignals(true); - m_gam_slider->blockSignals(true); + m_brightSlider->blockSignals(true); + m_contrastSlider->blockSignals(true); + m_gammaSlider->blockSignals(true); QStringList gammaValues; int bri; int con; int gam; bool ok = true; gammaValues = values.split(QLatin1Char(':')); bri = gammaValues.at(0).toInt(&ok); if (ok) { con = gammaValues.at(1).toInt(&ok); } if (ok) { gam = gammaValues.at(2).toInt(&ok); } if (ok) { - m_bri_slider->setValue(bri); - m_con_slider->setValue(con); - m_gam_slider->setValue(gam); + m_brightSlider->setValue(bri); + m_contrastSlider->setValue(con); + m_gammaSlider->setValue(gam); calculateGT(); } - m_bri_slider->blockSignals(false); - m_con_slider->blockSignals(false); - m_gam_slider->blockSignals(false); + m_brightSlider->blockSignals(false); + m_contrastSlider->blockSignals(false); + m_gammaSlider->blockSignals(false); } bool LabeledGamma::getValues(int &bri, int &con, int &gam) { - bri = m_bri_slider->value(); - con = m_con_slider->value(); - gam = m_gam_slider->value(); + bri = m_brightSlider->value(); + con = m_contrastSlider->value(); + gam = m_gammaSlider->value(); return true; } void LabeledGamma::setSize(int size) { - m_gam_tbl.resize(size); - for (int i = 0; i < m_gam_tbl.size(); i++) { - m_gam_tbl[i] = i; + m_gammaTable.resize(size); + for (int i = 0; i < m_gammaTable.size(); i++) { + m_gammaTable[i] = i; } - m_bri_slider->setValue(0); - m_con_slider->setValue(0); - m_gam_slider->setValue(0); + m_brightSlider->setValue(0); + m_contrastSlider->setValue(0); + m_gammaSlider->setValue(0); } const QVector &LabeledGamma::gammaTablePtr() { - return m_gam_tbl; + return m_gammaTable; } int LabeledGamma::size() { - return (int)(m_max_val + 1); + return m_gammaTable.size(); } +int LabeledGamma::maxValue() +{ + return m_maxValue; +} + + void LabeledGamma::calculateGT() { - double gam = 100.0 / m_gam_slider->value(); - double con = (200.0 / (100.0 - m_con_slider->value())) - 1; - double half_max = m_max_val / 2.0; - double bri = (m_bri_slider->value() / half_max) * m_max_val; + double gam = 100.0 / m_gammaSlider->value(); + double con = (200.0 / (100.0 - m_contrastSlider->value())) - 1; + double halfMax = m_maxValue / 2.0; + double bri = (m_brightSlider->value() / halfMax) * m_maxValue; double x; - for (int i = 0; i < m_gam_tbl.size(); i++) { + for (int i = 0; i < m_gammaTable.size(); i++) { // apply gamma - x = std::pow(i / m_max_val, gam) * m_max_val; + x = std::pow((double)i / m_gammaTable.size(), gam) * m_maxValue; // apply contrast - x = (con * (x - half_max)) + half_max; + x = (con * (x - halfMax)) + halfMax; // apply brightness + rounding x += bri + 0.5; // ensure correct value - if (x > m_max_val) { - x = m_max_val; + if (x > m_maxValue) { + x = m_maxValue; } if (x < 0) { x = 0; } - m_gam_tbl[i] = (int)x; + m_gammaTable[i] = (int)x; } - m_gamma_disp->update(); - emit gammaChanged(m_bri_slider->value(), m_con_slider->value(), m_gam_slider->value()); - emit gammaTableChanged(m_gam_tbl); + m_gammaDisplay->update(); + emit gammaChanged(m_brightSlider->value(), m_contrastSlider->value(), m_gammaSlider->value()); + emit gammaTableChanged(m_gammaTable); } } // NameSpace KSaneIface diff --git a/src/widgets/labeledgamma.h b/src/widgets/labeledgamma.h index abcb012..8e4f447 100644 --- a/src/widgets/labeledgamma.h +++ b/src/widgets/labeledgamma.h @@ -1,93 +1,97 @@ /* ============================================================ * * This file is part of the KDE project * * Date : 2007-09-13 * Description : Sane interface for KDE * * Copyright (C) 2007-2011 by Kare Sars * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 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 6 of version 3 of the license. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program. If not, see . * * ============================================================ */ #ifndef LABELED_GAMMA_H #define LABELED_GAMMA_H // Local includes #include "labeledslider.h" #include "gammadisp.h" /** *@author Kåre Särs */ namespace KSaneIface { /** * A wrapper for a checkbox */ class LabeledGamma : public KSaneOptionWidget { Q_OBJECT public: /** * Create the checkbox. * * \param parent parent widget * \param text is the text describing the checkbox. + * \param elements is the number of elements in the gamma table + * \param max is the maximum gamma-table-value */ - LabeledGamma(QWidget *parent, const QString &text, int elements); + LabeledGamma(QWidget *parent, const QString &text, int elements, int max); ~LabeledGamma(); void setColor(const QColor &color); void setSize(int size); const QVector &gammaTablePtr(); int size(); + int maxValue(); + bool getValues(int &bri, int &con, int &gam); public Q_SLOTS: void setValues(int bri, int con, int gam); void setValues(const QString &values); private Q_SLOTS: void calculateGT(); Q_SIGNALS: void gammaChanged(int bri, int con, int gam); - void gammaTableChanged(const QVector &gamma_tbl); + void gammaTableChanged(const QVector &gammaTable); private: - LabeledSlider *m_bri_slider; - LabeledSlider *m_con_slider; - LabeledSlider *m_gam_slider; + LabeledSlider *m_brightSlider; + LabeledSlider *m_contrastSlider; + LabeledSlider *m_gammaSlider; - QVector m_gam_tbl; - double m_max_val; + QVector m_gammaTable; + double m_maxValue; - GammaDisp *m_gamma_disp; + GammaDisp *m_gammaDisplay; }; } // NameSpace KSaneIface #endif // LABELED_GAMMA_H