1 /* ============================================================
2 *
3 * SPDX-FileCopyrightText: 2009 Kare Sars <kare dot sars at iki dot fi>
4 * SPDX-FileCopyrightText: 2014 Gregor Mitsch : port to KDE5 frameworks
5 * SPDX-FileCopyrightText: 2021 Alexander Stippich <a.stippich@gmx.net>
6 *
7 * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
8 *
9 * ============================================================ */
10
11 #include "ksanepagesizeoption.h"
12
13 #include <QPageSize>
14 #include <QSizeF>
15
16 #include <ksane_debug.h>
17
18 static constexpr int PageSizeWiggleRoom = 2; // in mm
19
20 namespace KSaneIface
21 {
22
KSanePageSizeOption(KSaneBaseOption * optionTopLeftX,KSaneBaseOption * optionTopLeftY,KSaneBaseOption * optionBottomRightX,KSaneBaseOption * optionBottomRightY,KSaneBaseOption * optionResolution)23 KSanePageSizeOption::KSanePageSizeOption(KSaneBaseOption *optionTopLeftX, KSaneBaseOption *optionTopLeftY,
24 KSaneBaseOption *optionBottomRightX, KSaneBaseOption *optionBottomRightY,
25 KSaneBaseOption *optionResolution) : KSaneBaseOption()
26 {
27 if (optionTopLeftX == nullptr || optionTopLeftY == nullptr ||
28 optionBottomRightX == nullptr || optionBottomRightY == nullptr) {
29
30 m_optionType = KSaneOption::TypeDetectFail;
31 return;
32 }
33
34 connect(optionTopLeftX, &KSaneBaseOption::valueChanged, this, &KSanePageSizeOption::optionTopLeftXUpdated);
35 connect(optionTopLeftY, &KSaneBaseOption::valueChanged, this, &KSanePageSizeOption::optionTopLeftYUpdated);
36 connect(optionBottomRightX, &KSaneBaseOption::valueChanged, this, &KSanePageSizeOption::optionBottomRightXUpdated);
37 connect(optionBottomRightY, &KSaneBaseOption::valueChanged, this, &KSanePageSizeOption::optionBottomRightYUpdated);
38
39 m_optionTopLeftX = optionTopLeftX;
40 m_optionTopLeftY = optionTopLeftY;
41 m_optionBottomRightX = optionBottomRightX;
42 m_optionBottomRightY = optionBottomRightY;
43 m_optionResolution = optionResolution;
44
45 const QList<QPageSize::PageSizeId> possibleSizesList = {
46 QPageSize::A3,
47 QPageSize::A4,
48 QPageSize::A5,
49 QPageSize::A6,
50 QPageSize::Letter,
51 QPageSize::Legal,
52 QPageSize::Tabloid,
53 QPageSize::B3,
54 QPageSize::B4,
55 QPageSize::B5,
56 QPageSize::B6,
57 QPageSize::C5E,
58 QPageSize::Comm10E,
59 QPageSize::DLE,
60 QPageSize::Executive,
61 QPageSize::Folio,
62 QPageSize::Ledger,
63 QPageSize::JisB3,
64 QPageSize::JisB4,
65 QPageSize::JisB5,
66 QPageSize::JisB6,
67 };
68
69 m_availableSizesList << QPageSize::size(QPageSize::Custom, QPageSize::Millimeter);
70 m_availableSizesListNames << QPageSize::name(QPageSize::Custom);
71
72 double maxScannerWidth = ensureMilliMeter(m_optionBottomRightX, m_optionBottomRightX->maximumValue().toDouble());
73 double maxScannerHeight = ensureMilliMeter(m_optionBottomRightY, m_optionBottomRightY->maximumValue().toDouble());
74
75 // Add portrait page sizes
76 for (const auto sizeCode : possibleSizesList) {
77 QSizeF size = QPageSize::size(sizeCode, QPageSize::Millimeter);
78 if (size.width() - PageSizeWiggleRoom > maxScannerWidth) {
79 continue;
80 }
81 if (size.height() - PageSizeWiggleRoom > maxScannerHeight) {
82 continue;
83 }
84 m_availableSizesList << size;
85 m_availableSizesListNames << QPageSize::name(sizeCode);
86 }
87
88 // Add landscape page sizes
89 for (const auto sizeCode : possibleSizesList) {
90 QSizeF size = QPageSize::size(sizeCode, QPageSize::Millimeter);
91 size.transpose();
92 if (size.width() - PageSizeWiggleRoom > maxScannerWidth) {
93 continue;
94 }
95 if (size.height() - PageSizeWiggleRoom > maxScannerHeight) {
96 continue;
97 }
98 m_availableSizesList << size;
99 m_availableSizesListNames << i18nc("Page size landscape", "Landscape %1", QPageSize::name(sizeCode));
100 }
101
102 // Set custom as current
103 m_currentIndex = 0;
104 if (m_availableSizesList.count() > 1) {
105 m_state = KSaneOption::StateActive;
106 } else {
107 m_state = KSaneOption::StateHidden;
108 }
109 m_optionType = KSaneOption::TypeValueList;
110 }
111
setValue(const QVariant & value)112 bool KSanePageSizeOption::setValue(const QVariant &value)
113 {
114 if (static_cast<QMetaType::Type>(value.type()) == QMetaType::QString) {
115 QString newValue = value.toString();
116 if (newValue == m_availableSizesListNames.at(m_currentIndex)) {
117 return true;
118 }
119 for (int i = 0; i < m_availableSizesListNames.size(); i++) {
120 QString sizeEntry = m_availableSizesListNames.at(i).toString();
121 if (sizeEntry == newValue) {
122 m_currentIndex = i;
123
124 if (i != 0) {
125 const auto size = m_availableSizesList.at(i);
126 m_optionTopLeftX->setValue(0);
127 m_optionTopLeftY->setValue(0);
128 m_optionBottomRightX->setValue(size.width());
129 m_optionBottomRightY->setValue(size.height());
130 }
131 Q_EMIT valueChanged(sizeEntry);
132 return true;
133 }
134 }
135 }
136 return false;
137 }
138
value() const139 QVariant KSanePageSizeOption::value() const
140 {
141 if (m_currentIndex >= 0 && m_currentIndex < m_availableSizesListNames.size()) {
142 return m_availableSizesListNames.at(m_currentIndex);
143 } else {
144 return QVariant();
145 }
146 }
147
valueAsString() const148 QString KSanePageSizeOption::valueAsString() const
149 {
150 if (m_currentIndex >= 0 && m_currentIndex < m_availableSizesListNames.size()) {
151 return m_availableSizesListNames.at(m_currentIndex).toString();
152 } else {
153 return QString();
154 }
155 }
156
valueList() const157 QVariantList KSanePageSizeOption::valueList() const
158 {
159 return m_availableSizesListNames;
160 }
161
state() const162 KSaneOption::KSaneOptionState KSanePageSizeOption::state() const
163 {
164 return m_state;
165 }
166
name() const167 QString KSanePageSizeOption::name() const
168 {
169 return PageSizeOptionName;
170 }
171
title() const172 QString KSanePageSizeOption::title() const
173 {
174 return i18n("Scan area size");
175 }
176
description() const177 QString KSanePageSizeOption::description() const
178 {
179 return i18n("Select a predefined page size for the scanning area.");
180 }
181
optionTopLeftXUpdated()182 void KSanePageSizeOption::optionTopLeftXUpdated()
183 {
184 if (m_currentIndex > 0 && m_currentIndex < m_availableSizesList.size()
185 && m_optionTopLeftY->value().toDouble() != 0 ) {
186 m_currentIndex = 0;
187 Q_EMIT valueChanged(QPageSize::name(QPageSize::Custom));
188 }
189 }
190
optionTopLeftYUpdated()191 void KSanePageSizeOption::optionTopLeftYUpdated()
192 {
193 if (m_currentIndex > 0 && m_currentIndex < m_availableSizesList.size()
194 && m_optionTopLeftY->value().toDouble() != 0 ) {
195 m_currentIndex = 0;
196 Q_EMIT valueChanged(QPageSize::name(QPageSize::Custom));
197 }
198 }
199
optionBottomRightXUpdated()200 void KSanePageSizeOption::optionBottomRightXUpdated()
201 {
202 if (m_currentIndex > 0 && m_currentIndex < m_availableSizesList.size()
203 && ensureMilliMeter(m_optionBottomRightX, m_optionBottomRightX->value().toDouble())!= m_availableSizesList.at(m_currentIndex).width() ) {
204 m_currentIndex = 0;
205 Q_EMIT valueChanged(QPageSize::name(QPageSize::Custom));
206 }
207 }
208
optionBottomRightYUpdated()209 void KSanePageSizeOption::optionBottomRightYUpdated()
210 {
211 if (m_currentIndex > 0 && m_currentIndex < m_availableSizesList.size()
212 && ensureMilliMeter(m_optionBottomRightY, m_optionBottomRightY->value().toDouble()) != m_availableSizesList.at(m_currentIndex).height() ) {
213 m_currentIndex = 0;
214 Q_EMIT valueChanged(QPageSize::name(QPageSize::Custom));
215 }
216 }
217
ensureMilliMeter(KSaneBaseOption * option,double value)218 double KSanePageSizeOption::ensureMilliMeter(KSaneBaseOption *option, double value)
219 {
220 // convert if necessary with current DPI if available
221 if (option->valueUnit() == KSaneOption::UnitPixel && m_optionResolution != nullptr) {
222 double dpi = m_optionResolution->value().toDouble();
223 if (dpi > 1) {
224 return value / (dpi / 25.4);
225 }
226 }
227 return value;
228 }
229
230 } // NameSpace KSaneIface
231