File indexing completed on 2024-04-21 15:12:11

0001 /* This file is part of the KDE Project         -*- mode:c++; -*-
0002    Copyright (C) 1999 Klaas Freitag <freitag@suse.de>
0003 
0004    This library is free software; you can redistribute it and/or
0005    modify it under the terms of the GNU Library General Public
0006    License as published by the Free Software Foundation; either
0007    version 2 of the License, or (at your option) any later version.
0008 
0009    This library is distributed in the hope that it will be useful,
0010    but WITHOUT ANY WARRANTY; without even the implied warranty of
0011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0012    Library General Public License for more details.
0013 
0014    You should have received a copy of the GNU Library General Public License
0015    along with this library; see the file COPYING.LIB.  If not, write to
0016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0017    Boston, MA 02110-1301, USA.
0018 */
0019 
0020 #ifndef KSCANDEVICE_H
0021 #define KSCANDEVICE_H
0022 
0023 #include "kookascan_export.h"
0024 
0025 #include <qobject.h>
0026 #include <qbytearray.h>
0027 #include <qimage.h>
0028 #include <qlist.h>
0029 #include <qhash.h>
0030 #include <qmap.h>
0031 
0032 #include <kconfigskeleton.h>
0033 
0034 #include "scanimage.h"
0035 
0036 extern "C" {
0037 #include <sane/sane.h>
0038 }
0039 
0040 class QWidget;
0041 class QSocketNotifier;
0042 
0043 class KConfigSkeletonItem;
0044 
0045 class KScanOption;
0046 class KScanOptSet;
0047 
0048 /**
0049  * @short Access and control a scanner.
0050  *
0051  * After constructing a @c KScanDevice, a scanner may be opened
0052  * via @c openDevice() by specifying its SANE backend name.  Having
0053  * done so, the scanner options supported by the scanner may be set
0054  * and read individually using a @c KScanOption.
0055  *
0056  * A scan or preview may be initiated, once the scan is finished the
0057  * scanned image data is made available via a signal.
0058  *
0059  * The scan device may be closed (using @c closeDevice()) and opened
0060  * again to change the scanner that is accessed.
0061  *
0062  * @author Klaas Freitag
0063  * @author Jonathan Marten
0064  **/
0065 
0066 class KOOKASCAN_EXPORT KScanDevice : public QObject
0067 {
0068     Q_OBJECT
0069 
0070 public:
0071 
0072     /**
0073      * Scanning/control status.
0074      **/
0075     enum Status {
0076         Ok,
0077         NoDevice,
0078         ParamError,
0079         OpenDevice,
0080         ControlError,
0081         ScanError,
0082         EmptyPic,
0083         NoMemory,
0084         Reload,
0085         Cancelled,
0086         OptionNotActive,
0087         NotSupported
0088     };
0089 
0090     /**
0091      * Construct a new scanner device object.
0092      *
0093      * @param parent The parent object
0094      **/
0095     explicit KScanDevice(QObject *parent);
0096 
0097     /**
0098      * Destructor.
0099      **/
0100     ~KScanDevice();
0101 
0102     /**
0103      * Open a scanner device.
0104      *
0105      * @param backend SANE name of the backend to open
0106      * @return The status of the operation
0107      *
0108      * @note This operation may prompt for SANE authentication if
0109      * it is required.
0110      **/
0111     KScanDevice::Status openDevice(const QByteArray &backend);
0112 
0113     /**
0114      * Close the scanner device and frees all related data.
0115      * After doing so, a new scanner may be opened.
0116      **/
0117     void closeDevice();
0118 
0119     /**
0120      * Get the device name of the current scanner backend.
0121      * It has the format, for example, "umax:/dev/sg1".
0122      *
0123      * @return The scanner backend name, or a null string if no scanner
0124      * is currently open.
0125      **/
0126     const QByteArray &scannerBackendName() const    { return (mScannerName); }
0127 
0128     /**
0129      * Get a readable name/description of the current scanner
0130      * backend.  It may read, for example, "Mustek SP1200 Flatbed scanner".
0131      *
0132      * @return The scanner description.  If no scanner is currently open,
0133      * the (I18N'ed) string "No scanner connected" is returned.
0134      **/
0135     QString scannerDescription() const;
0136 
0137     /**
0138      * Check whether a scanner device is opened and connected: that is,
0139      * whether the @c openDevice() returned @c KScanDevice::Ok).
0140      **/
0141     bool isScannerConnected() const
0142     {
0143         return (mScannerInitialised);
0144     }
0145 
0146     /**
0147      * Get the SANE scanner handle of the current scanner.
0148      *
0149      * @return The scanner handle, or @c nullptr if no scanner is
0150      * currently open.
0151      **/
0152     SANE_Handle scannerHandle() const
0153     {
0154         return (mScannerHandle);
0155     }
0156 
0157     /**
0158      * Acquires a preview from the current scanner device.
0159      * When the scan is complete, a result image will be sent by
0160      * @c sigNewPreview.
0161      *
0162      * @param forceGray If this is @c true, the preview is acquired
0163      * in greyscale regardless of any other settings.
0164      * @param dpi Resolution setting for the preview. If this is 0,
0165      * a suitable low resolution is selected.
0166      * @return The status of the operation
0167      **/
0168     KScanDevice::Status acquirePreview(bool forceGray = false, int dpi = 0);
0169 
0170     /**
0171      * Acquires a scan from the current scanner device.
0172      * When the scan is complete, a result image will be sent by
0173      * @c sigNewImage.
0174      *
0175      * @param filename File name to load, for virtual scanner test mode.
0176      * If this is a null or empty string, a real scan is performed.
0177      * @return The status of the operation
0178      **/
0179     KScanDevice::Status acquireScan(const QString &filename = QString());
0180 
0181     /**
0182      * Load the last saved preview image for this device from the saved file.
0183      *
0184      * @return The preview image, or a null image if none could be loaded.
0185      *
0186      * @see previewFile
0187      * @see savePreviewImage
0188      **/
0189     QImage loadPreviewImage() const;
0190 
0191     /**
0192      * Saves a preview image for this device to the standard save file.
0193      *
0194      * @param image Preview image which is to be saved
0195      * @return @c true if the saving was successful
0196      *
0197      * @see previewFile
0198      * @see loadPreviewImage
0199      * @note For historical reasons, the image is saved in BMP format.
0200      **/
0201     bool savePreviewImage(const QImage &image) const;
0202 
0203     /**
0204      * Get the names of all of the parameters supported by the
0205      * current scanner device.
0206      *
0207      * @return A list of all known parameter names, in order of their SANE
0208      * index.
0209      * @see getCommonOptions
0210      * @see getAdvancedOptions
0211      **/
0212     QList<QByteArray> getAllOptions() const;
0213 
0214     /**
0215      * Get the common options of the device. An application will normally
0216      * display these options in a convenient and easy to access way.
0217      *
0218      * @return A list of the names of the common options.
0219      * @see getAllOptions
0220      * @see getAdvancedOptions
0221      **/
0222     QList<QByteArray> getCommonOptions() const;
0223 
0224     /**
0225      * Get the advanced options of the device. An application may hide
0226      * these options away in a less obvious place.
0227      *
0228      * @return A list of the names of the advanced options.
0229      * @see getAllOptions
0230      * @see getCommonOptions
0231      **/
0232     QList<QByteArray> getAdvancedOptions() const;
0233 
0234     /**
0235      * Retrieve the currently active parameters from the scanner.
0236      * This includes all of those that have an associated GUI element,
0237      * and also any others (e.g. the TL_X and 3 other scan area settings)
0238      * that have been @c apply()'ed but do not have a GUI.
0239      *
0240      * @param optSet An option set which will receive the options
0241      **/
0242     void getCurrentOptions(KScanOptSet *optSet) const;
0243 
0244     /**
0245      * Load a saved parameter set. All options that exist in the set
0246      * and which the current scanner supports will be @c set()
0247      * with the values from the @c KScanOptSet and @c apply()'ed.
0248      *
0249      * @param optSet An option set with the options to be loaded
0250      **/
0251     void loadOptionSet(const KScanOptSet *optSet);
0252 
0253     /**
0254      * Check whether the current scanner device supports an option.
0255      *
0256      * @param name The name of a scanner parameter
0257      * @return @c true if the option is known by this scanner
0258      **/
0259     bool optionExists(const QByteArray &name) const;
0260 
0261     /**
0262      * Resolve a backend-specific option name into a generally known
0263      * SANE option name.  See the source code for those names supported.
0264      *
0265      * @param name The backend-specific parameter name
0266      * @return The generally known SANE name, or the input @p name
0267      * unchanged if it has no known alias.
0268      **/
0269     QByteArray aliasName(const QByteArray &name) const;
0270 
0271     /**
0272      * Create a @c KScanOption and GUI widget suitable for the specified
0273      * scanner parameter.
0274      *
0275      * @param name Name of the SANE parameter.
0276      * @param parent Parent for widget.
0277      * @return A @c KScanOption for the parameter, or @c nullptr if none
0278      * could be created.
0279      *
0280      * @see KScanOption::createWidget
0281      * @see KScanOption::widget
0282      * @see getExistingGuiElement
0283      **/
0284     KScanOption *getGuiElement(const QByteArray &name, QWidget *parent);
0285 
0286     /**
0287      * Find the @c KScanOption for an existing scanner parameter.
0288      *
0289      * @param name Name of the SANE parameter.
0290      * @return The @c KScanOption for the parameter, or @c nullptr if the
0291      * parameter does not exist or it has not been created yet.
0292      **/
0293     KScanOption *getExistingGuiElement(const QByteArray &name) const;
0294 
0295     /**
0296      * Create or retrieve a @c KScanOption for the specified scanner
0297      * parameter.
0298      *
0299      * @param name Name of the SANE parameter.
0300      * @param create If the option does not yet exist, then create it if
0301      * this is @c true (the default).  If this is @c false, then do not
0302      * create the option if it does not already exist but return nullptr
0303      * instead.
0304      * @return The existing or created option, or @c nullptr if @p create
0305      * is @c false and the option does not currently exist.
0306      * @note This is the only means for a calling library or application
0307      * to create or obtain a @c KScanOption.
0308      * @note The returned pointer is valid until the scanner device is
0309      * closed or the @c KScanDevice object is destroyed.
0310      **/
0311     KScanOption *getOption(const QByteArray &name, bool create = true);
0312 
0313     /**
0314      * Set the enabled/disabled state of the GUI widget for an option.
0315      *
0316      * @param name Name of the SANE parameter.
0317      * @param state @c true to enable the widget, @c false to disable it.
0318      *
0319      * @note If the option is not software settable, it will be disabled
0320      * regardless of the @p state parameter.
0321      * @see KScanOption::isSoftwareSettable
0322      **/
0323     void guiSetEnabled(const QByteArray &name, bool state);
0324 
0325     /**
0326      * Get the maximum scan area size.  This can be used, for example, to
0327      * set the size of a preview widget.
0328      *
0329      * @return The width and height of the scan area, in SANE units
0330      * as returned by the backend.
0331      * @note Currently it is assumed that these units are always
0332      * millimetres, although according to the SANE documentation it is
0333      * possible that the unit may be pixels instead.
0334      **/
0335     QSize getMaxScanSize();
0336 
0337     /**
0338      * Get the current scan image format and bit depth.
0339      *
0340      * @param format An integer to receive the format, this is a
0341      * @c SANE_Frame value.
0342      * @param depth An integer to receive the bit depth (the number of bits
0343      * per sample).
0344      **/
0345     void getCurrentFormat(int *format, int *depth);
0346 
0347     /**
0348      * Access a group in the global scanner configuration file.
0349      *
0350      * @param groupName The group name
0351      * @return the group
0352      */
0353     static KConfigGroup configGroup(const QString &groupName);
0354 
0355     /**
0356      * Get the global default value for a scanner configuration setting.
0357      *
0358      * @param item The settings template item
0359      * @return The default value
0360      **/
0361     template <class T> static T getDefault(const KConfigSkeletonItem *item)
0362     {
0363         return (static_cast<const KConfigSkeletonGenericItem<T> *>(item)->value());
0364     }
0365 
0366     /**
0367      * Read a configuration setting for the current scanner
0368      * from the global scanner configuration file.
0369      *
0370      * @param item The settings template item
0371      * @return The configuration setting, or its default value if none is
0372      * saved in the configuration.
0373      *
0374      * @see storeConfig
0375      **/
0376     template <class T> T getConfig(const KConfigSkeletonItem *item) const
0377     {
0378         const KConfigGroup grp = configGroup(mScannerName);
0379         return (grp.readEntry(item->key(), getDefault<T>(item)));
0380     }
0381 
0382     /**
0383      * Save a configuration setting for the current scanner
0384      * to the global scanner configuration file.
0385      *
0386      * @param item The settings template item
0387      * @param val Value to store
0388      *
0389      * @see getConfig
0390      **/
0391     template <class T> void storeConfig(const KConfigSkeletonItem *item, const T &val)
0392     {
0393         if (mScannerName.isNull()) return;
0394         //kDebug() << "Storing config" << key << "in group" << mScannerName;
0395         KConfigGroup grp = configGroup(mScannerName);
0396         grp.writeEntry(item->key(), val);
0397         grp.sync();
0398     }
0399 
0400     /**
0401      * Retrieve or prompt for a username/password to authenticate access
0402      * to the scanner.  If there is a saved username/password pair for
0403      * the current scanner, these will be returned.  Otherwise,
0404      * the user is prompted to enter a username/password (via a
0405      * @c KPasswordDialog) and the entries are saved in the global
0406      * scanner configuration file.
0407      *
0408      * @param retuser String to receive the user name
0409      * @param retpass String to receive the password
0410      * @return @c true if a saved username/password was available or
0411      * the user entered them, @c false if no saved username/password
0412      * was available and the user cancelled the password dialogue.
0413      *
0414      * @note This will normally be called by @c KScanGlobal::authCallback()
0415      * when a SANE operation requires authentication.
0416      **/
0417     bool authenticate(QByteArray *retuser, QByteArray *retpass);
0418 
0419     /**
0420      * Get an error message for the last SANE operation, if it failed.
0421      *
0422      * @return the error message string
0423      **/
0424     QString lastSaneErrorMessage() const;
0425 
0426     /**
0427      * Get an error message for the specified scan result status.
0428      *
0429      * @return the error message string
0430      **/
0431     static QString statusMessage(KScanDevice::Status stat);
0432 
0433     /**
0434      * Find the SANE index of an option.
0435      *
0436      * @param name Name of the SANE parameter.
0437      * @return Its option index, or 0 if the option is not known by the scanner.
0438      **/
0439     int getOptionIndex(const QByteArray &name) const;
0440 
0441     /**
0442      * Update the scanner with the value of the specified option (using
0443      * @c KScanOption::apply()), then reload and update the GUI widget
0444      * of all of the other options if necessary.  Their value or state
0445      * may have changed due to the change in this option; if so, SANE
0446      * will tell us to reload them.
0447      *
0448      * @param opt The option to @c apply().  If this is @c nullptr, this
0449      * function is equivalent to @c reloadAllOptions().
0450      *
0451      * @note Even if a reload is needed, the scanner option given as the
0452      * @p opt parameter is not reloaded. This is ensures that no recursion
0453      * happens while reloading the options.
0454      * @see reloadAllOptions
0455      **/
0456     void applyOption(KScanOption *opt);
0457 
0458     /**
0459      * Reload all of the scanner options and update their GUI widgets.
0460      *
0461      * @see applyOption
0462      **/
0463     void reloadAllOptions();
0464 
0465     /**
0466      * Set a format to be used for indicating the image type to the
0467      * application.  The GUI control is only shown when using the SANE
0468      * "test" device, normally the image type is resolved from the SANE
0469      * parameters.
0470      *
0471      * @param type the image type
0472      * @see sigScanStart()
0473      **/
0474     void setTestFormat(ScanImage::ImageType type)   { mTestFormat = type; }
0475 
0476 public slots:
0477     /**
0478      * Request the scan device to stop the scan currently in progress.
0479      * The scan may continue until the current data block has been
0480      * read and processed.
0481      **/
0482     void slotStopScanning();
0483 
0484 signals:
0485     /**
0486      * Emitted to indicate that a scan is about to start.
0487      * Depending on the scanner, there may be a delay (for example,
0488      * while the lamp warms up) between this signal and the
0489      * @c sigAcquireStart.
0490      *
0491      * @param type Image type information, if a scan is being started
0492      * and the image information is is currently available.  This will
0493      * be @c ScanImage::Preview if a preview is being started, and may
0494      * be @c ScanImage::None if not enough image information is available.
0495      *
0496      * @see sigAcquireStart
0497      **/
0498     void sigScanStart(ScanImage::ImageType type);
0499 
0500     /**
0501      * Emitted to indicate that a scan is starting to acquire data.
0502      * The first @c sigScanProgress will be emitted with progress value 0
0503      * immediately after this signal.
0504      *
0505      * @see sigScanStart
0506      **/
0507     void sigAcquireStart();
0508 
0509     /**
0510      * Emitted to indicate the scanning progress. The first value sent
0511      * is always 0 and the final value is always 100. If the scan results
0512      * in multiple frames (for a 3-pass scanner) the sequence will
0513      * repeat.
0514      *
0515      * @param progress The scan progress as a percentage
0516      **/
0517     void sigScanProgress(int progress);
0518 
0519     /**
0520      * Emitted when a new scan image has been acquired.
0521      *
0522      * @param img The acquired scan image
0523      *
0524      * @see sigNewPreview
0525      **/
0526     void sigNewImage(ScanImage::Ptr img);
0527 
0528     /**
0529      * Emitted when a new preview image has been acquired.
0530      *
0531      * @param img The acquired preview image
0532      * @param info Additional information for the image
0533      *
0534      * @see sigNewImage
0535      **/
0536     void sigNewPreview(ScanImage::Ptr img);
0537 
0538     /**
0539      * Emitted to indicate that a scan or preview has finished.
0540      * This signal is always emitted, even if the scan failed with
0541      * an error or was cancelled, and after the @c sigNewImage or
0542      * the @c sigNewPreview.
0543      *
0544      * @param stat Status of the scan
0545      **/
0546     void sigScanFinished(KScanDevice::Status stat);
0547 
0548     /**
0549      * Emitted when the device is about to be closed by @c closeDevice().
0550      * This gives any callers using this device a chance to give up any
0551      * dependencies on it.  While this signal is being emitted, the
0552      * scanner device is still open and valid.
0553      **/
0554     void sigCloseDevice();
0555 
0556 private slots:
0557     void doProcessABlock();
0558 
0559 private:
0560     /**
0561      * Get the standard file name for saving the preview image for the
0562      * current scanner.
0563      *
0564      * @return the preview file name
0565      *
0566      * @note Saving the preview image does not actually work unless a
0567      * subdirectory called @c previews exists within the calling
0568      * application's @c data resource directory.
0569      *
0570      * @see loadPreviewImage
0571      * @see savePreviewImage
0572      * @see KStandardDirs
0573      **/
0574     const QString previewFile() const;
0575 
0576     KScanDevice::Status findOptions();
0577     void showOptions();
0578     void loadOptionSetInternal(const KScanOptSet *optSet, bool prio);
0579     void applyAllOptions(bool prio);
0580 
0581     KScanDevice::Status createNewImage(const SANE_Parameters *p);
0582 
0583     KScanDevice::Status acquireData(bool isPreview);
0584     void scanFinished(KScanDevice::Status status);
0585 
0586     /**
0587      * Clear any saved authentication for this scanner, to ensure that the
0588      * user is prompted again next time.
0589      **/
0590     void clearSavedAuth();
0591 
0592     /**
0593      * Save the current option parameter set.
0594      * Only active and GUI options are saved.
0595      **/
0596     void saveStartupConfig();
0597 
0598     /**
0599      * Scanning progress state.
0600      **/
0601     enum ScanningState {                // only used by KScanDevice
0602         ScanIdle,
0603         ScanStarting,
0604         ScanInProgress,
0605         ScanNextFrame,
0606         ScanStopNow,
0607         ScanStopAdfFinished
0608     };
0609 
0610     typedef QHash<QByteArray, KScanOption *> OptionHash;
0611     typedef QMap<int, QByteArray> IndexMap;
0612 
0613     OptionHash mCreatedOptions;             // option name -> KScanOption
0614     IndexMap mKnownOptions;             // SANE index -> option name
0615 
0616     QByteArray mScannerName;
0617     bool mScannerInitialised;
0618     SANE_Handle mScannerHandle;
0619 
0620     KScanDevice::ScanningState mScanningState;
0621     SANE_Status mSaneStatus;
0622 
0623     SANE_Byte *mScanBuf;
0624     SANE_Parameters mSaneParameters;
0625     long mBytesRead;
0626     long mBlocksRead;
0627     int mBytesUsed;
0628     int mPixelX, mPixelY;
0629     bool mScanningPreview;
0630     QSocketNotifier *mSocketNotifier;
0631 
0632     int mCurrScanResolutionX;
0633     int mCurrScanResolutionY;
0634 
0635     ScanImage::Ptr mScanImage;
0636     ScanImage::ImageType mTestFormat;
0637 };
0638 
0639 #endif                          // KSCANDEVICE_H