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