diff --git a/src/ksanewidget.cpp b/src/ksanewidget.cpp --- a/src/ksanewidget.cpp +++ b/src/ksanewidget.cpp @@ -219,6 +219,12 @@ d->m_otherScrollA->setFrameShape(QFrame::NoFrame); d->m_optsTabWidget->addTab(d->m_otherScrollA, i18n("Scanner Specific Options")); + // Add the scan area options tab + d->m_areaScrollA = new QScrollArea; + d->m_areaScrollA->setWidgetResizable(true); + d->m_areaScrollA->setFrameShape(QFrame::NoFrame); + d->m_optsTabWidget->addTab(d->m_areaScrollA, i18n("Scan Area Options")); + d->m_splitter = new QSplitter(this); d->m_splitter->addWidget(d->m_optsTabWidget); d->m_splitter->setStretchFactor(0, 0); diff --git a/src/ksanewidget_p.h b/src/ksanewidget_p.h --- a/src/ksanewidget_p.h +++ b/src/ksanewidget_p.h @@ -54,6 +54,8 @@ #include "ksanepreviewthread.h" #include "ksanefinddevicesthread.h" #include "ksaneauth.h" +#include "labeledfslider.h" +#include "labeledcombo.h" #define IMG_DATA_R_SIZE 100000 @@ -98,10 +100,21 @@ void invertPreview(); void pollPollOptions(); + void updateScanarea(); + public: void alertUser(int type, const QString &strStatus); public: + QMap m_paperSizesMap; + LabeledCombo *m_scanareaPapersize; + LabeledFSlider *m_scanareaWidth; + LabeledFSlider *m_scanareaHeight; + LabeledFSlider *m_scanareaX; + LabeledFSlider *m_scanareaY; + QPushButton *m_scanareaFlip; + LabeledCheckbox *m_scanareaEnableManual; + // backend independent QTabWidget *m_optsTabWidget; QScrollArea *m_basicScrollA; @@ -111,6 +124,9 @@ QWidget *m_otherOptsTab; LabeledCheckbox *m_invertColors; + QScrollArea *m_areaScrollA; + QWidget *m_areaOptsTab; + QSplitter *m_splitter; SplitterCollapser *m_optionsCollapser; diff --git a/src/ksanewidget_p.cpp b/src/ksanewidget_p.cpp --- a/src/ksanewidget_p.cpp +++ b/src/ksanewidget_p.cpp @@ -38,6 +38,12 @@ #include #include +#include "labeledfslider.h" +#include "labeledcombo.h" +#include "labeledcheckbox.h" + + + #define SCALED_PREVIEW_MAX_SIDE 400 static const int ActiveSelection = 100000; @@ -416,6 +422,89 @@ // add a stretch to the end to keep the parameters at the top other_layout->addStretch(); + // scan area options + m_areaOptsTab = new QWidget; + m_areaScrollA->setWidget(m_areaOptsTab); + QVBoxLayout *area_layout = new QVBoxLayout(m_areaOptsTab); + + m_paperSizesMap.clear(); + + const QString defaultPaperSize = QStringLiteral("A4"); + + m_paperSizesMap[QStringLiteral("A3")] = QPointF(297.0f, 420.0f); + m_paperSizesMap[QStringLiteral("A4")] = QPointF(210.0f, 297.0f); + m_paperSizesMap[QStringLiteral("A5")] = QPointF(148.0f, 210.0f); + m_paperSizesMap[QStringLiteral("A6")] = QPointF(105.0f, 148.0f); + + m_paperSizesMap[QStringLiteral("B3")] = QPointF(353.0f, 500.0f); + m_paperSizesMap[QStringLiteral("B4")] = QPointF(250.0f, 353.0f); + m_paperSizesMap[QStringLiteral("B5")] = QPointF(176.0f, 250.0f); + m_paperSizesMap[QStringLiteral("B6")] = QPointF(125.0f, 176.0f); + + m_paperSizesMap[QStringLiteral("C3")] = QPointF(324.0f, 458.0f); + m_paperSizesMap[QStringLiteral("C4")] = QPointF(229.0f, 324.0f); + m_paperSizesMap[QStringLiteral("C5")] = QPointF(162.0f, 229.0f); + m_paperSizesMap[QStringLiteral("C6")] = QPointF(114.0f, 162.0f); + + m_paperSizesMap[QStringLiteral("Letter")] = QPointF(216.0f, 279.0f); + m_paperSizesMap[QStringLiteral("Legal")] = QPointF(216.0f, 356.0f); + m_paperSizesMap[QStringLiteral("Tabloid")] = QPointF(279.0f, 432.0f); + m_paperSizesMap[QStringLiteral("Ledger")] = QPointF(432.0f, 279.0f); + + m_paperSizesMap[QStringLiteral("Junior Legal")] = QPointF(127.0f, 203.0f); + m_paperSizesMap[QStringLiteral("Half Letter")] = QPointF(140.0f, 216.0f); + m_paperSizesMap[QStringLiteral("Government Letter")] = QPointF(203.0f, 267.0f); + m_paperSizesMap[QStringLiteral("Government Legal")] = QPointF(216.0f, 330.0f); + + m_scanareaPapersize = new LabeledCombo(m_areaOptsTab, i18n("select paper size"), m_paperSizesMap.keys()); + + m_scanareaWidth = new LabeledFSlider(m_areaOptsTab, i18n("width (mm)"), 0.0f, 500.0f, 0.1f); + m_scanareaHeight = new LabeledFSlider(m_areaOptsTab, i18n("height (mm)"), 0.0f, 500.0f, 0.1f); + + m_scanareaX = new LabeledFSlider(m_areaOptsTab, i18n("x offset (mm)"), 0.0f, 500.0f, 0.1f); + m_scanareaY = new LabeledFSlider(m_areaOptsTab, i18n("y offset (mm)"), 0.0f, 500.0f, 0.1f); + + m_scanareaFlip = new QPushButton(i18n("flip width/height"), m_areaOptsTab); + m_scanareaEnableManual = new LabeledCheckbox(m_areaOptsTab, i18n("enable manual selection")); + + m_scanareaEnableManual->setChecked(false); + + m_scanareaPapersize->setCurrentText(defaultPaperSize); + m_scanareaWidth->setValue(m_paperSizesMap[defaultPaperSize].x()); + m_scanareaHeight->setValue(m_paperSizesMap[defaultPaperSize].y()); + m_scanareaX->setValue(0.0f); + m_scanareaY->setValue(0.0f); + + connect(m_scanareaFlip, &QPushButton::clicked, this, [this]() { + float tmp = this->m_scanareaWidth->value(); + this->m_scanareaWidth->setValue(this->m_scanareaHeight->value()); + this->m_scanareaHeight->setValue(tmp); + }); + + connect(m_scanareaPapersize, &LabeledCombo::activatedStr, this, [this](const QString & selStr) { + QPointF selPoint = this->m_paperSizesMap[selStr]; + this->m_scanareaWidth->setValue(selPoint.x()); + this->m_scanareaHeight->setValue(selPoint.y()); + }); + + connect(m_scanareaWidth, SIGNAL(valueChanged(float)), SLOT(updateScanarea())); + connect(m_scanareaHeight, SIGNAL(valueChanged(float)), SLOT(updateScanarea())); + connect(m_scanareaX, SIGNAL(valueChanged(float)), SLOT(updateScanarea())); + connect(m_scanareaY, SIGNAL(valueChanged(float)), SLOT(updateScanarea())); + connect(m_scanareaEnableManual, SIGNAL(toggled(bool)), SLOT(updateScanarea())); + + area_layout->addWidget(m_scanareaPapersize); + area_layout->addWidget(m_scanareaWidth); + area_layout->addWidget(m_scanareaHeight); + + area_layout->addWidget(m_scanareaX); + area_layout->addWidget(m_scanareaY); + + area_layout->addWidget(m_scanareaFlip); + area_layout->addWidget(m_scanareaEnableManual); + + area_layout->addStretch(); + // calculate label widths int labelWidth = 0; KSaneOptionWidget *tmpOption; @@ -472,16 +561,70 @@ } } } + // Scan Area Options + labelWidth = 0; + for (int i = 0; i < area_layout->count(); ++i) { + if (area_layout->itemAt(i) && area_layout->itemAt(i)->widget()) { + tmpOption = qobject_cast(area_layout->itemAt(i)->widget()); + if (tmpOption) { + labelWidth = qMax(labelWidth, tmpOption->labelWidthHint()); + } + } + } + for (int i = 0; i < area_layout->count(); ++i) { + if (area_layout->itemAt(i) && area_layout->itemAt(i)->widget()) { + tmpOption = qobject_cast(area_layout->itemAt(i)->widget()); + if (tmpOption) { + tmpOption->setLabelWidth(labelWidth); + } + } + } // 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(); } + if (min_width < m_areaOptsTab->sizeHint().width()) { + min_width = m_areaOptsTab->sizeHint().width(); + } m_optsTabWidget->setMinimumWidth(min_width + m_basicScrollA->verticalScrollBar()->sizeHint().width() + 5); } +void KSaneWidgetPrivate::updateScanarea() +{ + if (m_scanareaEnableManual->isChecked()) + return; + + float w = m_scanareaWidth->value(); + float h = m_scanareaHeight->value(); + + float x1 = m_scanareaX->value(); + float y1 = m_scanareaY->value(); + + float x2 = x1 + w; + float y2 = y1 + h; + + float max_x = 0.0f; + float max_y = 0.0f; + m_optBrX->getMaxValue(max_x); + m_optBrY->getMaxValue(max_y); + + x1 = std::min(x1, max_x); + x2 = std::min(x2, max_x); + + y1 = std::min(y1, max_y); + y2 = std::min(y2, max_y); + + m_optTlX->setValue(x1); + m_optTlY->setValue(y1); + m_optBrX->setValue(x2); + m_optBrY->setValue(y2); + + m_previewViewer->setSelection(x1 / max_x, y1 / max_y, x2 / max_x, y2 / max_y); +} + void KSaneWidgetPrivate::setDefaultValues() { KSaneOption *option; @@ -535,6 +678,8 @@ m_optsTabWidget->setMinimumWidth(min_width + m_basicScrollA->verticalScrollBar()->sizeHint().width() + 5); + updateScanarea(); + m_previewViewer->zoom2Fit(); } @@ -547,6 +692,7 @@ m_optList.at(i)->readValue(); } + updateScanarea(); } void KSaneWidgetPrivate::handleSelection(float tl_x, float tl_y, float br_x, float br_y) diff --git a/src/widgets/labeledcombo.h b/src/widgets/labeledcombo.h --- a/src/widgets/labeledcombo.h +++ b/src/widgets/labeledcombo.h @@ -88,6 +88,7 @@ Q_SIGNALS: void activated(int); + void activatedStr(const QString&); private: QComboBox *m_combo; diff --git a/src/widgets/labeledcombo.cpp b/src/widgets/labeledcombo.cpp --- a/src/widgets/labeledcombo.cpp +++ b/src/widgets/labeledcombo.cpp @@ -42,6 +42,7 @@ m_label->setBuddy(m_combo); connect(m_combo, QOverload::of(&QComboBox::activated), this, &LabeledCombo::activated); + connect(m_combo, QOverload::of(&QComboBox::activated), this, &LabeledCombo::activatedStr); m_layout->addWidget(m_combo, 0, 1); m_layout->addWidget(new QWidget(this), 0, 2);