File indexing completed on 2024-12-01 07:26:16

0001 /*
0002  * SPDX-FileCopyrightText: 2009 Kare Sars <kare dot sars at iki dot fi>
0003  * SPDX-FileCopyrightText: 2014 Gregor Mitsch : port to KDE5 frameworks
0004  * SPDX-FileCopyrightText: 2021 Alexander Stippich <a.stippich@gmx.net>
0005  *
0006  * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0007  */
0008 
0009 #include "pagesizeoption.h"
0010 
0011 #include <QPageSize>
0012 #include <QSizeF>
0013 
0014 #include <ksanecore_debug.h>
0015 
0016 static constexpr int PageSizeWiggleRoom = 2; // in mm
0017 
0018 namespace KSaneCore
0019 {
0020 
0021 PageSizeOption::PageSizeOption(BaseOption *optionTopLeftX,
0022                                BaseOption *optionTopLeftY,
0023                                BaseOption *optionBottomRightX,
0024                                BaseOption *optionBottomRightY,
0025                                BaseOption *optionResolution)
0026     : BaseOption()
0027 {
0028     if (optionTopLeftX == nullptr || optionTopLeftY == nullptr || optionBottomRightX == nullptr || optionBottomRightY == nullptr) {
0029         m_optionType = Option::TypeDetectFail;
0030         return;
0031     }
0032 
0033     connect(optionTopLeftX, &BaseOption::valueChanged, this, &PageSizeOption::optionTopLeftXUpdated);
0034     connect(optionTopLeftY, &BaseOption::valueChanged, this, &PageSizeOption::optionTopLeftYUpdated);
0035     connect(optionBottomRightX, &BaseOption::valueChanged, this, &PageSizeOption::optionBottomRightXUpdated);
0036     connect(optionBottomRightY, &BaseOption::valueChanged, this, &PageSizeOption::optionBottomRightYUpdated);
0037 
0038     m_optionTopLeftX = optionTopLeftX;
0039     m_optionTopLeftY = optionTopLeftY;
0040     m_optionBottomRightX = optionBottomRightX;
0041     m_optionBottomRightY = optionBottomRightY;
0042     m_optionResolution = optionResolution;
0043 
0044     const QList<QPageSize::PageSizeId> possibleSizesList = {
0045         QPageSize::A3,
0046         QPageSize::A4,
0047         QPageSize::A5,
0048         QPageSize::A6,
0049         QPageSize::Letter,
0050         QPageSize::Legal,
0051         QPageSize::Tabloid,
0052         QPageSize::B3,
0053         QPageSize::B4,
0054         QPageSize::B5,
0055         QPageSize::B6,
0056         QPageSize::C5E,
0057         QPageSize::Comm10E,
0058         QPageSize::DLE,
0059         QPageSize::Executive,
0060         QPageSize::Folio,
0061         QPageSize::Ledger,
0062         QPageSize::JisB3,
0063         QPageSize::JisB4,
0064         QPageSize::JisB5,
0065         QPageSize::JisB6,
0066     };
0067 
0068     m_availableSizesList << QPageSize::size(QPageSize::Custom, QPageSize::Millimeter);
0069     m_availableSizesListNames << QPageSize::name(QPageSize::Custom);
0070 
0071     double maxScannerWidth = ensureMilliMeter(m_optionBottomRightX, m_optionBottomRightX->maximumValue().toDouble());
0072     double maxScannerHeight = ensureMilliMeter(m_optionBottomRightY, m_optionBottomRightY->maximumValue().toDouble());
0073 
0074     // Add portrait page sizes
0075     for (const auto sizeCode : possibleSizesList) {
0076         QSizeF size = QPageSize::size(sizeCode, QPageSize::Millimeter);
0077         if (size.width() - PageSizeWiggleRoom > maxScannerWidth) {
0078             continue;
0079         }
0080         if (size.height() - PageSizeWiggleRoom > maxScannerHeight) {
0081             continue;
0082         }
0083         m_availableSizesList << size;
0084         m_availableSizesListNames << QPageSize::name(sizeCode);
0085     }
0086 
0087     // Add landscape page sizes
0088     for (const auto sizeCode : possibleSizesList) {
0089         QSizeF size = QPageSize::size(sizeCode, QPageSize::Millimeter);
0090         size.transpose();
0091         if (size.width() - PageSizeWiggleRoom > maxScannerWidth) {
0092             continue;
0093         }
0094         if (size.height() - PageSizeWiggleRoom > maxScannerHeight) {
0095             continue;
0096         }
0097         m_availableSizesList << size;
0098         m_availableSizesListNames << i18nc("Page size landscape", "Landscape %1", QPageSize::name(sizeCode));
0099     }
0100 
0101     // Set custom as current
0102     m_currentIndex = 0;
0103     if (m_availableSizesList.count() > 1) {
0104         m_state = Option::StateActive;
0105     } else {
0106         m_state = Option::StateHidden;
0107     }
0108     m_optionType = Option::TypeValueList;
0109 }
0110 
0111 bool PageSizeOption::setValue(const QVariant &value)
0112 {
0113 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
0114     if (static_cast<QMetaType::Type>(value.type()) == QMetaType::QString) {
0115 #else
0116     if (value.userType() == QMetaType::QString) {
0117 #endif
0118         QString newValue = value.toString();
0119         if (newValue == m_availableSizesListNames.at(m_currentIndex)) {
0120             return true;
0121         }
0122         for (int i = 0; i < m_availableSizesListNames.size(); i++) {
0123             QString sizeEntry = m_availableSizesListNames.at(i).toString();
0124             if (sizeEntry == newValue) {
0125                 m_currentIndex = i;
0126 
0127                 if (i != 0) {
0128                     const auto size = m_availableSizesList.at(i);
0129                     m_optionTopLeftX->setValue(0);
0130                     m_optionTopLeftY->setValue(0);
0131                     m_optionBottomRightX->setValue(size.width());
0132                     m_optionBottomRightY->setValue(size.height());
0133                 }
0134                 Q_EMIT valueChanged(sizeEntry);
0135                 return true;
0136             }
0137         }
0138     }
0139     return false;
0140 }
0141 
0142 QVariant PageSizeOption::value() const
0143 {
0144     if (m_currentIndex >= 0 && m_currentIndex < m_availableSizesListNames.size()) {
0145         return m_availableSizesListNames.at(m_currentIndex);
0146     } else {
0147         return QVariant();
0148     }
0149 }
0150 
0151 QString PageSizeOption::valueAsString() const
0152 {
0153     if (m_currentIndex >= 0 && m_currentIndex < m_availableSizesListNames.size()) {
0154         return m_availableSizesListNames.at(m_currentIndex).toString();
0155     } else {
0156         return QString();
0157     }
0158 }
0159 
0160 QVariantList PageSizeOption::valueList() const
0161 {
0162     return m_availableSizesListNames;
0163 }
0164 
0165 Option::OptionState PageSizeOption::state() const
0166 {
0167     return m_state;
0168 }
0169 
0170 QString PageSizeOption::name() const
0171 {
0172     return PageSizeOptionName;
0173 }
0174 
0175 QString PageSizeOption::title() const
0176 {
0177     return i18n("Scan area size");
0178 }
0179 
0180 QString PageSizeOption::description() const
0181 {
0182     return i18n("Select a predefined page size for the scanning area.");
0183 }
0184 
0185 void PageSizeOption::optionTopLeftXUpdated()
0186 {
0187     if (m_currentIndex > 0 && m_currentIndex < m_availableSizesList.size() && m_optionTopLeftY->value().toDouble() != 0) {
0188         m_currentIndex = 0;
0189         Q_EMIT valueChanged(QPageSize::name(QPageSize::Custom));
0190     }
0191 }
0192 
0193 void PageSizeOption::optionTopLeftYUpdated()
0194 {
0195     if (m_currentIndex > 0 && m_currentIndex < m_availableSizesList.size() && m_optionTopLeftY->value().toDouble() != 0) {
0196         m_currentIndex = 0;
0197         Q_EMIT valueChanged(QPageSize::name(QPageSize::Custom));
0198     }
0199 }
0200 
0201 void PageSizeOption::optionBottomRightXUpdated()
0202 {
0203     if (m_currentIndex > 0 && m_currentIndex < m_availableSizesList.size()
0204         && ensureMilliMeter(m_optionBottomRightX, m_optionBottomRightX->value().toDouble()) != m_availableSizesList.at(m_currentIndex).width()) {
0205         m_currentIndex = 0;
0206         Q_EMIT valueChanged(QPageSize::name(QPageSize::Custom));
0207     }
0208 }
0209 
0210 void PageSizeOption::optionBottomRightYUpdated()
0211 {
0212     if (m_currentIndex > 0 && m_currentIndex < m_availableSizesList.size()
0213         && ensureMilliMeter(m_optionBottomRightY, m_optionBottomRightY->value().toDouble()) != m_availableSizesList.at(m_currentIndex).height()) {
0214         m_currentIndex = 0;
0215         Q_EMIT valueChanged(QPageSize::name(QPageSize::Custom));
0216     }
0217 }
0218 
0219 double PageSizeOption::ensureMilliMeter(BaseOption *option, double value)
0220 {
0221     // convert if necessary with current DPI if available
0222     if (option->valueUnit() == Option::UnitPixel && m_optionResolution != nullptr) {
0223         double dpi = m_optionResolution->value().toDouble();
0224         if (dpi > 1) {
0225             return value / (dpi / 25.4);
0226         }
0227     }
0228     return value;
0229 }
0230 
0231 } // namespace KSaneCore
0232 
0233 #include "moc_pagesizeoption.cpp"