KSaneCore

listoption.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 *
5 * SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
6 */
7
8#include "listoption.h"
9
10#include <QVarLengthArray>
11
12#include <ksanecore_debug.h>
13
14namespace KSaneCore
15{
16
17ListOption::ListOption(const SANE_Handle handle, const int index)
18 : BaseOption(handle, index)
19{
20 m_optionType = Option::TypeValueList;
21}
22
23void ListOption::readValue()
24{
25 if (BaseOption::state() == Option::StateHidden) {
26 return;
27 }
28
29 // read that current value
30 QVarLengthArray<unsigned char> data(m_optDesc->size);
31 SANE_Status status;
32 SANE_Int res;
33 status = sane_control_option(m_handle, m_index, SANE_ACTION_GET_VALUE, data.data(), &res);
34 if (status != SANE_STATUS_GOOD) {
35 return;
36 }
37
38 QVariant newValue;
39 switch (m_optDesc->type) {
40 case SANE_TYPE_INT:
41 newValue = static_cast<int>(toSANE_Word(data.data()));
42 break;
43 case SANE_TYPE_FIXED:
44 newValue = SANE_UNFIX(toSANE_Word(data.data()));
45 break;
46 case SANE_TYPE_STRING:
47 newValue = sane_i18n(reinterpret_cast<char *>(data.data()));
48 break;
49 default:
50 break;
51 }
52
53 if (newValue != m_currentValue) {
54 m_currentValue = newValue;
55 Q_EMIT valueChanged(m_currentValue);
56 }
57}
58
59void ListOption::readOption()
60{
61 beginOptionReload();
62 countEntries();
63 endOptionReload();
64}
65
66QVariantList ListOption::valueList() const
67{
68 int i;
69 QVariantList list;
70 list.reserve(m_entriesCount);
71
72 switch (m_optDesc->type) {
73 case SANE_TYPE_INT:
74 for (i = 1; i <= m_optDesc->constraint.word_list[0]; ++i) {
75 list << static_cast<int>(m_optDesc->constraint.word_list[i]);;
76 }
77 break;
78 case SANE_TYPE_FIXED:
79 for (i = 1; i <= m_optDesc->constraint.word_list[0]; ++i) {
80 list << SANE_UNFIX(m_optDesc->constraint.word_list[i]);
81 }
82 break;
83 case SANE_TYPE_STRING:
84 i = 0;
85 while (m_optDesc->constraint.string_list[i] != nullptr) {
86 list << sane_i18n(m_optDesc->constraint.string_list[i]);
87 i++;
88 }
89 break;
90 default :
91 qCDebug(KSANECORE_LOG) << "can not handle type:" << m_optDesc->type;
92 break;
93 }
94 return list;
95}
96
97QVariantList ListOption::internalValueList() const
98{
99 int i;
100 QVariantList list;
101 list.reserve(m_entriesCount);
102
103 switch (m_optDesc->type) {
104 case SANE_TYPE_INT:
105 for (i = 1; i <= m_optDesc->constraint.word_list[0]; ++i) {
106 list << static_cast<int>(m_optDesc->constraint.word_list[i]);;
107 }
108 break;
109 case SANE_TYPE_FIXED:
110 for (i = 1; i <= m_optDesc->constraint.word_list[0]; ++i) {
111 list << SANE_UNFIX(m_optDesc->constraint.word_list[i]);
112 }
113 break;
114 case SANE_TYPE_STRING:
115 i = 0;
116 while (m_optDesc->constraint.string_list[i] != nullptr) {
117 list << QString::fromLatin1(m_optDesc->constraint.string_list[i]);
118 i++;
119 }
120 break;
121 default :
122 qCDebug(KSANECORE_LOG) << "can not handle type:" << m_optDesc->type;
123 break;
124 }
125 return list;
126}
127
128bool ListOption::setValue(const QVariant &value)
129{
130 bool success = false;
131#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
132 if (static_cast<QMetaType::Type>(value.type()) == QMetaType::QString) {
133#else
134 if (value.userType() == QMetaType::QString) {
135#endif
136 success = setValue(value.toString());
137 } else {
138 success = setValue(value.toDouble());
139 }
140
141 return success;
142}
143
144QVariant ListOption::minimumValue() const
145{
146 QVariant value;
147 if (BaseOption::state() == Option::StateHidden) {
148 return value;
149 }
150 double dValueMin;
151 int iValueMin;
152 switch (m_optDesc->type) {
153 case SANE_TYPE_INT:
154 iValueMin = static_cast<int>(m_optDesc->constraint.word_list[1]);
155 for (int i = 2; i <= m_optDesc->constraint.word_list[0]; i++) {
156 iValueMin = qMin(static_cast<int>(m_optDesc->constraint.word_list[i]), iValueMin);
157 }
158 value = iValueMin;
159 break;
160 case SANE_TYPE_FIXED:
161 dValueMin = SANE_UNFIX(m_optDesc->constraint.word_list[1]);
162 for (int i = 2; i <= m_optDesc->constraint.word_list[0]; i++) {
163 dValueMin = qMin(SANE_UNFIX(m_optDesc->constraint.word_list[i]), dValueMin);
164 }
165 value = dValueMin;
166 break;
167 default:
168 qCDebug(KSANECORE_LOG) << "can not handle type:" << m_optDesc->type;
169 return value;
170 }
171 return value;
172}
173
174QVariant ListOption::value() const
175{
176 if (BaseOption::state() == Option::StateHidden) {
177 return QVariant();
178 }
179 return m_currentValue;
180}
181
182bool ListOption::setValue(double value)
183{
184 unsigned char data[4];
185 double tmp;
186 double minDiff;
187 int i;
188 int minIndex = 1;
189
190 switch (m_optDesc->type) {
191 case SANE_TYPE_INT:
192 tmp = static_cast<double>(m_optDesc->constraint.word_list[minIndex]);
193 minDiff = qAbs(value - tmp);
194 for (i = 2; i <= m_optDesc->constraint.word_list[0]; ++i) {
195 tmp = static_cast<double>(m_optDesc->constraint.word_list[i]);
196 if (qAbs(value - tmp) < minDiff) {
197 minDiff = qAbs(value - tmp);
198 minIndex = i;
199 }
200 }
201 fromSANE_Word(data, m_optDesc->constraint.word_list[minIndex]);
202 writeData(data);
203 readValue();
204 return (minDiff < 1.0);
205 case SANE_TYPE_FIXED:
206 tmp = SANE_UNFIX(m_optDesc->constraint.word_list[minIndex]);
207 minDiff = qAbs(value - tmp);
208 for (i = 2; i <= m_optDesc->constraint.word_list[0]; ++i) {
209 tmp = SANE_UNFIX(m_optDesc->constraint.word_list[i]);
210 if (qAbs(value - tmp) < minDiff) {
211 minDiff = qAbs(value - tmp);
212 minIndex = i;
213 }
214 }
215 fromSANE_Word(data, m_optDesc->constraint.word_list[minIndex]);
216 writeData(data);
217 readValue();
218 return (minDiff < 1.0);
219 default:
220 qCDebug(KSANECORE_LOG) << "can not handle type:" << m_optDesc->type;
221 break;
222 }
223 return false;
224}
225
226QString ListOption::valueAsString() const
227{
228 if (BaseOption::state() == Option::StateHidden) {
229 return QString();
230 }
231 return m_currentValue.toString();
232}
233
234bool ListOption::setValue(const QString &value)
235{
236 if (BaseOption::state() == Option::StateHidden) {
237 return false;
238 }
239
240 unsigned char data[4];
241 void* data_ptr = nullptr;
242 SANE_Word fixed;
243 int i;
244 double d;
245 bool ok;
246 QString tmp;
247
248 switch (m_optDesc->type) {
249 case SANE_TYPE_INT:
250 i = value.toInt(&ok);
251 if (ok) {
252 fromSANE_Word(data, i);
253 data_ptr = data;
254 } else {
255 return false;
256 }
257
258 break;
259 case SANE_TYPE_FIXED:
260 d = value.toDouble(&ok);
261 if (ok) {
262 fixed = SANE_FIX(d);
263 fromSANE_Word(data, fixed);
264 data_ptr = data;
265 } else {
266 return false;
267 }
268
269 break;
270 case SANE_TYPE_STRING:
271 i = 0;
272 while (m_optDesc->constraint.string_list[i] != nullptr) {
273 tmp = QString::fromLatin1(m_optDesc->constraint.string_list[i]);
274 if (value != tmp) {
275 tmp = sane_i18n(m_optDesc->constraint.string_list[i]);
276 }
277 if (value == tmp) {
278 data_ptr = (void *)m_optDesc->constraint.string_list[i];
279 break;
280 }
281 i++;
282 }
283 if (m_optDesc->constraint.string_list[i] == nullptr) {
284 return false;
285 }
286 break;
287 default:
288 qCDebug(KSANECORE_LOG) << "can only handle SANE_TYPE: INT, FIXED and STRING";
289 return false;
290 }
291 writeData(data_ptr);
292
293 readValue();
294 return true;
295}
296
297void ListOption::countEntries()
298{
299 m_entriesCount = 0;
300
301 switch (m_optDesc->type) {
302
303 case SANE_TYPE_INT:
304 case SANE_TYPE_FIXED:
305 m_entriesCount = m_optDesc->constraint.word_list[0];
306 break;
307
308 case SANE_TYPE_STRING:
309 while (m_optDesc->constraint.string_list[m_entriesCount] != nullptr) {
310 m_entriesCount++;
311 }
312 break;
313
314 default :
315 qCDebug(KSANECORE_LOG) << "can not handle type:" << m_optDesc->type;
316 break;
317 }
318}
319
320Option::OptionState ListOption::state() const
321{
322 if (m_entriesCount <= 1) {
323 return Option::StateHidden;
324 } else {
325 return BaseOption::state();
326 }
327}
328
329} // namespace KSaneCore
330
331#include "moc_listoption.cpp"
Q_SCRIPTABLE CaptureState status()
KIOCORE_EXPORT QStringList list(const QString &fileClass)
void reserve(qsizetype size)
QString fromLatin1(QByteArrayView str)
double toDouble(bool *ok) const const
int toInt(bool *ok, int base) const const
QTextStream & fixed(QTextStream &stream)
Type type() const const
double toDouble(bool *ok) 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 Tue Mar 26 2024 11:19:34 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.