KSaneCore

pagesizeoption.cpp
1/*
2 * SPDX-FileCopyrightText: 2009 Kare Sars <kare dot sars at iki dot fi>
3 * SPDX-FileCopyrightText: 2014 Gregor Mitsch : port to KDE5 frameworks
4 * SPDX-FileCopyrightText: 2021 Alexander Stippich <a.stippich@gmx.net>
5 *
6 * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
7 */
8
9#include "pagesizeoption.h"
10
11#include <QPageSize>
12#include <QSizeF>
13
14#include <ksanecore_debug.h>
15
16static constexpr int PageSizeWiggleRoom = 2; // in mm
17
18namespace KSaneCore
19{
20
21PageSizeOption::PageSizeOption(BaseOption *optionTopLeftX,
22 BaseOption *optionTopLeftY,
23 BaseOption *optionBottomRightX,
24 BaseOption *optionBottomRightY,
25 BaseOption *optionResolution,
26 BaseOption *optionPageWidth,
27 BaseOption *optionPageHeight)
28 : BaseOption()
29{
30 if (optionTopLeftX == nullptr || optionTopLeftY == nullptr || optionBottomRightX == nullptr || optionBottomRightY == nullptr) {
31 m_optionType = Option::TypeDetectFail;
32 return;
33 }
34
35 connect(optionTopLeftX, &BaseOption::valueChanged, this, &PageSizeOption::optionTopLeftXUpdated);
36 connect(optionTopLeftY, &BaseOption::valueChanged, this, &PageSizeOption::optionTopLeftYUpdated);
37 connect(optionBottomRightX, &BaseOption::valueChanged, this, &PageSizeOption::optionBottomRightXUpdated);
38 connect(optionBottomRightY, &BaseOption::valueChanged, this, &PageSizeOption::optionBottomRightYUpdated);
39
40 m_optionTopLeftX = optionTopLeftX;
41 m_optionTopLeftY = optionTopLeftY;
42 m_optionBottomRightX = optionBottomRightX;
43 m_optionBottomRightY = optionBottomRightY;
44 m_optionResolution = optionResolution;
45 m_optionPageWidth = optionPageWidth;
46 m_optionPageHeight = optionPageHeight;
47
48 /* some SANE backends set the maximum value of bottom right X and Y to the current page width and height values
49 * set current values of these option to maximum if available, such that we detect possible page sizes correctly
50 * see https://gitlab.com/sane-project/backends/-/issues/730 and https://bugs.kde.org/show_bug.cgi?id=476838 */
51 if (m_optionPageWidth != nullptr && m_optionPageHeight != nullptr) {
52 m_optionPageHeight->setValue(m_optionPageHeight->maximumValue());
53 m_optionPageWidth->setValue(m_optionPageWidth->maximumValue());
54 }
55
56 const QList<QPageSize::PageSizeId> possibleSizesList = {
78 };
79
81 m_availableSizesListNames << QPageSize::name(QPageSize::Custom);
82
83 double maxScannerWidth = ensureMilliMeter(m_optionBottomRightX, m_optionBottomRightX->maximumValue().toDouble());
84 double maxScannerHeight = ensureMilliMeter(m_optionBottomRightY, m_optionBottomRightY->maximumValue().toDouble());
85
86 // Add portrait page sizes
87 for (const auto sizeCode : possibleSizesList) {
89 if (size.width() - PageSizeWiggleRoom > maxScannerWidth) {
90 continue;
91 }
92 if (size.height() - PageSizeWiggleRoom > maxScannerHeight) {
93 continue;
94 }
95 m_availableSizesList << size;
96 m_availableSizesListNames << QPageSize::name(sizeCode);
97 }
98
99 // Add landscape page sizes
100 for (const auto sizeCode : possibleSizesList) {
102 size.transpose();
103 if (size.width() - PageSizeWiggleRoom > maxScannerWidth) {
104 continue;
105 }
106 if (size.height() - PageSizeWiggleRoom > maxScannerHeight) {
107 continue;
108 }
109 m_availableSizesList << size;
110 m_availableSizesListNames << i18nc("Page size landscape", "Landscape %1", QPageSize::name(sizeCode));
111 }
112
113 // Set custom as current
114 m_currentIndex = 0;
115 if (m_availableSizesList.count() > 1) {
116 m_state = Option::StateActive;
117 } else {
118 m_state = Option::StateHidden;
119 }
120 m_optionType = Option::TypeValueList;
121}
122
123bool PageSizeOption::setValue(const QVariant &value)
124{
125#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
126 if (static_cast<QMetaType::Type>(value.type()) == QMetaType::QString) {
127#else
128 if (value.userType() == QMetaType::QString) {
129#endif
130 QString newValue = value.toString();
131 if (newValue == m_availableSizesListNames.at(m_currentIndex)) {
132 return true;
133 }
134 for (int i = 0; i < m_availableSizesListNames.size(); i++) {
135 QString sizeEntry = m_availableSizesListNames.at(i).toString();
136 if (sizeEntry == newValue) {
137 m_currentIndex = i;
138
139 if (i != 0) {
140 const auto size = m_availableSizesList.at(i);
141 if (m_optionPageWidth != nullptr && m_optionPageHeight != nullptr) {
142 m_optionPageWidth->setValue(size.width());
143 m_optionPageHeight->setValue(size.height());
144 }
145 m_optionTopLeftX->setValue(0);
146 m_optionTopLeftY->setValue(0);
147 m_optionBottomRightX->setValue(size.width());
148 m_optionBottomRightY->setValue(size.height());
149 }
150 Q_EMIT valueChanged(sizeEntry);
151 return true;
152 }
153 }
154 }
155 return false;
156}
157
158QVariant PageSizeOption::value() const
159{
160 if (m_currentIndex >= 0 && m_currentIndex < m_availableSizesListNames.size()) {
161 return m_availableSizesListNames.at(m_currentIndex);
162 } else {
163 return QVariant();
164 }
165}
166
167QString PageSizeOption::valueAsString() const
168{
169 if (m_currentIndex >= 0 && m_currentIndex < m_availableSizesListNames.size()) {
170 return m_availableSizesListNames.at(m_currentIndex).toString();
171 } else {
172 return QString();
173 }
174}
175
176QVariantList PageSizeOption::valueList() const
177{
178 return m_availableSizesListNames;
179}
180
181Option::OptionState PageSizeOption::state() const
182{
183 return m_state;
184}
185
186QString PageSizeOption::name() const
187{
188 return PageSizeOptionName;
189}
190
191QString PageSizeOption::title() const
192{
193 return i18n("Scan area size");
194}
195
196QString PageSizeOption::description() const
197{
198 return i18n("Select a predefined page size for the scanning area.");
199}
200
201void PageSizeOption::optionTopLeftXUpdated()
202{
203 if (m_currentIndex > 0 && m_currentIndex < m_availableSizesList.size() && m_optionTopLeftY->value().toDouble() != 0) {
204 m_currentIndex = 0;
205 Q_EMIT valueChanged(QPageSize::name(QPageSize::Custom));
206 }
207}
208
209void PageSizeOption::optionTopLeftYUpdated()
210{
211 if (m_currentIndex > 0 && m_currentIndex < m_availableSizesList.size() && m_optionTopLeftY->value().toDouble() != 0) {
212 m_currentIndex = 0;
213 Q_EMIT valueChanged(QPageSize::name(QPageSize::Custom));
214 }
215}
216
217void PageSizeOption::optionBottomRightXUpdated()
218{
219 if (m_currentIndex > 0 && m_currentIndex < m_availableSizesList.size()
220 && ensureMilliMeter(m_optionBottomRightX, m_optionBottomRightX->value().toDouble()) != m_availableSizesList.at(m_currentIndex).width()) {
221 m_currentIndex = 0;
222 Q_EMIT valueChanged(QPageSize::name(QPageSize::Custom));
223 }
224}
225
226void PageSizeOption::optionBottomRightYUpdated()
227{
228 if (m_currentIndex > 0 && m_currentIndex < m_availableSizesList.size()
229 && ensureMilliMeter(m_optionBottomRightY, m_optionBottomRightY->value().toDouble()) != m_availableSizesList.at(m_currentIndex).height()) {
230 m_currentIndex = 0;
231 Q_EMIT valueChanged(QPageSize::name(QPageSize::Custom));
232 }
233}
234
235double PageSizeOption::ensureMilliMeter(BaseOption *option, double value)
236{
237 // convert if necessary with current DPI if available
238 if (option->valueUnit() == Option::UnitPixel && m_optionResolution != nullptr) {
239 double dpi = m_optionResolution->value().toDouble();
240 if (dpi > 1) {
241 return value / (dpi / 25.4);
242 }
243 }
244 return value;
245}
246
247} // namespace KSaneCore
248
249#include "moc_pagesizeoption.cpp"
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
QString name() const const
QSizeF size(PageSizeId pageSizeId, Unit units)
qreal height() const const
void transpose()
qreal width() const const
const QChar at(qsizetype position) const const
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
Type type() const const
QString toString() const const
int userType() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 18 2024 12:17:19 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.