KSaneCore

baseoption.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 "baseoption.h"
9
10#include <ksanecore_debug.h>
11
12namespace KSaneCore
13{
14
15BaseOption::BaseOption() : QObject()
16{
17}
18
19BaseOption::BaseOption(const SANE_Handle handle, const int index)
20 : QObject(), m_handle(handle), m_index(index)
21{
22}
23
24BaseOption::~BaseOption()
25{
26 if (m_data) {
27 free(m_data);
28 m_data = nullptr;
29 }
30}
31
32void BaseOption::readOption()
33{
34 beginOptionReload();
35 endOptionReload();
36}
37
38void BaseOption::beginOptionReload()
39{
40 if (m_handle != nullptr) {
41 m_optDesc = sane_get_option_descriptor(m_handle, m_index);
42 }
43}
44
45void BaseOption::endOptionReload()
46{
47 Q_EMIT optionReloaded();
48}
49
50Option::OptionState BaseOption::state() const
51{
52 if (m_optDesc == nullptr) {
53 return Option::StateHidden;
54 }
55
56 if (((m_optDesc->cap & SANE_CAP_SOFT_DETECT) == 0) || (m_optDesc->cap & SANE_CAP_INACTIVE) || ((m_optDesc->size == 0) && (type() != Option::TypeAction))) {
57 return Option::StateHidden;
58 } else if ((m_optDesc->cap & SANE_CAP_SOFT_SELECT) == 0) {
59 return Option::StateDisabled;
60 }
61 return Option::StateActive;
62}
63
64bool BaseOption::needsPolling() const
65{
66 if (!m_optDesc) {
67 return false;
68 }
69
70 if ((m_optDesc->cap & SANE_CAP_SOFT_DETECT) && !(m_optDesc->cap & SANE_CAP_SOFT_SELECT)) {
71 qCDebug(KSANECORE_LOG) << name() << "optDesc->cap =" << m_optDesc->cap;
72 return true;
73 }
74
75 return false;
76}
77
78QString BaseOption::name() const
79{
80 if (m_optDesc == nullptr) {
81 return QString();
82 }
83 return QString::fromUtf8(m_optDesc->name);
84}
85
86QString BaseOption::title() const
87{
88 if (m_optDesc == nullptr) {
89 return QString();
90 }
91 return sane_i18n(m_optDesc->title);
92}
93
94QString BaseOption::description() const
95{
96 if (m_optDesc == nullptr) {
97 return QString();
98 }
99 return sane_i18n(m_optDesc->desc);
100}
101
102Option::OptionType BaseOption::type() const
103{
104 return m_optionType;
105}
106
107bool BaseOption::writeData(void *data)
108{
109 SANE_Status status;
110 SANE_Int res;
111
112 if (state() == Option::StateDisabled) {
113 return false;
114 }
115
116 status = sane_control_option(m_handle, m_index, SANE_ACTION_SET_VALUE, data, &res);
117 if (status != SANE_STATUS_GOOD) {
118 qCDebug(KSANECORE_LOG) << m_optDesc->name << "sane_control_option returned:" << sane_strstatus(status);
119 // write failed. re read the current setting
120 readValue();
121 return false;
122 }
123 if (res & SANE_INFO_INEXACT) {
124 //qCDebug(KSANECORE_LOG) << "write was inexact. Reload value just in case...";
125 readValue();
126 }
127
128 if (res & SANE_INFO_RELOAD_OPTIONS) {
129 Q_EMIT optionsNeedReload();
130 // optReload reloads also the values
131 } else if (res & SANE_INFO_RELOAD_PARAMS) {
132 // 'else if' because with optReload we force also valReload :)
133 Q_EMIT valuesNeedReload();
134 }
135
136 return true;
137}
138
139void BaseOption::readValue() {}
140
141SANE_Word BaseOption::toSANE_Word(unsigned char *data)
142{
143 SANE_Word tmp;
144 // if __BYTE_ORDER is not defined we get #if 0 == 0
145#if __BYTE_ORDER == __LITTLE_ENDIAN
146 tmp = (data[0] & 0xff);
147 tmp += ((SANE_Word)(data[1] & 0xff)) << 8;
148 tmp += ((SANE_Word)(data[2] & 0xff)) << 16;
149 tmp += ((SANE_Word)(data[3] & 0xff)) << 24;
150#else
151 tmp = (data[3] & 0xff);
152 tmp += ((SANE_Word)(data[2] & 0xff)) << 8;
153 tmp += ((SANE_Word)(data[1] & 0xff)) << 16;
154 tmp += ((SANE_Word)(data[0] & 0xff)) << 24;
155#endif
156 return tmp;
157}
158
159void BaseOption::fromSANE_Word(unsigned char *data, SANE_Word from)
160{
161 // if __BYTE_ORDER is not defined we get #if 0 == 0
162#if __BYTE_ORDER == __LITTLE_ENDIAN
163 data[0] = (from & 0x000000FF);
164 data[1] = (from & 0x0000FF00) >> 8;
165 data[2] = (from & 0x00FF0000) >> 16;
166 data[3] = (from & 0xFF000000) >> 24;
167#else
168 data[3] = (from & 0x000000FF);
169 data[2] = (from & 0x0000FF00) >> 8;
170 data[1] = (from & 0x00FF0000) >> 16;
171 data[0] = (from & 0xFF000000) >> 24;
172#endif
173}
174
175QVariant BaseOption::value() const
176{
177 return QVariant();
178}
179
180QVariant BaseOption::minimumValue() const
181{
182 return QVariant();
183}
184
185QVariant BaseOption::maximumValue() const
186{
187 return QVariant();
188}
189
190QVariant BaseOption::stepValue() const
191{
192 return QVariant();
193}
194
195QVariantList BaseOption::valueList() const
196{
197 return QVariantList();
198}
199
200QVariantList BaseOption::internalValueList() const
201{
202 return QVariantList();
203}
204
205Option::OptionUnit BaseOption::valueUnit() const
206{
207 if (m_optDesc != nullptr) {
208 switch (m_optDesc->unit) {
209 case SANE_UNIT_PIXEL:
210 return Option::UnitPixel;
211 case SANE_UNIT_BIT:
212 return Option::UnitBit;
213 case SANE_UNIT_MM:
214 return Option::UnitMilliMeter;
215 case SANE_UNIT_DPI:
216 return Option::UnitDPI;
217 case SANE_UNIT_PERCENT:
218 return Option::UnitPercent;
219 case SANE_UNIT_MICROSECOND:
220 return Option::UnitMicroSecond;
221 default:
222 return Option::UnitNone;
223 }
224 } else {
225 return Option::UnitNone;
226 }
227}
228
229int BaseOption::valueSize() const
230{
231 if (m_optDesc != nullptr) {
232 return m_optDesc->size / sizeof(SANE_Word);
233 }
234 return 0;
235}
236
237QString BaseOption::valueAsString() const
238{
239 return QString();
240}
241
242bool BaseOption::setValue(const QVariant &)
243{
244 return false;
245}
246
247bool BaseOption::storeCurrentData()
248{
249 SANE_Status status;
250 SANE_Int res;
251
252 // check if we can read the value
253 if (state() == Option::StateHidden) {
254 return false;
255 }
256
257 // read that current value
258 if (m_data != nullptr) {
259 free(m_data);
260 }
261 m_data = (unsigned char *)malloc(m_optDesc->size);
262 status = sane_control_option(m_handle, m_index, SANE_ACTION_GET_VALUE, m_data, &res);
263 if (status != SANE_STATUS_GOOD) {
264 qCDebug(KSANECORE_LOG) << m_optDesc->name << "sane_control_option returned" << status;
265 return false;
266 }
267 return true;
268}
269
270bool BaseOption::restoreSavedData()
271{
272 // check if we have saved any data
273 if (m_data == nullptr) {
274 return false;
275 }
276
277 // check if we can write the value
278 if (state() == Option::StateHidden) {
279 return false;
280 }
281 if (state() == Option::StateDisabled) {
282 return false;
283 }
284
285 writeData(m_data);
286 readValue();
287 return true;
288}
289
290Option::OptionType BaseOption::optionType(const SANE_Option_Descriptor *optDesc)
291{
292 if (!optDesc) {
293 return Option::TypeDetectFail;
294 }
295
296 switch (optDesc->constraint_type) {
297 case SANE_CONSTRAINT_NONE:
298 switch (optDesc->type) {
299 case SANE_TYPE_BOOL:
300 return Option::TypeBool;
301 case SANE_TYPE_INT:
302 if (optDesc->size == sizeof(SANE_Word)) {
303 return Option::TypeInteger;
304 }
305 qCDebug(KSANECORE_LOG) << "Can not handle:" << optDesc->title;
306 qCDebug(KSANECORE_LOG) << "SANE_CONSTRAINT_NONE && SANE_TYPE_INT";
307 qCDebug(KSANECORE_LOG) << "size" << optDesc->size << "!= sizeof(SANE_Word)";
308 break;
309 case SANE_TYPE_FIXED:
310 if (optDesc->size == sizeof(SANE_Word)) {
311 return Option::TypeDouble;
312 }
313 qCDebug(KSANECORE_LOG) << "Can not handle:" << optDesc->title;
314 qCDebug(KSANECORE_LOG) << "SANE_CONSTRAINT_NONE && SANE_TYPE_FIXED";
315 qCDebug(KSANECORE_LOG) << "size" << optDesc->size << "!= sizeof(SANE_Word)";
316 break;
317 case SANE_TYPE_BUTTON:
318 return Option::TypeAction;
319 case SANE_TYPE_STRING:
320 return Option::TypeString;
321 case SANE_TYPE_GROUP:
322 return Option::TypeDetectFail;
323 }
324 break;
325 case SANE_CONSTRAINT_RANGE:
326 switch (optDesc->type) {
327 case SANE_TYPE_BOOL:
328 return Option::TypeBool;
329 case SANE_TYPE_INT:
330 if (optDesc->size == sizeof(SANE_Word)) {
331 return Option::TypeInteger;
332 }
333
334 if ((strcmp(optDesc->name, SANE_NAME_GAMMA_VECTOR) == 0) ||
335 (strcmp(optDesc->name, SANE_NAME_GAMMA_VECTOR_R) == 0) ||
336 (strcmp(optDesc->name, SANE_NAME_GAMMA_VECTOR_G) == 0) ||
337 (strcmp(optDesc->name, SANE_NAME_GAMMA_VECTOR_B) == 0)) {
338 return Option::TypeGamma;
339 }
340 qCDebug(KSANECORE_LOG) << "Can not handle:" << optDesc->title;
341 qCDebug(KSANECORE_LOG) << "SANE_CONSTRAINT_RANGE && SANE_TYPE_INT && !SANE_NAME_GAMMA_VECTOR...";
342 qCDebug(KSANECORE_LOG) << "size" << optDesc->size << "!= sizeof(SANE_Word)";
343 break;
344 case SANE_TYPE_FIXED:
345 if (optDesc->size == sizeof(SANE_Word)) {
346 return Option::TypeDouble;
347 }
348 qCDebug(KSANECORE_LOG) << "Can not handle:" << optDesc->title;
349 qCDebug(KSANECORE_LOG) << "SANE_CONSTRAINT_RANGE && SANE_TYPE_FIXED";
350 qCDebug(KSANECORE_LOG) << "size" << optDesc->size << "!= sizeof(SANE_Word)";
351 qCDebug(KSANECORE_LOG) << "Analog Gamma vector?";
352 break;
353 case SANE_TYPE_STRING:
354 qCDebug(KSANECORE_LOG) << "Can not handle:" << optDesc->title;
355 qCDebug(KSANECORE_LOG) << "SANE_CONSTRAINT_RANGE && SANE_TYPE_STRING";
356 return Option::TypeDetectFail;
357 case SANE_TYPE_BUTTON:
358 return Option::TypeAction;
359 case SANE_TYPE_GROUP:
360 return Option::TypeDetectFail;
361 }
362 break;
363 case SANE_CONSTRAINT_WORD_LIST:
364 case SANE_CONSTRAINT_STRING_LIST:
365 return Option::TypeValueList;
366 }
367 return Option::TypeDetectFail;
368}
369
370} // namespace KSaneCore
371
372#include "moc_baseoption.cpp"
Q_SCRIPTABLE CaptureState status()
Type type(const QSqlDatabase &db)
QString name(StandardAction id)
QString fromUtf8(QByteArrayView str)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri May 24 2024 11:49:00 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.