1 /* This file is part of the KDE Project         -*- mode:c++; -*-
2    Copyright (C) 1999 Klaas Freitag <freitag@suse.de>
3 
4    This library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Library General Public
6    License as published by the Free Software Foundation; either
7    version 2 of the License, or (at your option) any later version.
8 
9    This library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Library General Public License for more details.
13 
14    You should have received a copy of the GNU Library General Public License
15    along with this library; see the file COPYING.LIB.  If not, write to
16    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17    Boston, MA 02110-1301, USA.
18 */
19 
20 #ifndef KSCANDEVICE_H
21 #define KSCANDEVICE_H
22 
23 #include "kookascan_export.h"
24 
25 #include <qobject.h>
26 #include <qbytearray.h>
27 #include <qimage.h>
28 #include <qlist.h>
29 #include <qhash.h>
30 #include <qmap.h>
31 
32 #include <kconfigskeleton.h>
33 
34 extern "C" {
35 #include <sane/sane.h>
36 }
37 
38 class QWidget;
39 class QSocketNotifier;
40 
41 class KConfigSkeletonItem;
42 
43 class KScanOption;
44 class KScanOptSet;
45 class ImageMetaInfo;
46 
47 /**
48  * @short Access and control a scanner.
49  *
50  * After constructing a @c KScanDevice, a scanner may be opened
51  * via @c openDevice() by specifying its SANE backend name.  Having
52  * done so, the scanner options supported by the scanner may be set
53  * and read individually using a @c KScanOption.
54  *
55  * A scan or preview may be initiated, once the scan is finished the
56  * scanned image data is made available via a signal.
57  *
58  * The scan device may be closed (using @c closeDevice()) and opened
59  * again to change the scanner that is accessed.
60  *
61  * @author Klaas Freitag
62  * @author Jonathan Marten
63  **/
64 
65 class KOOKASCAN_EXPORT KScanDevice : public QObject
66 {
67     Q_OBJECT
68 
69 public:
70 
71     /**
72      * Scanning/control status.
73      **/
74     enum Status {
75         Ok,
76         NoDevice,
77         ParamError,
78         OpenDevice,
79         ControlError,
80         ScanError,
81         EmptyPic,
82         NoMemory,
83         Reload,
84         Cancelled,
85         OptionNotActive,
86         NotSupported
87     };
88 
89     /**
90      * Construct a new scanner device object.
91      *
92      * @param parent The parent object
93      **/
94     explicit KScanDevice(QObject *parent);
95 
96     /**
97      * Destructor.
98      **/
99     ~KScanDevice();
100 
101     /**
102      * Open a scanner device.
103      *
104      * @param backend SANE name of the backend to open
105      * @return The status of the operation
106      *
107      * @note This operation may prompt for SANE authentication if
108      * it is required.
109      **/
110     KScanDevice::Status openDevice(const QByteArray &backend);
111 
112     /**
113      * Close the scanner device and frees all related data.
114      * After doing so, a new scanner may be opened.
115      **/
116     void closeDevice();
117 
118     /**
119      * Get the device name of the current scanner backend.
120      * It has the format, for example, "umax:/dev/sg1".
121      *
122      * @return The scanner backend name, or a null string if no scanner
123      * is currently open.
124      **/
scannerBackendName()125     const QByteArray &scannerBackendName() const	{ return (mScannerName); }
126 
127     /**
128      * Get a readable name/description of the current scanner
129      * backend.  It may read, for example, "Mustek SP1200 Flatbed scanner".
130      *
131      * @return The scanner description.  If no scanner is currently open,
132      * the (I18N'ed) string "No scanner connected" is returned.
133      **/
134     QString scannerDescription() const;
135 
136     /**
137      * Check whether a scanner device is opened and connected: that is,
138      * whether the @c openDevice() returned @c KScanDevice::Ok).
139      **/
isScannerConnected()140     bool isScannerConnected() const
141     {
142         return (mScannerInitialised);
143     }
144 
145     /**
146      * Get the SANE scanner handle of the current scanner.
147      *
148      * @return The scanner handle, or @c nullptr if no scanner is
149      * currently open.
150      **/
scannerHandle()151     SANE_Handle scannerHandle() const
152     {
153         return (mScannerHandle);
154     }
155 
156     /**
157      * Acquires a preview from the current scanner device.
158      * When the scan is complete, a result image will be sent by
159      * @c sigNewPreview.
160      *
161      * @param forceGray If this is @c true, the preview is acquired
162      * in greyscale regardless of any other settings.
163      * @param dpi Resolution setting for the preview. If this is 0,
164      * a suitable low resolution is selected.
165      * @return The status of the operation
166      **/
167     KScanDevice::Status acquirePreview(bool forceGray = false, int dpi = 0);
168 
169     /**
170      * Acquires a scan from the current scanner device.
171      * When the scan is complete, a result image will be sent by
172      * @c sigNewImage.
173      *
174      * @param filename File name to load, for virtual scanner test mode.
175      * If this is a null or empty string, a real scan is performed.
176      * @return The status of the operation
177      **/
178     KScanDevice::Status acquireScan(const QString &filename = QString());
179 
180     /**
181      * Get the standard file name for saving the preview image for the
182      * current scanner.
183      *
184      * @return Preview file name
185      *
186      * @note Saving the preview image this does not actually work unless a
187      * subdirectory called @c previews exists within the calling application's
188      * @c data resource directory.
189      * @see loadPreviewImage
190      * @see savePreviewImage
191      * @see KStandardDirs
192      **/
193     const QString previewFile() const;
194 
195     /**
196      * Load the last saved preview image for this device from the saved file.
197      *
198      * @return The preview image, or a null image if none could be loaded.
199      *
200      * @see previewFile
201      * @see savePreviewImage
202      **/
203     QImage loadPreviewImage();
204 
205     /**
206      * Saves a preview image for this device to the standard save file.
207      *
208      * @param image Preview image which is to be saved
209      * @return @c true if the saving was successful
210      *
211      * @see previewFile
212      * @see loadPreviewImage
213      * @note For historical reasons, the image is saved in BMP format.
214      **/
215     bool savePreviewImage(const QImage &image) const;
216 
217     /**
218      * Get the names of all of the parameters supported by the
219      * current scanner device.
220      *
221      * @return A list of all known parameter names, in order of their SANE
222      * index.
223      * @see getCommonOptions
224      * @see getAdvancedOptions
225      **/
226     QList<QByteArray> getAllOptions() const;
227 
228     /**
229      * Get the common options of the device. An application will normally
230      * display these options in a convenient and easy to access way.
231      *
232      * @return A list of the names of the common options.
233      * @see getAllOptions
234      * @see getAdvancedOptions
235      **/
236     QList<QByteArray> getCommonOptions() const;
237 
238     /**
239      * Get the advanced options of the device. An application may hide
240      * these options away in a less obvious place.
241      *
242      * @return A list of the names of the advanced options.
243      * @see getAllOptions
244      * @see getCommonOptions
245      **/
246     QList<QByteArray> getAdvancedOptions() const;
247 
248     /**
249      * Retrieve the currently active parameters from the scanner.
250      * This includes all of those that have an associated GUI element,
251      * and also any others (e.g. the TL_X and 3 other scan area settings)
252      * that have been @c apply()'ed but do not have a GUI.
253      *
254      * @param optSet An option set which will receive the options
255      **/
256     void getCurrentOptions(KScanOptSet *optSet) const;
257 
258     /**
259      * Load a saved parameter set. All options that exist in the set
260      * and which the current scanner supports will be @c set()
261      * with the values from the @c KScanOptSet and @c apply()'ed.
262      *
263      * @param optSet An option set with the options to be loaded
264      **/
265     void loadOptionSet(const KScanOptSet *optSet);
266 
267     /**
268      * Check whether the current scanner device supports an option.
269      *
270      * @param name The name of a scanner parameter
271      * @return @c true if the option is known by this scanner
272      **/
273     bool optionExists(const QByteArray &name) const;
274 
275     /**
276      * Resolve a backend-specific option name into a generally known
277      * SANE option name.  See the source code for those names supported.
278      *
279      * @param name The backend-specific parameter name
280      * @return The generally known SANE name, or the input @p name
281      * unchanged if it has no known alias.
282      **/
283     QByteArray aliasName(const QByteArray &name) const;
284 
285     /**
286      * Create a @c KScanOption and GUI widget suitable for the specified
287      * scanner parameter.
288      *
289      * @param name Name of the SANE parameter.
290      * @param parent Parent for widget.
291      * @return A @c KScanOption for the parameter, or @c nullptr if none
292      * could be created.
293      *
294      * @see KScanOption::createWidget
295      * @see KScanOption::widget
296      * @see getExistingGuiElement
297      **/
298     KScanOption *getGuiElement(const QByteArray &name, QWidget *parent);
299 
300     /**
301      * Find the @c KScanOption for an existing scanner parameter.
302      *
303      * @param name Name of the SANE parameter.
304      * @return The @c KScanOption for the parameter, or @c nullptr if the
305      * parameter does not exist or it has not been created yet.
306      **/
307     KScanOption *getExistingGuiElement(const QByteArray &name) const;
308 
309     /**
310      * Create or retrieve a @c KScanOption for the specified scanner
311      * parameter.
312      *
313      * @param name Name of the SANE parameter.
314      * @param create If the option does not yet exist, then create it if
315      * this is @c true (the default).  If this is @c false, then do not
316      * create the option if it does not already exist but return nullptr
317      * instead.
318      * @return The existing or created option, or @c nullptr if @p create
319      * is @c false and the option does not currently exist.
320      * @note This is the only means for a calling library or application
321      * to create or obtain a @c KScanOption.
322      * @note The returned pointer is valid until the scanner device is
323      * closed or the @c KScanDevice object is destroyed.
324      **/
325     KScanOption *getOption(const QByteArray &name, bool create = true);
326 
327     /**
328      * Set the enabled/disabled state of the GUI widget for an option.
329      *
330      * @param name Name of the SANE parameter.
331      * @param state @c true to enable the widget, @c false to disable it.
332      *
333      * @note If the option is not software settable, it will be disabled
334      * regardless of the @p state parameter.
335      * @see KScanOption::isSoftwareSettable
336      **/
337     void guiSetEnabled(const QByteArray &name, bool state);
338 
339     /**
340      * Get the maximum scan area size.  This can be used, for example, to
341      * set the size of a preview widget.
342      *
343      * @return The width and height of the scan area, in SANE units
344      * as returned by the backend.
345      * @note Currently it is assumed that these units are always
346      * millimetres, although according to the SANE documentation it is
347      * possible that the unit may be pixels instead.
348      **/
349     QSize getMaxScanSize();
350 
351     /**
352      * Get the current scan image format and bit depth.
353      *
354      * @param format An integer to receive the format, this is a
355      * @c SANE_Frame value.
356      * @param depth An integer to receive the bit depth (the number of bits
357      * per sample).
358      **/
359     void getCurrentFormat(int *format, int *depth);
360 
361     /**
362      * Access a group in the global scanner configuration file.
363      *
364      * @param groupName The group name
365      * @return the group
366      */
367     static KConfigGroup configGroup(const QString &groupName);
368 
369     /**
370      * Get the global default value for a scanner configuration setting.
371      *
372      * @param item The settings template item
373      * @return The default value
374      **/
getDefault(const KConfigSkeletonItem * item)375     template <class T> static T getDefault(const KConfigSkeletonItem *item)
376     {
377         return (static_cast<const KConfigSkeletonGenericItem<T> *>(item)->value());
378     }
379 
380     /**
381      * Read a configuration setting for the current scanner
382      * from the global scanner configuration file.
383      *
384      * @param item The settings template item
385      * @return The configuration setting, or its default value if none is
386      * saved in the configuration.
387      *
388      * @see storeConfig
389      **/
getConfig(const KConfigSkeletonItem * item)390     template <class T> T getConfig(const KConfigSkeletonItem *item) const
391     {
392         const KConfigGroup grp = configGroup(mScannerName);
393         return (grp.readEntry(item->key(), getDefault<T>(item)));
394     }
395 
396     /**
397      * Save a configuration setting for the current scanner
398      * to the global scanner configuration file.
399      *
400      * @param item The settings template item
401      * @param val Value to store
402      *
403      * @see getConfig
404      **/
storeConfig(const KConfigSkeletonItem * item,const T & val)405     template <class T> void storeConfig(const KConfigSkeletonItem *item, const T &val)
406     {
407         if (mScannerName.isNull()) return;
408         //kDebug() << "Storing config" << key << "in group" << mScannerName;
409         KConfigGroup grp = configGroup(mScannerName);
410         grp.writeEntry(item->key(), val);
411         grp.sync();
412     }
413 
414     /**
415      * Retrieve or prompt for a username/password to authenticate access
416      * to the scanner.  If there is a saved username/password pair for
417      * the current scanner, these will be returned.  Otherwise,
418      * the user is prompted to enter a username/password (via a
419      * @c KPasswordDialog) and the entries are saved in the global
420      * scanner configuration file.
421      *
422      * @param retuser String to receive the user name
423      * @param retpass String to receive the password
424      * @return @c true if a saved username/password was available or
425      * the user entered them, @c false if no saved username/password
426      * was available and the user cancelled the password dialogue.
427      *
428      * @note This will normally be called by @c KScanGlobal::authCallback()
429      * when a SANE operation requires authentication.
430      **/
431     bool authenticate(QByteArray *retuser, QByteArray *retpass);
432 
433     /**
434      * Get an error message for the last SANE operation, if it failed.
435      *
436      * @return the error message string
437      **/
438     QString lastSaneErrorMessage() const;
439 
440     /**
441      * Get an error message for the specified scan result status.
442      *
443      * @return the error message string
444      **/
445     static QString statusMessage(KScanDevice::Status stat);
446 
447     /**
448      * Find the SANE index of an option.
449      *
450      * @param name Name of the SANE parameter.
451      * @return Its option index, or 0 if the option is not known by the scanner.
452      **/
453     int getOptionIndex(const QByteArray &name) const;
454 
455     /**
456      * Update the scanner with the value of the specified option (using
457      * @c KScanOption::apply()), then reload and update the GUI widget
458      * of all of the other options if necessary.  Their value or state
459      * may have changed due to the change in this option; if so, SANE
460      * will tell us to reload them.
461      *
462      * @param opt The option to @c apply().  If this is @c nullptr, this
463      * function is equivalent to @c reloadAllOptions().
464      *
465      * @note Even if a reload is needed, the scanner option given as the
466      * @p opt parameter is not reloaded. This is ensures that no recursion
467      * happens while reloading the options.
468      * @see reloadAllOptions
469      **/
470     void applyOption(KScanOption *opt);
471 
472     /**
473      * Reload all of the scanner options and update their GUI widgets.
474      *
475      * @see applyOption
476      **/
477     void reloadAllOptions();
478 
479 public slots:
480     /**
481      * Request the scan device to stop the scan currently in progress.
482      * The scan may continue until the current data block has been
483      * read and processed.
484      **/
485     void slotStopScanning();
486 
487 signals:
488     /**
489      * Emitted to indicate that a scan is about to start.
490      * Depending on the scanner, there may be a delay (for example,
491      * while the lamp warms up) between this signal and the
492      * @c sigAcquireStart.
493      *
494      * @param info Image information, if it is currently available
495      * @see sigAcquireStart
496      *
497      * @note The @p info parameter may be nullptr, or it may not contain
498      * any useful format information.
499      **/
500     void sigScanStart(const ImageMetaInfo *info);
501 
502     /**
503      * Emitted to indicate that a scan is starting to acquire data.
504      * The first @c sigScanProgress will be emitted with progress value 0
505      * immediately after this signal.
506      * @see sigScanStart
507      **/
508     void sigAcquireStart();
509 
510     /**
511      * Emitted to indicate the scanning progress. The first value sent
512      * is always 0 and the final value is always 100. If the scan results
513      * in multiple frames (for a 3-pass scanner) the sequence will
514      * repeat.
515      *
516      * @param progress The scan progress as a percentage
517      **/
518     void sigScanProgress(int progress);
519 
520     /**
521      * Emitted when a new scan image has been acquired.
522      * The receiver should take a deep copy of the image, as it will
523      * be destroyed after this signal has been delivered.
524      *
525      * @param img The acquired scan image
526      * @param info Additional information for the image
527      * @see sigNewPreview
528      **/
529     void sigNewImage(const QImage *img, const ImageMetaInfo *info);
530 
531     /**
532      * Emitted when a new preview image has been acquired.
533      * The receiver should take a deep copy of the image, as it will
534      * be destroyed after this signal has been delivered.
535      *
536      * @param img The acquired preview image
537      * @param info Additional information for the image
538      * @see sigNewImage
539      **/
540     void sigNewPreview(const QImage *img, const ImageMetaInfo *info);
541 
542     /**
543      * Emitted to indicate that a scan or preview has finished.
544      * This signal is always emitted, even if the scan failed with
545      * an error or was cancelled, and before the @c sigNewImage or
546      * the @c sigNewPreview.
547      *
548      * @param stat Status of the scan
549      **/
550     void sigScanFinished(KScanDevice::Status stat);
551 
552     /**
553      * Emitted when the device is about to be closed by @c closeDevice().
554      * This gives any callers using this device a chance to give up any
555      * dependencies on it.  While this signal is being emitted, the
556      * scanner device is still open and valid.
557      **/
558     void sigCloseDevice();
559 
560 private slots:
561     void doProcessABlock();
562     void slotScanFinished(KScanDevice::Status status);
563 
564 private:
565     KScanDevice::Status findOptions();
566     void showOptions();
567     void loadOptionSetInternal(const KScanOptSet *optSet, bool prio);
568     void applyAllOptions(bool prio);
569 
570     KScanDevice::Status createNewImage(const SANE_Parameters *p);
571 
572     KScanDevice::Status acquireData(bool isPreview = false);
573 
574     /**
575      * Clear any saved authentication for this scanner, to ensure that the
576      * user is prompted again next time.
577      **/
578     void clearSavedAuth();
579 
580     /**
581      * Save the current option parameter set.
582      * Only active and GUI options are saved.
583      **/
584     void saveStartupConfig();
585 
586     /**
587      * Scanning progress state.
588      **/
589     enum ScanningState {                // only used by KScanDevice
590         ScanIdle,
591         ScanStarting,
592         ScanInProgress,
593         ScanNextFrame,
594         ScanStopNow,
595         ScanStopAdfFinished
596     };
597 
598     typedef QHash<QByteArray, KScanOption *> OptionHash;
599     typedef QMap<int, QByteArray> IndexMap;
600 
601     OptionHash mCreatedOptions;             // option name -> KScanOption
602     IndexMap mKnownOptions;             // SANE index -> option name
603 
604     KScanOptSet *mSavedOptions;
605 
606     QByteArray mScannerName;
607     bool mScannerInitialised;
608     SANE_Handle mScannerHandle;
609 
610     KScanDevice::ScanningState mScanningState;
611     SANE_Status mSaneStatus;
612 
613     SANE_Byte *mScanBuf;
614     QImage *mScanImage;
615     ImageMetaInfo *mImageInfo;
616     SANE_Parameters mSaneParameters;
617     long mBytesRead;
618     long mBlocksRead;
619     int mBytesUsed;
620     int mPixelX, mPixelY;
621     bool mScanningPreview;
622     QSocketNotifier *mSocketNotifier;
623 
624     int mCurrScanResolutionX;
625     int mCurrScanResolutionY;
626 };
627 
628 #endif                          // KSCANDEVICE_H
629