import libksane, skanlite and ksaneplugin (bootstrap will fail)

This commit is contained in:
Ivailo Monev 2015-01-01 01:22:10 +00:00
parent 2023560860
commit b839a26abc
112 changed files with 17574 additions and 0 deletions

View file

@ -40,6 +40,8 @@ macro_optional_add_subdirectory (kdenetwork-filesharing)
macro_optional_add_subdirectory (kfilemetadata)
# macro_optional_add_subdirectory (kfilereplace)
macro_optional_add_subdirectory (lokalize)
# FIXME: make skanlite and ksaneplugin find libksane
macro_optional_add_subdirectory (libksane)
macro_optional_add_subdirectory (libkscreen)
# FIXME: make kget find libktorrent
macro_optional_add_subdirectory (libktorrent)
@ -53,6 +55,7 @@ macro_optional_add_subdirectory (kolourpaint)
macro_optional_add_subdirectory (kompare)
macro_optional_add_subdirectory (krdc)
macro_optional_add_subdirectory (krfb)
macro_optional_add_subdirectory (ksaneplugin)
macro_optional_add_subdirectory (ksnapshot)
macro_optional_add_subdirectory (ksystemlog)
macro_optional_add_subdirectory (ktimer)
@ -61,5 +64,6 @@ macro_optional_add_subdirectory (kuser)
macro_optional_add_subdirectory (okular)
macro_optional_add_subdirectory (partitionmanager)
macro_optional_add_subdirectory (print-manager)
macro_optional_add_subdirectory (skanlite)
macro_optional_add_subdirectory (svgpart)
macro_optional_add_subdirectory (thumbnailers)

View file

@ -0,0 +1,25 @@
project(ksaneplugin)
SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake/modules )
find_package(KDE4 REQUIRED)
include(KDE4Defaults)
include(MacroLibrary)
include(MacroOptionalAddSubdirectory)
find_package(KSane REQUIRED)
include_directories(${KSANE_INCLUDE_DIR})
add_definitions (${QT_DEFINITIONS} ${QT_QTDBUS_DEFINITIONS} ${KDE4_DEFINITIONS} -DQT_USE_FAST_CONCATENATION -DQT_USE_FAST_OPERATOR_PLUS)
include_directories (${QDBUS_INCLUDE_DIRS} ${CMAKE_SOURCE_DIR} ${CMAKE_BINARY_DIR} ${KDE4_INCLUDES})
########### target ###############
kde4_add_plugin(ksaneplugin sanedialog.cpp)
target_link_libraries(ksaneplugin ${KDE4_KDEUI_LIBS} ${KDE4_KIO_LIBS} ${KSANE_LIBRARY})
install(TARGETS ksaneplugin DESTINATION ${PLUGIN_INSTALL_DIR} )
########### install files ###############
install( FILES ksane_scan_service.desktop DESTINATION ${SERVICES_INSTALL_DIR} )

510
ksaneplugin/COPYING Normal file
View file

@ -0,0 +1,510 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations
below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it
becomes a de-facto standard. To achieve this, non-free programs must
be allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control
compilation and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at least
three years, to give the same user the materials specified in
Subsection 6a, above, for a charge no more than the cost of
performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply, and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License
may add an explicit geographical distribution limitation excluding those
countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms
of the ordinary General Public License).
To apply these terms, attach the following notices to the library.
It is safest to attach them to the start of each source file to most
effectively convey the exclusion of warranty; and each file should
have at least the "copyright" line and a pointer to where the full
notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or
your school, if any, to sign a "copyright disclaimer" for the library,
if necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James
Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

2
ksaneplugin/Messages.sh Normal file
View file

@ -0,0 +1,2 @@
#! /usr/bin/env bash
$XGETTEXT *.cpp -o $podir/ksaneplugin.pot

View file

@ -0,0 +1,22 @@
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -0,0 +1,44 @@
# cmake macro to test if libksane is installed
#
# KSANE_FOUND - system has KSANE libs
# KSANE_INCLUDE_DIR - the KSANE include directory
# KSANE_LIBRARY - The library needed to use KSANE
if (KSANE_INCLUDE_DIR)
# Already in cache, be silent
set(KSANE_FIND_QUIETLY TRUE)
endif (KSANE_INCLUDE_DIR)
FIND_FILE(KSANE_LOCAL_FOUND libksane/version.h.cmake ${CMAKE_SOURCE_DIR}/libs/libksane NO_DEFAULT_PATH)
if (KSANE_LOCAL_FOUND)
set(KSANE_INCLUDE_DIR ${CMAKE_SOURCE_DIR}/libs/libksane)
set(KSANE_DEFINITIONS -I${KSANE_INCLUDE_DIR})
set(KSANE_LIBRARY ksane)
message(STATUS "Found KSane library in local sub-folder: ${KSANE_LIBRARY}")
set(KSANE_FOUND TRUE)
MARK_AS_ADVANCED(KSANE_INCLUDE_DIR KSANE_LIBRARY)
else (KSANE_LOCAL_FOUND)
FIND_PATH(KSANE_INCLUDE_DIR libksane/ksane.h ${KDE4_INCLUDES})
FIND_LIBRARY(KSANE_LIBRARY ksane PATH ${KDE4_LIB_DIR})
if (KSANE_INCLUDE_DIR AND KSANE_LIBRARY)
set(KSANE_FOUND TRUE)
else (KSANE_INCLUDE_DIR AND KSANE_LIBRARY)
set(KSANE_FOUND FALSE)
endif (KSANE_INCLUDE_DIR AND KSANE_LIBRARY)
if (KSANE_FOUND)
if (NOT KSane_FIND_QUIETLY)
message(STATUS "Found libksane: ${KSANE_LIBRARY}")
endif (NOT KSane_FIND_QUIETLY)
else (KSANE_FOUND)
if (KSane_FIND_REQUIRED)
message(FATAL_ERROR "Could not find libksane")
endif (KSane_FIND_REQUIRED)
endif (KSANE_FOUND)
endif (KSANE_LOCAL_FOUND)
MARK_AS_ADVANCED(KSANE_INCLUDE_DIR KSANE_LIBRARY)

View file

@ -0,0 +1,81 @@
[Desktop Entry]
Type=Service
Name=KDE Scan Service
Name[af]=Kde Skandeer Diens
Name[ar]=خدمة المسح لكدي
Name[ast]=Serviciu de dixitalización de KDE
Name[bg]=Услуга за сканиране
Name[br]=Damanterien skramm
Name[bs]=KDEov servis za skeniranje
Name[ca]=Servei d'escaneig del KDE
Name[ca@valencia]=Servei d'escaneig del KDE
Name[cs]=Skenovací služba pro KDE
Name[cy]=Gwasanaeth Sganio KDE
Name[da]=KDE Skanneservice
Name[de]=Scan-Dienst von KDE
Name[el]=Υπηρεσία σάρωσης του KDE
Name[en_GB]=KDE Scan Service
Name[eo]=KDE skana servo
Name[es]=Servicio de digitalización de KDE
Name[et]=KDE skaneerimisteenus
Name[eu]=KDEren eskaneatze zerbitzua
Name[fa]=خدمت پویش KDE
Name[fi]=KDE :n skannauspalvelu
Name[fr]=Service de numérisation de KDE
Name[ga]=Seirbhís Scanta KDE
Name[gl]=Servizo de escáner de KDE
Name[he]=שירות הסריקה של KDE
Name[hi]= ि
Name[hne]= ि
Name[hr]=KDE skan servis
Name[hu]=KDE lapolvasó szolgáltatás
Name[ia]=Servicio de scander de KDE
Name[is]=KDE myndlesaraþjónusta
Name[it]=Servizio di scansione di KDE
Name[ja]=KDE
Name[kk]=KDE сканер қызметі
Name[km]= KDE
Name[ko]=KDE
Name[ku]=KDE Servîsa Venihêrînê
Name[lt]=KDE skanavimo tarnyba
Name[lv]=KDE skenēšanas serviss
Name[mr]=
Name[ms]=Perkhidmatan Imbas KDE
Name[nb]=KDE skannetjeneste
Name[nds]=Bildinleesdeenst för KDE
Name[ne]=
Name[nl]=KDE Scannerdiensten
Name[nn]=KDE Skanningsteneste
Name[pa]=KDE ਿ
Name[pl]=Usługa skanowania KDE
Name[pt]=Serviço de Digitalização do KDE
Name[pt_BR]=Serviço de digitalização do KDE
Name[ro]=Serviciu de scanare KDE
Name[ru]=Служба сканирования KDE
Name[se]=KDE skánnenbálválus
Name[si]=KDE
Name[sk]=Skenovacia služba pre KDE
Name[sl]=Storitev optičnega branja za KDE
Name[sr]=КДЕов сервис за скенирање
Name[sr@ijekavian]=КДЕов сервис за скенирање
Name[sr@ijekavianlatin]=KDEov servis za skeniranje
Name[sr@latin]=KDEov servis za skeniranje
Name[sv]=KDE:s bildläsartjänst
Name[ta]=ி
Name[tg]=Сканеронӣ дар KDE
Name[th]=-K
Name[tr]=KDE Tarayıcı Servisi
Name[ug]=KDE شويلىلاش مۇلازىمىتى
Name[uk]=Служба сканування KDE
Name[uz]=KDE skan qilish xizmati
Name[uz@cyrillic]=KDE скан қилиш хизмати
Name[vi]=Dch v quét ca KDE
Name[wa]=Siervice di scanaedje di KDE
Name[xh]=Inkonzo yemita yovavanyo ye KDE
Name[x-test]=xxKDE Scan Servicexx
Name[zh_CN]=KDE
Name[zh_HK]=KDE
Name[zh_TW]=KDE
X-KDE-Library=ksaneplugin
InitialPreference=3
X-KDE-ServiceTypes=KScan/KScanDialog

114
ksaneplugin/sanedialog.cpp Normal file
View file

@ -0,0 +1,114 @@
/* ============================================================
*
* Date : 2008-04-17
* Description : Sane plugin interface for KDE
*
* Copyright (C) 2008 by Kare Sars <kare dot sars at iki dot fi>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================ */
#include "sanedialog.h"
#include <KLocale>
#include <KDebug>
#include <KPluginLoader>
#include <KMessageBox>
#include <KSharedConfig>
K_PLUGIN_FACTORY(SaneDialogFactory, registerPlugin<SaneDialog>();)
K_EXPORT_PLUGIN(SaneDialogFactory("ksaneplugin"))
///////////////////////////////////////////////////////////////////
SaneDialog::SaneDialog(QWidget *parent, const QVariantList &)
: KScanDialog(Plain, Close, parent)
{
ksanew = new KSaneIface::KSaneWidget(this);
addPage(ksanew, QString());
connect(ksanew, SIGNAL(imageReady(QByteArray &, int, int, int, int)),
this, SLOT(imageReady(QByteArray &, int, int, int, int)));
openDev = QString();
}
bool SaneDialog::setup()
{
if(!ksanew) {
// new failed
return false;
}
if (!openDev.isEmpty()) {
return true;
}
// need to select a scanner
openDev = ksanew->selectDevice(0);
if (openDev.isEmpty()) {
// either no scanner was found or then cancel was pressed.
return false;
}
if (ksanew->openDevice(openDev) == false) {
// could not open the scanner
KMessageBox::sorry(0, i18n("Opening the selected scanner failed."));
openDev = QString();
return false;
}
// restore scan dialog size and all options for the selected device if available
KSharedConfigPtr configPtr = KSharedConfig::openConfig("scannersettings");
restoreDialogSize(KConfigGroup(configPtr, "ScanDialog"));
QString groupName = openDev;
if (configPtr->hasGroup(groupName)) {
KConfigGroup group(configPtr, groupName);
QStringList keys = group.keyList();
for (int i = 0; i < keys.count(); i++)
ksanew->setOptVal(keys[i], group.readEntry(keys[i]));
}
return true;
}
SaneDialog::~SaneDialog()
{
if (ksanew && !openDev.isEmpty()) {
// save scan dialog size and all options for the selected device if available
KSharedConfigPtr configPtr = KSharedConfig::openConfig("scannersettings");
KConfigGroup group(configPtr, "ScanDialog");
saveDialogSize(group, KConfigGroup::Persistent);
group = configPtr->group(openDev);
QMap<QString, QString> opts;
ksanew->getOptVals(opts);
QMap<QString, QString>::const_iterator i = opts.constBegin();
for (; i != opts.constEnd(); ++i)
group.writeEntry(i.key(), i.value(), KConfigGroup::Persistent);
}
}
void SaneDialog::imageReady(QByteArray &data, int w, int h, int bpl, int f)
{
/* copy the image data into img */
QImage img = ksanew->toQImage(data, w, h, bpl, (KSaneIface::KSaneWidget::ImageFormat)f);
emit finalImage(img, nextId());
}
#include "sanedialog.moc"

52
ksaneplugin/sanedialog.h Normal file
View file

@ -0,0 +1,52 @@
/* ============================================================
*
* Date : 2008-04-17
* Description : Sane plugin interface for KDE
*
* Copyright (C) 2008 by Kare Sars <kare dot sars at iki dot fi>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================ */
#ifndef SANEDIALOG_H
#define SANEDIALOG_H
#include <kscan.h>
#include <libksane/ksane.h>
class SaneDialog : public KScanDialog
{
Q_OBJECT
public:
explicit SaneDialog( QWidget *parent = 0, const QVariantList &args = QVariantList() );
~SaneDialog();
virtual bool setup();
protected slots:
void imageReady(QByteArray &, int, int, int, int);
private:
KSaneIface::KSaneWidget *ksanew;
QString openDev;
};
#endif // SCAN_H

3
libksane/.directory Normal file
View file

@ -0,0 +1,3 @@
[Dolphin]
Timestamp=2015,1,1,1,18,6
Version=3

2
libksane/.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
*.kate-swp
tests/databases/*/*.db

8
libksane/AUTHORS Normal file
View file

@ -0,0 +1,8 @@
AUTHORS AND MAINTAINERS:
Kare Sars <kare dot sars at iki dot fi>
Caulier Gilles <caulier dot gilles at gmail dot com>
CONTRIBUTORS:
Angelo Naselli <anaselli at linux dot it>

83
libksane/CMakeLists.txt Normal file
View file

@ -0,0 +1,83 @@
PROJECT(libksane)
MESSAGE(STATUS "----------------------------------------------------------------------------------")
MESSAGE(STATUS "Starting CMake configuration for: libksane")
# building separately or as part of kdegraphics ?
IF(NOT KDE4_FOUND)
FIND_PACKAGE(KDE4 REQUIRED)
ENDIF(NOT KDE4_FOUND)
# Check if sane API is available.
IF (NOT WIN32)
FIND_PACKAGE(Sane)
macro_log_feature(SANE_FOUND "SANE development toolkit" "Scanner Access Now Easy (SANE) development package" "http://www.sane-project.org" TRUE "" "Needed by libksane")
ENDIF (NOT WIN32)
ADD_DEFINITIONS (${QT_DEFINITIONS} ${KDE4_DEFINITIONS})
INCLUDE_DIRECTORIES (${CMAKE_SOURCE_DIR}
${CMAKE_BINARY_DIR}
${KDE4_INCLUDES}
${CMAKE_CURRENT_BINARY_DIR}/libksane)
# =======================================================
# Information to update before to release this library.
# Library version history:
# API ABI
# 0.1.0 => 0.1.0
# 0.1.1 => 0.1.1
# 0.2.0 => 0.2.0
# Library API version
SET(KSANE_LIB_MAJOR_VERSION "0")
SET(KSANE_LIB_MINOR_VERSION "3")
SET(KSANE_LIB_PATCH_VERSION "0")
# Suffix to add at end of version string. Usual values are:
# "-git" : alpha code unstable from git. Do not use in production
# "-beta1" : beta1 release.
# "-beta2" : beta2 release.
# "-beta3" : beta3 release.
# "-rc" : release candidate.
# "" : final relase. Can be used in production.
SET(KSANE_LIB_SUFFIX_VERSION "")
# Library ABI version used by linker.
# For details : http://www.gnu.org/software/libtool/manual/libtool.html#Updating-version-info
SET(KSANE_LIB_SO_CUR_VERSION "0")
SET(KSANE_LIB_SO_REV_VERSION "2")
SET(KSANE_LIB_SO_AGE_VERSION "0")
# =======================================================
# Set env. variables accordinly.
SET(KSANE_LIB_VERSION_STRING "${KSANE_LIB_MAJOR_VERSION}.${KSANE_LIB_MINOR_VERSION}.${KSANE_LIB_PATCH_VERSION}${KSANE_LIB_SUFFIX_VERSION}")
SET(KSANE_LIB_VERSION_ID "0x0${KSANE_LIB_MAJOR_VERSION}0${KSANE_LIB_MINOR_VERSION}0${KSANE_LIB_PATCH_VERSION}")
SET(KSANE_LIB_SO_VERSION_STRING "${KSANE_LIB_SO_CUR_VERSION}.${KSANE_LIB_SO_REV_VERSION}.${KSANE_LIB_SO_AGE_VERSION}")
# =======================================================
ADD_DEFINITIONS(-DKDE_DEFAULT_DEBUG_AREA=51004)
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/libksane/version.h.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/libksane/version.h)
# =======================================================
# To prevent warnings from M$ compiler
IF(WIN32 AND MSVC)
ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS)
ADD_DEFINITIONS(-D_ATL_SECURE_NO_WARNINGS)
ADD_DEFINITIONS(-D_AFX_SECURE_NO_WARNINGS)
ENDIF(WIN32 AND MSVC)
# =======================================================
IF (SANE_FOUND)
ADD_SUBDIRECTORY(libksane)
ELSE (SANE_FOUND)
ADD_SUBDIRECTORY(ksanetwain)
ENDIF (SANE_FOUND)
macro_display_feature_log()

340
libksane/COPYING Normal file
View file

@ -0,0 +1,340 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

View file

@ -0,0 +1,22 @@
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. The name of the author may not be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

510
libksane/COPYING.LIB Normal file
View file

@ -0,0 +1,510 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations
below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it
becomes a de-facto standard. To achieve this, non-free programs must
be allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control
compilation and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at least
three years, to give the same user the materials specified in
Subsection 6a, above, for a charge no more than the cost of
performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply, and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License
may add an explicit geographical distribution limitation excluding those
countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms
of the ordinary General Public License).
To apply these terms, attach the following notices to the library.
It is safest to attach them to the start of each source file to most
effectively convey the exclusion of warranty; and each file should
have at least the "copyright" line and a pointer to where the full
notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or
your school, if any, to sign a "copyright disclaimer" for the library,
if necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James
Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

33
libksane/COPYING.twain Normal file
View file

@ -0,0 +1,33 @@
The file twain.h may be copied under the TWAIN License as specified at
http://www.twain.org/license.shtm
The TWAIN License
The TWAIN Working Group grants customer ("Customer") the worldwide,
royalty-free, non-exclusive license to reproduce and distribute the
software and documentation of the TWAIN toolkit ("TWAIN Toolkit"). The
TWAIN Toolkit was designed to be used by third parties to assist them
in becoming compliant with the TWAIN standard, but it has not been
developed to the standards of a commercial product. Consequently, the
TWAIN toolkit is provided AS IS without any warranty. THE TWAIN
Working Group disclaims all warranties in the TWAIN toolkit whether
implied, express or statutory, including, without limitation, the
implied warranties of merchantability, noninfringement of third party
rights and fitness for a particular purpose. The TWAIN Working Group
disclaims all liability for damages, whether direct, indirect,
special, incidental, or consequential, arising from the reproduction,
distribution, modification, or other use of the TWAIN Toolkit.
As a condition of this license, Customer agrees to include in software
programs based in whole or in part on the TWAIN Toolkit the following
providions in (i) the header or similar file in such software and (ii)
prominently in its documentation and to require its sublicensees to
include these provisions in similar locations: The TWAIN Toolkit is
distributed as is. The developer and distributors of the TWAIN Toolkit
expressly disclaim all implied, express or statutory warranties
including, without limitation, the implied warranties of
merchantability, noninfringement of third party rights and fitness for
a particular purpose. Neither the developers nor the distributors will
be liable for damages, whether direct, indirect, special, incidental,
or consequential, as a result of the reproduction, modification,
distribution or other use of the TWAIN Toolkit.

12
libksane/ChangeLog Normal file
View file

@ -0,0 +1,12 @@
0.1.2
- Add support for button parameters
- Move the progress bar so that it is more visible during scan
0.1.1
- Add toQImage() for a nicer API
0.1.0
- Initial release

5
libksane/NEWS Normal file
View file

@ -0,0 +1,5 @@
0.1.0
------------------------------------------------------------------------
First implementation
For details and info about previous versions, see ChangeLog.

72
libksane/README Normal file
View file

@ -0,0 +1,72 @@
SANE Library interface for KDE
This library is a part of Kipi-Plugins project (http://www.digikam.org)
-- AUTHORS ------------------------------------------------------------
See AUTHORS file for details.
-- ABOUT --------------------------------------------------------------
Libksane is a KDE interface for SANE library to control flat scanners.
This library is used by kipi-plugins, digiKam and others kipi host programs.
The library documentation is available on header files.
-- DEPENDENCIES -------------------------------------------------------
CMake >= 2.4.x http://www.cmake.org
libqt >= 4.2.x http://www.qtsoftware.com
libkde >= 4.0.x http://www.kde.org
libsane >= 1.0.18 http://www.sane-project.org
-- INSTALL ------------------------------------------------------------
In order to compile, especially when QT3/Qt4 are installed at the same time,
just use something like that:
# export VERBOSE=1
# export QTDIR=/usr/lib/qt4/
# export PATH=$QTDIR/bin:$PATH
# cmake .
# make
Usual CMake options:
-DCMAKE_INSTALL_PREFIX : decide where the program will be install on your computer.
-DCMAKE_BUILD_TYPE : decide which type of build you want. You can chose between "debugfull", "debug", "profile", "relwithdebinfo" and "release". The default is "relwithdebinfo" (-O2 -g).
Compared to old KDE3 autoconf options:
"cmake . -DCMAKE_BUILD_TYPE=debugfull" is equivalent to "./configure --enable-debug=full"
"cmake . -DCMAKE_INSTALL_PREFIX=/usr" is equivalent to "./configure --prefix=/usr"
More details can be found ata this url: http://techbase.kde.org/Development/Tutorials/CMake#Environment_Variables
Note: To know KDE install path on your computer, use 'kde-config --prefix' command line like this (with full debug object enabled):
"cmake . -DCMAKE_BUILD_TYPE=debugfull -DCMAKE_INSTALL_PREFIX=`kde4-config --prefix`"
-- CONTACT ------------------------------------------------------------
If you have questions, comments, suggestions to make do email at:
kde-imaging@kde.org
IRC channel from freenode.net server:
#kde-imaging
-- BUGS ---------------------------------------------------------------
IMPORTANT : the bugreports and wishlist are hosted by the KDE bugs report
system who can be contacted by the standard Kde help menu of plugins dialog.
A mail will be automatically sent to the Kipi mailing list.
There is no need to contact directly the Kipi mailing list for a bug report
or a devel wish.
The current Kipi bugs and devel wish reported to the Kde bugs report can be see
at this url :
http://bugs.kde.org/buglist.cgi?product=kipiplugins&component=libksane&bug_status=UNCONFIRMED&bug_status=NEW&bug_status=ASSIGNED&bug_status=REOPENED

49
libksane/TODO Normal file
View file

@ -0,0 +1,49 @@
TODO list of new features:
* Cleanup the code for closing the device
* Progressive final scan: scan can provide huge image especially in 16 bits color depth.
Send image data to host application by block, not the whole image at once.
# KSaneCore (most signals/slots from KSaneWidget)
QList<KSaneOption*> options() const // handles to sane options
KSaneBasicOptions* createBasicOptions(QWidget *parent=0) const // A widget with current "basic options"
KSaneSpecialOptions* createSpecialOptions(QWidget *parent=0) const // A widget with the rest of the options
void signalPreviewUpdated(QImage *img);
KSaneCore never displays popups and always emits userMessage like signals for user information
# KSaneOption
virtual QWidget* createWidget(QWidget* parent=0) const; // Create a KSaneOptionWidget and connect it to the option
QString saneName() const; // Technical name of the sane option
QString title() const; // Translated option title
QString description() const; // Translated option description
Cleanup public API
# KSaneOptionWidget
Remove label and custom label size code
# KSaneBasicOptions(QWidget *parent=0) // Use private header for basic/Special selection
bool loadOptions(const QList<KSaneOption*> &options)
# KSaneSpecialOptions(QWidget *parent=0) // Use private header for basic/Special selection
bool loadOptions(const QList<KSaneOption*> &options)
# KSanePreview
Figure out how to minimize copying the image data to all possible preview widgets
void "connectToCore"(KSaneCore*) // connect to previewUpdated(..), scanProgress(), ...
# KSaneWidget
Use KSaneCore + KSaneBasicOptions + KSaneSpecialOptions + KSanePreview to create a GUI like the current
Forward userMessage signals if connected or popup a dialog
#General cleanup:
-> enum xxx { }; for easier signal/slot handling
float -> qreal
# Pure Qt library option?

View file

@ -0,0 +1,10 @@
GET_FILENAME_COMPONENT(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH)
GET_FILENAME_COMPONENT(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH)
GET_FILENAME_COMPONENT(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH)
GET_FILENAME_COMPONENT(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH)
find_library(KSANE_LIBRARY NAMES ksane HINTS ${_IMPORT_PREFIX}/lib NO_DEFAULT_PATH)
find_path(KSANE_INCLUDE_DIR NAMES libksane/ksane.h HINTS ${_IMPORT_PREFIX}/include NO_DEFAULT_PATH)
SET(KSANE_LIBRARY "${KSANE_LIBRARY}" CACHE FILEPATH "KSane image scanning library")
SET(KSANE_INCLUDE_DIR "${KSANE_INCLUDE_DIR}" CACHE PATH "Include path for KSane library")
SET(KSANE_FOUND TRUE)

View file

@ -0,0 +1,15 @@
Begin4
Title: libksane
Version: ${KSANE_LIB_VERSION_STRING}
Entered-date: 2007-09-13
Description: libksane is a C++ library for SANE interface to control flat scanners.
Keywords: kde image sane scanner digiKam kipi-plugins
Author: caulier dot gilles at gmail dot com (Gilles Caulier)
kare dot sars at iki dot fi (Kare Sars)
Maintained-by:
Primary-site: http://www.digikam.org
Alternate-site: http://www.digikam.org
Original-site:
Platforms:
Copying-policy: LGPL
End

View file

@ -0,0 +1,12 @@
prefix=${CMAKE_INSTALL_PREFIX}
exec_prefix=${BIN_INSTALL_DIR}
libdir=${LIB_INSTALL_DIR}
includedir=${INCLUDE_INSTALL_DIR}
Name: libksane
Description: libksane is a C++ library for SANE interface to control flat scanners.
URL: http://www.digikam.org
Requires:
Version: ${KSANE_LIB_VERSION_STRING}
Libs: -L${LIB_INSTALL_DIR} -lksane
Cflags: -I${INCLUDE_INSTALL_DIR}

View file

@ -0,0 +1,35 @@
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/../libksane/version.h.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/version.h)
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}/../libksane
${CMAKE_CURRENT_BINARY_DIR})
IF( WIN32 )
ADD_DEFINITIONS( -DMAKE_KSANE_LIB )
ENDIF()
set(ktwain_src
twainiface.cpp
ktwain_widget.cpp
)
KDE4_ADD_LIBRARY(ksane SHARED ${ktwain_src})
TARGET_LINK_LIBRARIES(ksane ${KDE4_KDEUI_LIBS})
SET_TARGET_PROPERTIES(ksane PROPERTIES
VERSION ${KSANE_LIB_SO_VERSION_STRING}
SOVERSION ${KSANE_LIB_SO_CUR_VERSION}
LINK_FLAGS -Wl,-subsystem,console
)
install(TARGETS ksane ${INSTALL_TARGETS_DEFAULT_ARGS} )
INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/../libksane/ksane.h
${CMAKE_CURRENT_SOURCE_DIR}/../libksane/libksane_export.h
${CMAKE_CURRENT_BINARY_DIR}/version.h
DESTINATION ${INCLUDE_INSTALL_DIR}/libksane COMPONENT Devel)
configure_file(../cmake/templates/KSaneConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/KSaneConfig.cmake @ONLY)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/KSaneConfig.cmake
DESTINATION ${LIB_INSTALL_DIR}/cmake/KSane)

View file

@ -0,0 +1,149 @@
/* ============================================================
*
* This file is part of the KDE project
*
* Date : 2009-05-11
* Description : Sane interface for KDE
*
* Copyright (C) 2009 by Kare Sars <kare dot sars at iki dot fi>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================ */
#include "../libksane/ksane.h"
#include "../libksane/ksane.moc"
// Qt includes
#include <QMap>
#include <QHBoxLayout>
#include <QTimer>
#include <QDebug>
// KDE includes
#include <klocalizedstring.h>
#include <kpushbutton.h>
// Local includes
#include "twainiface.h"
namespace KSaneIface
{
KSaneWidget::KSaneWidget(QWidget* parent)
: QWidget(parent), d(new KSaneWidgetPrivate)
{
KPushButton *openDialog = new KPushButton;
openDialog->setText(i18n("Open scan dialog"));
QHBoxLayout *lay = new QHBoxLayout;
lay->addWidget(openDialog);
setLayout(lay);
connect(openDialog, SIGNAL(clicked()), d, SLOT(ReOpenDialog()));
// Forward signals from the private class
//connect(d, SIGNAL(scanProgress(int)), this, SIGNAL(scanProgress(int)));
connect(d, SIGNAL(ImageReady(QByteArray&,int,int,int,int)),
this, SIGNAL(imageReady(QByteArray&,int,int,int,int)));
//connect(d, SIGNAL(scanDone(int,QString)), this, SIGNAL(scanDone(int,QString)));
}
KSaneWidget::~KSaneWidget()
{
delete d;
}
QString KSaneWidget::selectDevice(QWidget* parent)
{
//qDebug() << "KSaneWidget::selectDevice";
return d->SelectSource();
}
bool KSaneWidget::openDevice(const QString &device_name)
{
//qDebug() << "KSaneWidget::openDevice" << device_name;
if (!d->OpenSource(device_name)) return false;
QTimer::singleShot(0, d, SLOT(OpenDialog()));
return true;
}
bool KSaneWidget::closeDevice()
{
//qDebug() << "KSaneWidget::closeDevice";
d->CloseDSM();
return true;
}
QImage KSaneWidget::toQImage(const QByteArray &data,
int width,
int height,
int bytes_per_line,
ImageFormat format)
{
QImage img = QImage::fromData(data, "BMP");
return img;
}
QImage KSaneWidget::toQImageSilent(const QByteArray &data,
int width,
int height,
int bytes_per_line,
ImageFormat format)
{
return KSaneWidget::toQImage(data,
width,
height,
bytes_per_line,
format);
}
void KSaneWidget::scanFinal()
{
}
void KSaneWidget::scanCancel()
{
emit scanProgress(0);
}
// stubbed functions that will not get an implementation any time soon.
QString KSaneWidget::vendor() const {return QString();}
QString KSaneWidget::make() const {return QString();}
QString KSaneWidget::model() const {return QString();}
void KSaneWidget::getOptVals(QMap <QString, QString> &opts) {opts.clear();}
bool KSaneWidget::getOptVal(const QString &optname, QString &value){return false;}
int KSaneWidget::setOptVals(const QMap <QString, QString> &opts) {return 0;}
bool KSaneWidget::setOptVal(const QString &option, const QString &value) {return false;}
void KSaneWidget::setScanButtonText(const QString &scanLabel) {}
void KSaneWidget::setPreviewButtonText(const QString &previewLabel) {}
void KSaneWidget::enableAutoSelect(bool enable) {}
float KSaneWidget::currentDPI() {return 0.0;}
void KSaneWidget::setPreviewResolution(float dpi){Q_UNUSED(dpi);}
void KSaneWidget::setSelection(QPointF lefttop, QPointF rightbottom){Q_UNUSED(lefttop); Q_UNUSED(rightbottom);}
void KSaneWidget::setOptionsCollapsed(bool){}
void KSaneWidget::setScanButtonHidden(bool){}
void KSaneWidget::initGetDeviceList() const {}
} // NameSpace KSaneIface

1977
libksane/ksanetwain/twain.h Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,595 @@
/* ============================================================
*
* This file is a part of kdegraphics
*
* Date : 2009-05-12
* Description : Twain interface
*
* Copyright (C) 2002-2003 Stephan Stapel <stephan dot stapel at web dot de>
* Copyright (C) 2008-2009 by Gilles Caulier <caulier dot gilles at gmail dot com>
* Copyright (C) 2009 by Kare Sars <kare dot sars at iki dot fi>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================ */
// I renamed the class to KSaneWidgetPrivate to remove
// the need for a wrapper class with this name. (Kare)
#include "twainiface.moc"
#include "ksane.h"
#define TWCPP_ANYCOUNT (-1)
#define TWCPP_CANCELTHIS (1)
#define TWCPP_CANCELALL (2)
#define TWCPP_DOTRANSFER (0)
#include <QtGlobal>
#include <QDebug>
#include <cstring>
namespace KSaneIface
{
KSaneWidgetPrivate::KSaneWidgetPrivate(): QWidget(0)
{
// This is a dumy widget not visible. We use Qwidget to dispatch Windows event to
// Twain interface. This is not possible to do it using QObject as well.
m_hMessageWnd = 0;
m_hTwainDLL = NULL;
m_pDSMProc = NULL;
m_bDSOpen = false;
m_bDSMOpen = false;
m_bSourceEnabled = false;
m_bModalUI = true;
m_nImageCount = TWCPP_ANYCOUNT;
InitTwain();
}
KSaneWidgetPrivate::~KSaneWidgetPrivate()
{
ReleaseTwain();
}
bool KSaneWidgetPrivate::winEvent(MSG* pMsg, long* result)
{
return ProcessMessage(*pMsg);
}
/** Initializes TWAIN interface . Is already called from the constructor.
It should be called again if ReleaseTwain is called.
hWnd is the window which has to subclassed in order to receive
Twain messaged. Normally - this would be your main application window.
*/
bool KSaneWidgetPrivate::InitTwain()
{
char libName[512];
if((m_hTwainDLL && m_pDSMProc)) {
return true;
}
memset(&m_AppId,0,sizeof(m_AppId));
if(!IsWindow(this->winId())) {
return false;
}
m_hMessageWnd = this->winId();
strcpy(libName, "TWAIN_32.DLL");
m_hTwainDLL = LoadLibraryA(libName);
if(m_hTwainDLL != NULL)
{
if(!(m_pDSMProc = (DSMENTRYPROC)GetProcAddress(m_hTwainDLL, (LPCSTR)MAKEINTRESOURCE(1))))
{
FreeLibrary(m_hTwainDLL);
m_hTwainDLL = NULL;
}
}
if((m_hTwainDLL && m_pDSMProc))
{
// Expects all the fields in m_AppId to be set except for the id field.
m_AppId.Id = 0; // Initialize to 0 (Source Manager will assign real value)
m_AppId.Version.MajorNum = 0; // Your app's version number
m_AppId.Version.MinorNum = 2;
m_AppId.Version.Language = TWLG_USA;
m_AppId.Version.Country = TWCY_USA;
strcpy(m_AppId.Version.Info, "libksane");
m_AppId.ProtocolMajor = TWON_PROTOCOLMAJOR;
m_AppId.ProtocolMinor = TWON_PROTOCOLMINOR;
m_AppId.SupportedGroups = DG_IMAGE | DG_CONTROL;
strcpy(m_AppId.Manufacturer, "KDE");
strcpy(m_AppId.ProductFamily, "Generic");
strcpy(m_AppId.ProductName, "libksane");
m_bDSMOpen= CallTwainProc(&m_AppId, NULL, DG_CONTROL,
DAT_PARENT, MSG_OPENDSM, (TW_MEMREF)&m_hMessageWnd);
return true;
}
else {
return false;
}
}
/** Releases the twain interface . Need not be called unless you
want to specifically shut it down.
*/
void KSaneWidgetPrivate::ReleaseTwain()
{
if((m_hTwainDLL && m_pDSMProc))
{
CloseDSM();
FreeLibrary(m_hTwainDLL);
m_hTwainDLL = NULL;
m_pDSMProc = NULL;
}
}
/** Entry point into Twain. For a complete description of this
routine please refer to the Twain specification 1.8
*/
bool KSaneWidgetPrivate::CallTwainProc(pTW_IDENTITY pOrigin, pTW_IDENTITY pDest,
TW_UINT32 DG, TW_UINT16 DAT, TW_UINT16 MSG, TW_MEMREF pData)
{
if (!(m_hTwainDLL && m_pDSMProc)) {
m_returnCode = TWRC_FAILURE;
return false;
}
m_returnCode = (*m_pDSMProc)(pOrigin, pDest, DG, DAT, MSG, pData);
if(m_returnCode == TWRC_FAILURE) {
(*m_pDSMProc)(pOrigin, pDest, DG_CONTROL, DAT_STATUS, MSG_GET, &m_Status);
}
return (m_returnCode == TWRC_SUCCESS);
}
/** Called to display a dialog box to select the Twain source to use.
This can be overridden if a list of all sources is available
to the application. These sources can be enumerated by Twain.
it is not yet supportted by KSaneWidgetPrivate.
*/
QString KSaneWidgetPrivate::SelectSource()
{
TW_IDENTITY src;
memset(&src, 0, sizeof(src));
// debug printouts
bool ret_ok = CallTwainProc(&m_AppId, NULL, DG_CONTROL, DAT_IDENTITY, MSG_GETFIRST, &src);
while (ret_ok) {
ret_ok = CallTwainProc(&m_AppId, NULL, DG_CONTROL, DAT_IDENTITY, MSG_GETNEXT, &src);
}
// set the default entry selected
CallTwainProc(&m_AppId, NULL, DG_CONTROL, DAT_IDENTITY, MSG_GETDEFAULT, &src);
// now open the selection dialog
if (!CallTwainProc(&m_AppId, NULL, DG_CONTROL, DAT_IDENTITY, MSG_USERSELECT, &src)) {
return QString();
}
QString source;
source += src.ProductName;
source += ';';
source += src.ProductFamily;
source += ';';
source += src.Manufacturer;
//qDebug()<< source;
return source;
}
/** Closes the Data Source
*/
void KSaneWidgetPrivate::CloseDS()
{
if(DSOpen()) {
if(m_bSourceEnabled) {
TW_USERINTERFACE twUI;
if(CallTwainProc(&m_AppId, &m_Source, DG_CONTROL,
DAT_USERINTERFACE, MSG_DISABLEDS, &twUI)) {
m_bSourceEnabled = false;
}
}
CallTwainProc(&m_AppId, NULL, DG_CONTROL,
DAT_IDENTITY, MSG_CLOSEDS, (TW_MEMREF)&m_Source);
m_bDSOpen = false;
}
}
/** Closes the Data Source Manager */
void KSaneWidgetPrivate::CloseDSM()
{
if(m_hTwainDLL && m_pDSMProc && m_bDSMOpen) {
CloseDS();
CallTwainProc(&m_AppId, NULL, DG_CONTROL, DAT_PARENT, MSG_CLOSEDSM, (TW_MEMREF)&m_hMessageWnd);
m_bDSMOpen = false;
}
}
/** Returns true if the Data Source is Open */
bool KSaneWidgetPrivate::DSOpen() const
{
//qDebug() << m_hTwainDLL << m_pDSMProc << m_bDSMOpen << m_bDSOpen;
return (m_hTwainDLL && m_pDSMProc) && m_bDSMOpen && m_bDSOpen;
}
/** Opens a Data Source */
bool KSaneWidgetPrivate::OpenSource(const QString &source)
{
if (source.isEmpty()) {
return false;
}
QStringList splited = source.split(';');
if (splited.size() != 3) {
return false;
}
// go thorough the list and check if the source is available
bool ret_ok = CallTwainProc(&m_AppId, NULL, DG_CONTROL, DAT_IDENTITY, MSG_GETFIRST, &m_Source);
while (ret_ok) {
//qDebug() << m_Source.Id << m_Source.Version.MajorNum << m_Source.Version.MinorNum;
//qDebug() << m_Source.Manufacturer << m_Source.ProductFamily << m_Source.ProductName;
if (QString(m_Source.ProductName) == splited[0]) break;
ret_ok = CallTwainProc(&m_AppId, NULL, DG_CONTROL, DAT_IDENTITY, MSG_GETNEXT, &m_Source);
}
if (!ret_ok) {
// CallTwainProc failed when reading beyond the last source
return false;
}
// open the source
if (m_hTwainDLL && m_pDSMProc && m_bDSMOpen) {
m_bDSOpen = CallTwainProc(&m_AppId, NULL, DG_CONTROL, DAT_IDENTITY, MSG_OPENDS, (TW_MEMREF)&m_Source);
//qDebug() << "OpenSource(qst..) m_bDSOpen" << m_bDSOpen;
}
SetImageCount(TWCPP_ANYCOUNT);
return DSOpen();
}
/** Re-Opens a Data Source */
bool KSaneWidgetPrivate::ReOpenDialog()
{
//qDebug() << "ReOpenSource:" << m_hTwainDLL << m_pDSMProc << m_bDSMOpen << m_bDSOpen;
if (DSOpen()) {
// already open
return true;
}
// open the source
if (m_hTwainDLL && m_pDSMProc && m_bDSMOpen) {
m_bDSOpen = CallTwainProc(&m_AppId, NULL, DG_CONTROL, DAT_IDENTITY, MSG_OPENDS, (TW_MEMREF)&m_Source);
//qDebug() << "ReOpenSource() m_bDSOpen" << m_bDSOpen;
}
SetImageCount(TWCPP_ANYCOUNT);
if (DSOpen()) {
return EnableSource(true);
}
//else
return false;
}
/** Should be called from the main message loop of the application. Can always be called,
it will not process the message unless a scan is in progress. */
bool KSaneWidgetPrivate::ProcessMessage(MSG msg)
{
// TODO: don't really know why...
if (msg.message == 528) return false;
if (m_hMessageWnd == 0) return false;
if(m_bSourceEnabled) {
TW_UINT16 twRC = TWRC_NOTDSEVENT;
TW_EVENT twEvent;
twEvent.pEvent = (TW_MEMREF)&msg;
//memset(&twEvent, 0, sizeof(TW_EVENT));
twEvent.TWMessage = MSG_NULL;
CallTwainProc(&m_AppId, &m_Source, DG_CONTROL,
DAT_EVENT, MSG_PROCESSEVENT, (TW_MEMREF)&twEvent);
if(m_returnCode != TWRC_NOTDSEVENT) {
TranslateMessage(twEvent);
}
return (twRC==TWRC_DSEVENT);
}
return false;
}
/** Queries the capability of the Twain Data Source */
bool KSaneWidgetPrivate::GetCapability(TW_CAPABILITY& twCap, TW_UINT16 cap, TW_UINT16 conType)
{
if(DSOpen())
{
twCap.Cap = cap;
twCap.ConType = conType;
twCap.hContainer = NULL;
if(CallTwainProc(&m_AppId, &m_Source, DG_CONTROL,
DAT_CAPABILITY, MSG_GET, (TW_MEMREF)&twCap))
{
return true;
}
}
return false;
}
/** Queries the capability of the Twain Data Source */
bool KSaneWidgetPrivate::GetCapability(TW_UINT16 cap, TW_UINT32& value)
{
TW_CAPABILITY twCap;
if(GetCapability(twCap, cap))
{
pTW_ONEVALUE pVal;
pVal = (pTW_ONEVALUE )GlobalLock(twCap.hContainer);
if(pVal)
{
value = pVal->Item;
GlobalUnlock(pVal);
GlobalFree(twCap.hContainer);
return true;
}
}
return false;
}
/** Sets the capability of the Twain Data Source */
bool KSaneWidgetPrivate::SetCapability(TW_UINT16 cap, TW_UINT16 value, bool sign)
{
if(DSOpen()) {
TW_CAPABILITY twCap;
pTW_ONEVALUE pVal;
bool ret_value = false;
twCap.Cap = cap;
twCap.ConType = TWON_ONEVALUE;
twCap.hContainer = GlobalAlloc(GHND,sizeof(TW_ONEVALUE));
if(twCap.hContainer) {
pVal = (pTW_ONEVALUE)GlobalLock(twCap.hContainer);
pVal->ItemType = sign ? TWTY_INT16 : TWTY_UINT16;
pVal->Item = (TW_UINT32)value;
GlobalUnlock(twCap.hContainer);
ret_value = SetCapability(twCap);
GlobalFree(twCap.hContainer);
}
return ret_value;
}
return false;
}
/** Sets the capability of the Twain Data Source */
bool KSaneWidgetPrivate::SetCapability(TW_CAPABILITY& cap)
{
if(DSOpen()) {
return CallTwainProc(&m_AppId, &m_Source, DG_CONTROL,
DAT_CAPABILITY, MSG_SET, (TW_MEMREF)&cap);
}
return false;
}
/** Sets the number of images which can be accpeted by the application at one time */
bool KSaneWidgetPrivate::SetImageCount(TW_INT16 nCount)
{
if(SetCapability(CAP_XFERCOUNT,(TW_UINT16)nCount,true)) {
m_nImageCount = nCount;
return true;
}
else {
if(m_returnCode == TWRC_CHECKSTATUS) {
TW_UINT32 count = 0;
if(GetCapability(CAP_XFERCOUNT, count)) {
nCount = (TW_INT16)count;
if(SetCapability(CAP_XFERCOUNT, nCount)) {
m_nImageCount = nCount;
return true;
}
}
}
}
return false;
}
/** Called to enable the Twain Acquire Dialog. This too can be
* overridden but is a helluva job. */
bool KSaneWidgetPrivate::OpenDialog()
{
EnableSource(true);
return true;
}
/** Called to enable the Twain Acquire Dialog. This too can be
* overridden but is a helluva job. */
bool KSaneWidgetPrivate::EnableSource(bool showUI)
{
//qDebug() << "DSOpen() =" << DSOpen();
if(DSOpen() && !m_bSourceEnabled) {
TW_USERINTERFACE twUI;
twUI.ShowUI = showUI;
twUI.hParent = (TW_HANDLE)m_hMessageWnd;
if(CallTwainProc(&m_AppId, &m_Source, DG_CONTROL,
DAT_USERINTERFACE, MSG_ENABLEDS, (TW_MEMREF)&twUI))
{
m_bSourceEnabled = true;
m_bModalUI = twUI.ModalUI;
}
else {
m_bSourceEnabled = false;
m_bModalUI = true;
}
//qDebug() << "EnableSource:ModalUI=" << twUI.ModalUI;
return m_bSourceEnabled;
}
return false;
}
/** Called by ProcessMessage to Translate a TWAIN message */
void KSaneWidgetPrivate::TranslateMessage(TW_EVENT& twEvent)
{
switch(twEvent.TWMessage)
{
case MSG_XFERREADY:
//qDebug() << "MSG_XFERREADY";
TransferImage();
break;
case MSG_CLOSEDSREQ:
//qDebug() << "MSG_CLOSEDSREQ";
CloseDS();
break;
}
}
/** Gets Imageinfo for an image which is about to be transferred. */
bool KSaneWidgetPrivate::GetImageInfo(TW_IMAGEINFO& info)
{
if(m_bSourceEnabled) {
return CallTwainProc(&m_AppId, &m_Source, DG_IMAGE,
DAT_IMAGEINFO, MSG_GET, (TW_MEMREF)&info);
}
return false;
}
/** Transfers the image or cancels the transfer depending on the state of the TWAIN system */
void KSaneWidgetPrivate::TransferImage()
{
TW_IMAGEINFO info;
bool bContinue=true;
while(bContinue) {
if(GetImageInfo(info)) {
int permission = TWCPP_DOTRANSFER;
switch(permission)
{
case TWCPP_CANCELTHIS:
bContinue=EndTransfer();
break;
case TWCPP_CANCELALL:
CancelTransfer();
bContinue=false;
break;
case TWCPP_DOTRANSFER:
bContinue=GetImage(info);
break;
}
}
}
}
/** Ends the current transfer.
Returns true if the more images are pending */
bool KSaneWidgetPrivate::EndTransfer()
{
TW_PENDINGXFERS twPend;
if(CallTwainProc(&m_AppId, &m_Source, DG_CONTROL,
DAT_PENDINGXFERS, MSG_ENDXFER, (TW_MEMREF)&twPend))
{
return twPend.Count != 0;
}
return false;
}
/** Aborts all transfers */
void KSaneWidgetPrivate::CancelTransfer()
{
TW_PENDINGXFERS twPend;
CallTwainProc(&m_AppId, &m_Source, DG_CONTROL, DAT_PENDINGXFERS, MSG_RESET, (TW_MEMREF)&twPend);
}
/** Calls TWAIN to actually get the image */
bool KSaneWidgetPrivate::GetImage(TW_IMAGEINFO& info)
{
TW_MEMREF pdata;
CallTwainProc(&m_AppId, &m_Source, DG_IMAGE, DAT_IMAGENATIVEXFER, MSG_GET, &pdata);
switch(m_returnCode)
{
case TWRC_XFERDONE:
//qDebug()<< "GetImage:TWRC_XFERDONE";
ImageData(pdata, info);
break;
case TWRC_CANCEL:
//qDebug()<< "GetImage:TWRC_CANCEL";
break;
case TWRC_FAILURE:
//qDebug()<< "GetImage:TWRC_FAILURE";
CancelTransfer();
return false;
break;
}
GlobalFree(pdata);
return EndTransfer();
}
void KSaneWidgetPrivate::ImageData(TW_MEMREF pdata, TW_IMAGEINFO& info)
{
if (pdata && (info.ImageWidth != -1) && (info.ImageLength != - 1))
{
// Under Windows, Twain interface return a DIB data structure.
// See http://en.wikipedia.org/wiki/Device-independent_bitmap#DIBs_in_memory for details.
HGLOBAL hDIB = (HGLOBAL)(qptrdiff)pdata;
int size = (int)GlobalSize(hDIB);
const char* bits = (const char*)GlobalLock(hDIB);
// DIB is BMP without header. we will add it to load data in QImage using std loader from Qt.
QByteArray baBmp;
QDataStream ds(&baBmp, QIODevice::WriteOnly);
ds.writeRawData("BM", 2);
qint32 filesize = size + 14;
ds << filesize;
qint16 reserved = 0;
ds << reserved;
ds << reserved;
qint32 pixOffset = 14 + 40 + 0;
ds << pixOffset;
ds.writeRawData(bits, size);
emit ImageReady(baBmp, 0,0,0, (int)KSaneWidget::FormatBMP);
GlobalUnlock(hDIB);
}
}
} // namespace KSaneIface

View file

@ -0,0 +1,127 @@
/* ============================================================
*
* This file is a part of kdegraphics
*
* Date : 2009-05-12
* Description : Twain interface
*
* Copyright (C) 2002-2003 Stephan Stapel <stephan dot stapel at web dot de>
* Copyright (C) 2008-2009 by Gilles Caulier <caulier dot gilles at gmail dot com>
* Copyright (C) 2009 by Kare Sars <kare dot sars at iki dot fi>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================ */
#ifndef TWAINIFACE_H
#define TWAINIFACE_H
#include "twain.h"
// Windows includes
#include <windows.h>
#include <QWidget>
namespace KSaneIface
{
class KSaneWidgetPrivate : public QWidget
{
Q_OBJECT
public:
KSaneWidgetPrivate();
~KSaneWidgetPrivate();
/**
* Hook-in. See class documentation for details!
* @result One should return false to get the message being
* processed by the application (should return false by default!)
*/
bool winEvent(MSG* pMsg, long *result);
void CloseDSM();
QString SelectSource();
bool OpenSource(const QString &device);
public Q_SLOTS:
bool OpenDialog();
bool ReOpenDialog();
Q_SIGNALS:
void ImageReady(QByteArray &data, int width, int height, int bytes_per_line, int format);
private:
bool InitTwain();
void ReleaseTwain();
bool ProcessMessage(MSG msg);
bool SetImageCount(TW_INT16 nCount=1);
bool DSOpen() const;
bool CallTwainProc(pTW_IDENTITY pOrigin, pTW_IDENTITY pDest,
TW_UINT32 DG, TW_UINT16 DAT, TW_UINT16 MSG,
TW_MEMREF pData);
bool EnableSource(bool showUI);
void CloseDS();
bool GetCapability(TW_CAPABILITY& twCap, TW_UINT16 cap, TW_UINT16 conType=TWON_DONTCARE16);
bool GetCapability(TW_UINT16 cap, TW_UINT32& value);
bool SetCapability(TW_UINT16 cap, TW_UINT16 value, bool sign=false);
bool SetCapability(TW_CAPABILITY& twCap);
bool GetImageInfo(TW_IMAGEINFO& info);
void TranslateMessage(TW_EVENT& twEvent);
void TransferImage();
bool EndTransfer();
void CancelTransfer();
bool GetImage(TW_IMAGEINFO& info);
void ImageData(TW_MEMREF pdata, TW_IMAGEINFO& info);
protected:
bool m_bDSMOpen;
bool m_bDSOpen;
bool m_bSourceEnabled;
bool m_bModalUI;
int m_nImageCount;
HINSTANCE m_hTwainDLL;
DSMENTRYPROC m_pDSMProc;
TW_IDENTITY m_AppId;
TW_IDENTITY m_Source;
TW_STATUS m_Status;
TW_INT16 m_returnCode;
HWND m_hMessageWnd;
};
} // namespace KSaneIface
#endif /* TWAINIFACE_H */

View file

@ -0,0 +1,79 @@
INCLUDE_DIRECTORIES(${SANE_INCLUDE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/options
${CMAKE_CURRENT_SOURCE_DIR}/widgets
)
SET(ksane_LIB_SRCS
widgets/gamma_disp.cpp
widgets/labeled_gamma.cpp
widgets/labeled_checkbox.cpp
widgets/labeled_entry.cpp
widgets/labeled_combo.cpp
widgets/labeled_fslider.cpp
widgets/labeled_slider.cpp
widgets/ksane_button.cpp
widgets/ksane_option_widget.cpp
ksane_viewer.cpp
selectionitem.cpp
ksane_device_dialog.cpp
ksane_find_devices_thread.cpp
ksane_widget.cpp
ksane_scan_thread.cpp
ksane_preview_thread.cpp
ksane_widget_private.cpp
splittercollapser.cpp
ksane_auth.cpp
options/ksane_option.cpp
options/ksane_opt_button.cpp
options/ksane_opt_checkbox.cpp
options/ksane_opt_entry.cpp
options/ksane_opt_gamma.cpp
options/ksane_opt_slider.cpp
options/ksane_opt_fslider.cpp
options/ksane_opt_combo.cpp
)
KDE4_ADD_LIBRARY(ksane SHARED ${ksane_LIB_SRCS})
TARGET_LINK_LIBRARIES(ksane ${KDE4_KDEUI_LIBS}
${SANE_LIBRARY}
)
SET_TARGET_PROPERTIES(ksane PROPERTIES VERSION ${KSANE_LIB_SO_VERSION_STRING} SOVERSION ${KSANE_LIB_SO_CUR_VERSION})
OPTION(COMPILE_VIEWER_TESTAPP "Compile a small test application for the viewer")
IF (COMPILE_VIEWER_TESTAPP)
message("Compile testapp")
kde4_add_executable(viewer_test ksane_viewer.cpp ksane_viewer_test.cpp selectionitem.cpp)
target_link_libraries(viewer_test ${KDE4_KDEUI_LIBS})
ENDIF()
INSTALL(TARGETS ksane ${INSTALL_TARGETS_DEFAULT_ARGS} )
CONFIGURE_FILE(../cmake/templates/KSaneConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/KSaneConfig.cmake @ONLY)
# Check if compilation is done through digiKam SC or not. If yes, do not install header files.
IF (NOT DIGIKAMSC_COMPILE_LIBKSANE)
INSTALL(FILES ksane.h
libksane_export.h
${CMAKE_CURRENT_BINARY_DIR}/version.h
DESTINATION ${INCLUDE_INSTALL_DIR}/libksane COMPONENT Devel)
IF(NOT WIN32)
CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/cmake/templates/libksane.pc.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/libksane.pc)
CONFIGURE_FILE(${CMAKE_SOURCE_DIR}/cmake/templates/libksane.lsm.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/libksane.lsm)
INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/libksane.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig )
ENDIF(NOT WIN32)
# Install find cmake script to the system for client applications.
INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/KSaneConfig.cmake
DESTINATION ${LIB_INSTALL_DIR}/cmake/KSane)
ENDIF()
KDE4_INSTALL_ICONS(${ICON_INSTALL_DIR})

View file

@ -0,0 +1,15 @@
/** @mainpage libKSane
@brief A library for dealing with scanners
LibKSane is a KDE interface for SANE library to control flat scanners.
This library provides a widget to control a scanner, KSaneWidget. Internally,
it will use the <a href="http://www.sane-project.org/">SANE</a> library (or
directly use TWAIN on Windows if SANE is not available).
@see KSaneWidget
*/
// vim:ft=doxygen

3
libksane/libksane/Messages.sh Executable file
View file

@ -0,0 +1,3 @@
#! /bin/sh
$XGETTEXT `find . -name \*.cpp` ../ksanetwain/*.cpp -o $podir/libksane.pot

View file

@ -0,0 +1,33 @@
// krazy:skip
//begin strings from hplip-3.9.2/scan/sane/common.h to make them translatable
I18N_NOOP("None");
I18N_NOOP("MH");
I18N_NOOP("MR");
I18N_NOOP("MMR");
I18N_NOOP("JPEG");
I18N_NOOP("Auto");
I18N_NOOP("Flatbed");
I18N_NOOP("ADF");
I18N_NOOP("Advanced");
I18N_NOOP("Compression");
I18N_NOOP("Selects the scanner compression "\
"method for faster scans, possibly at the expense of image quality.");
I18N_NOOP("JPEG compression factor");
I18N_NOOP("Sets the scanner JPEG compression "\
"factor. Larger numbers mean better compression, " \
"and smaller numbers mean better image quality.");
I18N_NOOP("Batch scan");
I18N_NOOP("Enables continuous scanning with automatic document feeder (ADF).");
I18N_NOOP("Duplex");
I18N_NOOP("Enables scanning on both sides of the page.");
I18N_NOOP("Geometry");
I18N_NOOP("Length measurement");
I18N_NOOP("Selects how the scanned image "\
"length is measured and reported, which is impossible to know in advance for scrollfed scans.");
I18N_NOOP("Unknown");
I18N_NOOP("Unlimited");
I18N_NOOP("Approximate");
I18N_NOOP("Padded");
I18N_NOOP("Exact");
I18N_NOOP("???");
//end strings from hplip-3.9.2/scan/sane/common.h to make them translatable

Binary file not shown.

After

Width:  |  Height:  |  Size: 129 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 803 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 B

307
libksane/libksane/ksane.h Normal file
View file

@ -0,0 +1,307 @@
/* ============================================================
*
* This file is part of the KDE project
*
* Date : 2007-09-13
* Description : Sane interface for KDE
*
* Copyright (C) 2007-2010 by Kare Sars <kare dot sars at iki dot fi>
* Copyright (C) 2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================ */
#ifndef KSANE_H
#define KSANE_H
// Qt includes
#include <QtGui/QWidget>
// Local includes
#include "libksane_export.h"
/** This namespace collects all methods and classes in LibKSane. */
namespace KSaneIface
{
class KSaneWidgetPrivate;
/**
* This class provides the widget containing the scan options and the preview.
* @author Kare Sars <kare.sars@iki.fi>
*/
class LIBKSANE_EXPORT KSaneWidget : public QWidget
{
Q_OBJECT
friend class KSaneWidgetPrivate;
public:
/** This enumeration describes the type of the returned data.
* The number of formats might grow, so it is wise to be prepared fro more.*/
typedef enum
{
FormatBlackWhite, /**< One bit per pixel 1 = black 0 = white */
FormatGrayScale8, /**< Grayscale with one byte per pixel 0 = black 255 = white */
FormatGrayScale16, /**< Grayscale withtTwo bytes per pixel.
* The byte order is the one provided by libsane. */
FormatRGB_8_C, /**< Every pixel consists of three colors in the order Read,
* Grean and Blue, with one byte per color (no alpha channel). */
FormatRGB_16_C, /**< Every pixel consists of three colors in the order Read,
* Grean and Blue, with two bytes per color(no alpha channel).
* The byte order is the one provided by libsane. */
FormatBMP, /**< The image data is returned as a BMP. */
FormatNone = 0xFFFF /**< This enumeration value should never be returned to the user */
} ImageFormat;
/** @note There might come more enumerations in the future. */
typedef enum
{
NoError, /**< The scanning was finished successfully.*/
ErrorCannotSegment, /**< If this error status is returned libksane can not segment the
* returned data. Scanning without segmentation should work.
* @note segmentation is not implemented yet.*/
ErrorGeneral, /**< The error string should contain an error message. */
Information /**< There is some information to the user. */
} ScanStatus;
struct DeviceInfo
{
QString name; /* unique device name */
QString vendor; /* device vendor string */
QString model; /* device model name */
QString type; /* device type (e.g., "flatbed scanner") */
};
/** This constructor initializes the private class variables, but the widget is left empty.
* The options and the preview are added with the call to openDevice(). */
KSaneWidget(QWidget* parent=0);
/** Standard destructor */
~KSaneWidget();
/** This helper method displays a dialog for selecting a scanner. The libsane
* device name of the selected scanner device is returned. */
QString selectDevice(QWidget* parent=0);
/**
* Get the list of available scanning devices. Connect to availableDevices()
* which is fired once these devices are known.
*/
void initGetDeviceList() const;
/** This method opens the specified scanner device and adds the scan options to the
* KSane widget.
* @param device_name is the libsane device name for the scanner to open.
* @return 'true' if all goes well and 'false' if the specified scanner can not be opened. */
bool openDevice(const QString &device_name);
/** This method closes the currently open scanner device.
* @return 'true' if all goes well and 'false' if no device is open. */
bool closeDevice();
KDE_DEPRECATED bool makeQImage(const QByteArray &, int, int, int, ImageFormat, QImage &);
/**
* This is a convenience method that can be used to create a QImage from the image data
* returned by the imageReady(...) signal.
* @note: If the image data has 16 bits/color the * data is truncated to 8 bits/color
* since QImage does not support 16 bits/color. A warning message will be shown.
*
* @param data is the byte data containing the image.
* @param width is the width of the image in pixels.
* @param height is the height of the image in pixels.
* @param bytes_per_line is the number of bytes used per line. This might include padding
* and is probably only relevant for 'FormatBlackWhite'.
* @param format is the KSane image format of the data.
* @return This function returns the provided image data as a QImage. */
QImage toQImage(const QByteArray &data,
int width,
int height,
int bytes_per_line,
ImageFormat format);
/**
* This is a convenience method that can be used to create a QImage from the image data
* returned by the imageReady(...) signal.
* @note: If the image data has 16 bits/color the * data is truncated to 8 bits/color, but
* unlike toQImage() this function will not give a warning.
*
* @param data is the byte data containing the image.
* @param width is the width of the image in pixels.
* @param height is the height of the image in pixels.
* @param bytes_per_line is the number of bytes used per line. This might include padding
* and is probably only relevant for 'FormatBlackWhite'.
* @param format is the KSane image format of the data.
* @return This function returns the provided image data as a QImage. */
QImage toQImageSilent(const QByteArray &data,
int width,
int height,
int bytes_per_line,
ImageFormat format);
/** This method returns the vendor name of the scanner (Same as make). */
QString vendor() const;
/** This method returns the make name of the scanner. */
QString make() const;
/** This methos returns the model of the scanner. */
QString model() const;
/** This method returns the current resolution of the acquired image,
* in dots per inch.
* @note This function should be called from the slot connected
* to the imageReady signal. The connection should not be queued.
* @return the resolution used for scanning or 0.0 on failure. */
float currentDPI();
/** This method returns the scan area's width in mm
* @return Width of the scannable area in mm */
float scanAreaWidth();
/** This method returns the scan area's height in mm
* @return Height of the scannable area in mm */
float scanAreaHeight();
/** This method sets the selection according to the given points
* @note The points are defined with respect to the scan areas top-left corner in mm
* @param topLeft Upper left corner of the selection (in mm)
* @param bottomRight Lower right corner of the selection (in mm) */
void setSelection(QPointF topLeft, QPointF bottomRight);
/** This function is used to set the preferred resolution for scanning the preview.
* @param dpi is the wanted scan resolution for the preview
* @note if the set value is not supported, the cloasest one is used
* @note setting the value 0 means that the default calculated value should be used */
void setPreviewResolution(float dpi);
/** This method reads the available parameters and their values and
* returns them in a QMap (Name, value)
* @param opts is a QMap with the parameter names and values. */
void getOptVals(QMap <QString, QString> &opts);
/** This method can be used to write many parameter values at once.
* @param opts is a QMap with the parameter names and values.
* @return This function returns the number of successful writes. */
int setOptVals(const QMap <QString, QString> &opts);
/** This function reads one parameter value into a string.
* @param optname is the name of the parameter to read.
* @param value is the string representation of the value.
* @return this function returns true if the read was successful. */
bool getOptVal(const QString &optname, QString &value);
/** This function writes one parameter value into a string.
* @param optname is the name of the parameter to write.
* @param value is the string representation of the value.
* @return this function returns true if the write was successful. */
bool setOptVal(const QString &optname, const QString &value);
/** This function sets the label on the final scan button
* @param scanLabel is the new label for the button. */
void setScanButtonText(const QString &scanLabel);
/** This function sets the label on the preview button
* @param previewLabel is the new label for the button. */
void setPreviewButtonText(const QString &previewLabel);
/** This function can be used to enable/disable automatic selections on previews.
* The default state is enabled.
* @param enable specifies if the auto selection should be turned on or off. */
void enableAutoSelect(bool enable);
/** This function is used to programatically collapse/restore the options.
* @param collapse defines the state to set. */
void setOptionsCollapsed(bool collapse);
/** This function is used hide/show the final scan button.
* @param hidden defines the state to set. */
void setScanButtonHidden(bool hidden);
public Q_SLOTS:
/** This method can be used to cancel a scan or prevent an automatic new scan. */
void scanCancel();
/** This method can be used to start a scan (if no GUI is needed).
* @note libksane may return one or more images as a result of one invocation of this slot.
* If no more images are wanted scanCancel should be called in the slot handling the
* imageReady signal. */
void scanFinal();
Q_SIGNALS:
/**
* This Signal is emitted when a final scan is ready.
* @param data is the byte data containing the image.
* @param width is the width of the image in pixels.
* @param height is the height of the image in pixels.
* @param bytes_per_line is the number of bytes used per line. This might include padding
* and is probably only relevant for 'FormatBlackWhite'.
* @param format is the KSane image format of the data. */
void imageReady(QByteArray &data, int width, int height,
int bytes_per_line, int format);
/**
* This signal is emitted when the scanning has ended.
* @param status contains a ScanStatus status code.
* @param strStatus If an error has occurred this string will contain an error message.
* otherwise the string is empty. */
void scanDone(int status, const QString &strStatus);
/**
* This signal is emitted when the user is to be notified about something.
* @note If no slot is connected to this signal the message will be displayed in a KMessageBox.
* @param type contains a ScanStatus code to identify the type of message (error/info/...).
* @param msg is the message to the user.
* otherwise the string is empty. */
void userMessage(int type, const QString &strStatus);
/**
* This Signal is emitted for progress information during a scan.
* The GUI already has a progress bar, but if the GUI is hidden,
* this can be used to display a progress bar.
* @param percent is the percentage of the scan progress (0-100). */
void scanProgress(int percent);
/**
* This signal is emitted every time the device list is updated or
* after initGetDeviceList() is called.
* @param deviceList is a QList of KSaneWidget::DeviceInfo that contain the
* device name, model, vendor and type of the attached scanners.
* @note The list is only a snapshot of the current available devices. Devices
* might be added or removed/opened after the signal is emitted.
*/
void availableDevices(const QList<KSaneWidget::DeviceInfo> &deviceList);
/**
* This Signal is emitted when a hardware button is pressed.
* @param optionName is the untranslated technical name of the sane-option.
* @param optionLabel is the translated user visible label of the sane-option.
* @param pressed indicates if the value is true or false.
* @note The SANE standard does not specify hardware buttons and their behaviors,
* so this signal is emitted for sane-options that behave like hardware buttons.
* That is the sane-options are read-only and type boolean. The naming of hardware
* buttons also differ from backend to backend.
*/
void buttonPressed(const QString &optionName, const QString &optionLabel, bool pressed);
private:
KSaneWidgetPrivate * const d;
};
} // NameSpace KSaneIface
#endif // SANE_WIDGET_H

View file

@ -0,0 +1,136 @@
/* ============================================================
*
* This file is part of the KDE project
*
* Date : 2010
* Description : Sane authentication helpers.
*
* Copyright (C) 2010 by Kare Sars <kare dot sars at iki dot fi>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================ */
#include "ksane_auth.h"
// Qt includes
#include <QMutex>
#include <QList>
// KDE includes
#include <KDebug>
namespace KSaneIface
{
static KSaneAuth *s_instance = 0;
static QMutex s_mutex;
struct KSaneAuth::Private
{
struct AuthStruct
{
QString resource;
QString username;
QString password;
};
QList<AuthStruct> authList;
};
KSaneAuth *KSaneAuth::getInstance()
{
s_mutex.lock();
if (s_instance == 0) {
s_instance = new KSaneAuth();
}
s_mutex.unlock();
return s_instance;
}
KSaneAuth::KSaneAuth() : d(new Private) {}
KSaneAuth::~KSaneAuth()
{
d->authList.clear();
delete d;
}
void KSaneAuth::setDeviceAuth(const QString &resource, const QString &username, const QString &password)
{
// This is a short list so we do not need a QMap...
int i;
for (i=0; i<d->authList.size(); i++) {
if (resource == d->authList.at(i).resource) {
// update the existing node
d->authList[i].username = username;
d->authList[i].password = password;
break;
}
}
if (i==d->authList.size()) {
// Add a new list node
Private::AuthStruct tmp;
tmp.resource = resource;
tmp.username = username;
tmp.password = password;
d->authList << tmp;
}
}
void KSaneAuth::clearDeviceAuth(const QString &resource)
{
// This is a short list so we do not need a QMap...
for (int i=0; i<d->authList.size(); i++) {
if (resource == d->authList.at(i).resource) {
d->authList.removeAt(i);
return;
}
}
}
/** static function called by sane_open to get authorization from user */
void KSaneAuth::authorization(SANE_String_Const resource, SANE_Char *username, SANE_Char *password)
{
kDebug() << resource;
// This is vague in the standard... what can I find in the resource string?
// I have found that "resource contains the backend name + "$MD5$....."
// it does not contain unique identifiers like ":libusb:001:004"
// -> remove $MD5 and later before comparison...
QString res(resource);
int end = res.indexOf("$MD5$");
res = res.left(end);
kDebug() << res;
QList<Private::AuthStruct> list = getInstance()->d->authList;
for (int i=0; i<list.size(); i++) {
kDebug() << res << list.at(i).resource;
if (list.at(i).resource.contains(res)) {
qstrncpy(username, list.at(i).username.toLocal8Bit(), SANE_MAX_USERNAME_LEN);
qstrncpy(password, list.at(i).password.toLocal8Bit(), SANE_MAX_PASSWORD_LEN);
break;
}
}
}
}

View file

@ -0,0 +1,63 @@
/* ============================================================
*
* This file is part of the KDE project
*
* Date : 2010
* Description : Sane authentication helpers.
*
* Copyright (C) 2010 by Kare Sars <kare dot sars at iki dot fi>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================ */
#ifndef KSANE_AUTH_H
#define KSANE_AUTH_H
// Qt includes
#include <QString>
// Sane includes
extern "C"
{
#include <sane/saneopts.h>
#include <sane/sane.h>
}
namespace KSaneIface
{
class KSaneAuth
{
public:
static KSaneAuth *getInstance();
~KSaneAuth();
void setDeviceAuth(const QString &resource, const QString &username, const QString &password);
void clearDeviceAuth(const QString &resource);
static void authorization(SANE_String_Const resource, SANE_Char *username, SANE_Char *password);
private:
KSaneAuth();
struct Private;
Private * const d;
};
}
#endif

View file

@ -0,0 +1,189 @@
/* ============================================================
*
* This file is part of the KDE project
*
* Date : 2007-09-13
* Description : Sane interface for KDE
*
* Copyright (C) 2007-2008 by Kare Sars <kare dot sars at iki dot fi>
* Copyright (C) 2009 by Grzegorz Kurtyka <grzegorz dot kurtyka at gmail dot com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================ */
// Local includes
#include "ksane_device_dialog.h"
#include "ksane_device_dialog.moc"
// Sane includes
extern "C"
{
#include <sane/saneopts.h>
#include <sane/sane.h>
}
// KDE includes
#include <KDebug>
#include <KPushButton>
#include <QScrollArea>
#include <QLabel>
namespace KSaneIface
{
KSaneDeviceDialog::KSaneDeviceDialog(QWidget *parent)
: KDialog(parent)
{
setButtons(KDialog::User1 | KDialog::Ok | KDialog::Cancel);
setButtonText(User1, i18n("Reload devices list"));
m_btnGroup = new QButtonGroup(this);
m_btnBox = new QGroupBox;
QVBoxLayout *layout = new QVBoxLayout;
m_btnContainer = new QWidget;
m_btnLayout = new QVBoxLayout(m_btnContainer);
QScrollArea *area = new QScrollArea;
m_btnBox->setLayout(layout);
QLabel *explanation =
new QLabel(i18n("<html>The SANE (Scanner Access Now Easy) system could not find any device.<br>"
"Check that the scanner is plugged in and turned on<br>"
"or check your systems scanner setup.<br>"
"For details about SANE see the "
"<a href='http://www.sane-project.org/'>SANE homepage</a>.</html>"));
explanation->setOpenExternalLinks(true);
int l,t,r,b;
layout->getContentsMargins(&l, &t, &r, &b);
explanation->setContentsMargins(l, t, r, b);
layout->addWidget(explanation);
m_btnBox->adjustSize(); // make sure to see the complete explanation text
layout->addWidget(area);
layout->setContentsMargins(0,0,0,0);
area->setWidgetResizable(true);
area->setFrameShape(QFrame::NoFrame);
area->setWidget(m_btnContainer);
setMainWidget(m_btnBox);
setMinimumHeight(200);
m_findDevThread = FindSaneDevicesThread::getInstance();
connect(m_findDevThread, SIGNAL(finished()), this, SLOT(updateDevicesList()));
connect(this, SIGNAL(user1Clicked()), this, SLOT(reloadDevicesList()));
reloadDevicesList();
}
KSaneDeviceDialog::~KSaneDeviceDialog() {
///@todo wait for thread to finish if its running
}
void KSaneDeviceDialog::reloadDevicesList()
{
setAvailable(false);
while (!m_btnGroup->buttons().isEmpty()) {
delete m_btnGroup->buttons().takeFirst();
}
m_btnBox->setTitle(i18n("Looking for devices. Please wait."));
m_btnBox->layout()->itemAt(0)->widget()->hide(); // explanation
enableButton(KDialog::User1, false);
if(!m_findDevThread->isRunning()) {
m_findDevThread->start();
}
}
void KSaneDeviceDialog::setAvailable(bool avail)
{
enableButtonOk(avail);
if(avail) {
m_selectedDevice = getSelectedName();
setButtonFocus(KDialog::Ok);
}
}
void KSaneDeviceDialog::setDefault(QString defaultBackend)
{
m_selectedDevice = defaultBackend;
}
QString KSaneDeviceDialog::getSelectedName() {
QAbstractButton *selectedButton = m_btnGroup->checkedButton();
if(selectedButton) {
return selectedButton->objectName();
}
return QString();
}
void KSaneDeviceDialog::updateDevicesList()
{
while (!m_btnGroup->buttons().isEmpty()) {
delete m_btnGroup->buttons().takeFirst();
}
const QList<KSaneWidget::DeviceInfo> list = m_findDevThread->devicesList();
if (list.isEmpty()) {
m_btnBox->setTitle(i18n("Sorry. No devices found."));
m_btnBox->layout()->itemAt(0)->widget()->show(); // explanation
m_btnBox->layout()->itemAt(1)->widget()->hide(); // scroll area
enableButton(KDialog::User1, true);
return;
}
delete m_btnLayout;
m_btnLayout = new QVBoxLayout;
m_btnContainer->setLayout(m_btnLayout);
m_btnBox->setTitle(i18n("Found devices:"));
m_btnBox->layout()->itemAt(0)->widget()->hide(); // explanation
m_btnBox->layout()->itemAt(1)->widget()->show(); // scroll area
for (int i=0; i< list.size(); i++) {
QRadioButton *b = new QRadioButton(this);
b->setObjectName(list[i].name);
b->setToolTip(list[i].name);
b->setText(QString("%1 : %2\n%3")
.arg(list[i].vendor)
.arg(list[i].model)
.arg(list[i].name));
m_btnLayout->addWidget(b);
m_btnGroup->addButton(b);
connect(b, SIGNAL(clicked(bool)), this, SLOT(setAvailable(bool)));
if((i==0) || (list[i].name == m_selectedDevice)) {
b->setChecked(true);
setAvailable(true);
}
}
m_btnLayout->addStretch();
if(list.size() == 1) {
button(KDialog::Ok)->animateClick();
}
enableButton(KDialog::User1, true);
}
} // NameSpace KSaneIface

View file

@ -0,0 +1,83 @@
/* ============================================================
*
* This file is part of the KDE project
*
* Date : 2007-09-13
* Description : Sane interface for KDE
*
* Copyright (C) 2007-2010 by Kare Sars <kare dot sars at iki dot fi>
* Copyright (C) 2009 by Grzegorz Kurtyka <grzegorz dot kurtyka at gmail dot com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================ */
#ifndef KSANE_DEVICE_DIALOG_H
#define KSANE_DEVICE_DIALOG_H
#include "ksane_find_devices_thread.h"
// Qt includes
#include <QGroupBox>
#include <QStringList>
#include <QButtonGroup>
#include <QToolTip>
#include <QRadioButton>
#include <QCheckBox>
#include <QPushButton>
#include <QBoxLayout>
// KDE includes
#include <KDialog>
#include <klocale.h>
namespace KSaneIface
{
class KSaneDeviceDialog : public KDialog
{
Q_OBJECT
public:
KSaneDeviceDialog(QWidget *parent=0);
~KSaneDeviceDialog();
QString getSelectedName();
void setDefault(QString);
public Q_SLOTS:
void reloadDevicesList();
private Q_SLOTS:
void setAvailable(bool avail);
void updateDevicesList();
private:
QWidget *m_btnContainer;
QGroupBox *m_btnBox;
QButtonGroup *m_btnGroup;
QVBoxLayout *m_btnLayout;
QString m_defaultBackend;
QString m_selectedDevice;
FindSaneDevicesThread *m_findDevThread;
};
} // NameSpace KSaneIface
#endif

View file

@ -0,0 +1,107 @@
/* ============================================================
*
* This file is part of the KDE project
*
* Date : 2007-09-13
* Description : Sane interface for KDE
*
* Copyright (C) 2009 by Grzegorz Kurtyka <grzegorz dot kurtyka at gmail dot com>
* Copyright (C) 2010 by Kare Sars <kare dot sars at iki dot fi>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================ */
#include "ksane_find_devices_thread.h"
#include "ksane_find_devices_thread.moc"
#include "ksane_widget_private.h"
// Sane includes
extern "C"
{
#include <sane/saneopts.h>
#include <sane/sane.h>
}
// KDE includes
#include <KDebug>
// Qt includes
#include <QMutex>
namespace KSaneIface
{
static FindSaneDevicesThread *s_instancesane = 0;
static QMutex s_mutexsane;
FindSaneDevicesThread *FindSaneDevicesThread::getInstance()
{
s_mutexsane.lock();
if (s_instancesane == 0) {
s_instancesane = new FindSaneDevicesThread();
}
s_mutexsane.unlock();
return s_instancesane;
}
FindSaneDevicesThread::FindSaneDevicesThread() : QThread(0)
{
}
FindSaneDevicesThread::~FindSaneDevicesThread()
{
s_mutexsane.lock();
wait();
s_mutexsane.unlock();
}
void FindSaneDevicesThread::run()
{
SANE_Device const **devList;
//SANE_Int version;
SANE_Status status;
// This is unfortunately not very reliable as many back-ends do not refresh
// the device list after the sane_init() call...
status = sane_get_devices(&devList, SANE_FALSE);
m_deviceList.clear();
if (status == SANE_STATUS_GOOD) {
int i = 0;
KSaneWidget::DeviceInfo tmp;
while(devList[i] != 0) {
tmp.name = devList[i]->name;
tmp.vendor = devList[i]->vendor;
tmp.model = devList[i]->model;
tmp.type = devList[i]->type;
m_deviceList << tmp;
i++;
}
}
}
const QList<KSaneWidget::DeviceInfo> FindSaneDevicesThread::devicesList() const
{
return m_deviceList;
}
}

View file

@ -0,0 +1,57 @@
/* ============================================================
*
* This file is part of the KDE project
*
* Date : 2007-09-13
* Description : Sane interface for KDE
*
* Copyright (C) 2007-2008 by Kare Sars <kare dot sars at iki dot fi>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================ */
#ifndef KSANE_FIND_DEVICES_THREAD_H
#define KSANE_FIND_DEVICES_THREAD_H
#include "ksane.h"
#include <QThread>
#include <QList>
namespace KSaneIface
{
class FindSaneDevicesThread : public QThread {
Q_OBJECT
public:
static FindSaneDevicesThread *getInstance();
~FindSaneDevicesThread();
void run();
const QList<KSaneWidget::DeviceInfo> devicesList() const;
private:
FindSaneDevicesThread();
QList<KSaneWidget::DeviceInfo> m_deviceList;
};
}
#endif

View file

@ -0,0 +1,472 @@
/* ============================================================
*
* This file is part of the KDE project
*
* Date : 2009-11-13
* Description : Sane interface for KDE
*
* Copyright (C) 2009 by Kare Sars <kare dot sars at iki dot fi>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================ */
// Local includes
#include "ksane_preview_thread.moc"
#include <KDebug>
#include <QMutexLocker>
namespace KSaneIface
{
KSanePreviewThread::KSanePreviewThread(SANE_Handle handle, QImage *img):
QThread(),
status(SANE_STATUS_GOOD),
m_frameSize(0),
m_frameRead(0),
m_dataSize(0),
m_frame_t_count(0),
m_pixel_x(0),
m_pixel_y(0),
m_px_c_index(0),
m_img(img),
m_saneHandle(handle),
m_invertColors(false),
m_readStatus(READ_READY),
// m_scanProgress(0),
m_saneStartDone(false),
m_imageResized(false)
{
m_px_colors[0] = 0;
m_px_colors[1] = 0;
m_px_colors[2] = 0;
}
void KSanePreviewThread::setPreviewInverted(bool inverted)
{
m_invertColors = inverted;
}
void KSanePreviewThread::cancelScan()
{
m_readStatus = READ_CANCEL;
}
void KSanePreviewThread::run()
{
m_dataSize = 0;
m_readStatus = READ_ON_GOING;
m_saneStartDone = false;
// Start the scanning with sane_start
status = sane_start(m_saneHandle);
if (status != SANE_STATUS_GOOD) {
kDebug() << "sane_start=" << sane_strstatus(status);
sane_cancel(m_saneHandle);
m_readStatus = READ_ERROR;
return;
}
// Read image parameters
status = sane_get_parameters(m_saneHandle, &m_params);
if (status != SANE_STATUS_GOOD) {
kDebug() << "sane_get_parameters=" << sane_strstatus(status);
sane_cancel(m_saneHandle);
m_readStatus = READ_ERROR;
return;
}
// calculate data size
m_frameSize = m_params.lines * m_params.bytes_per_line;
if ((m_params.format == SANE_FRAME_RED) ||
(m_params.format == SANE_FRAME_GREEN) ||
(m_params.format == SANE_FRAME_BLUE))
{
// this is unfortunately calculated again for every frame....
m_dataSize = m_frameSize*3;
}
else {
m_dataSize = m_frameSize;
}
// create a new image if necessary
if ((m_img->height() != m_params.lines) ||
(m_img->width() != m_params.pixels_per_line))
{
// just hope that the frame size is not changed between different frames of the same image.
if (m_params.lines > 0) {
*m_img = QImage(m_params.pixels_per_line, m_params.lines, QImage::Format_RGB32);
}
else {
// handscanners have the number of lines -1 -> make room for something
*m_img = QImage(m_params.pixels_per_line, m_params.pixels_per_line, QImage::Format_RGB32);
}
m_img->fill(0xFFFFFFFF);
}
m_imageResized = false;
m_pixel_x = 0;
m_pixel_y = 0;
m_frameRead = 0;
m_px_c_index = 0;
m_frame_t_count = 0;
// set the m_saneStartDone here so the new QImage gets allocated before updating the preview.
m_saneStartDone = true;
while (m_readStatus == READ_ON_GOING) {
readData();
}
}
int KSanePreviewThread::scanProgress()
{
// handscanners have negative data size
if (m_dataSize <= 0) return 0;
int bytesRead;
if (m_frameSize < m_dataSize) {
bytesRead = m_frameRead + (m_frameSize * m_frame_t_count);
}
else {
bytesRead = m_frameRead;
}
return (int)(((float)bytesRead * 100.0)/m_dataSize);
}
void KSanePreviewThread::readData()
{
SANE_Int readBytes;
status = sane_read(m_saneHandle, m_readData, PREVIEW_READ_CHUNK_SIZE, &readBytes);
switch (status)
{
case SANE_STATUS_GOOD:
// continue to parsing the data
break;
case SANE_STATUS_EOF:
// (handscanners have negative frame size)
if (m_frameRead < m_frameSize) {
kDebug() << "frameRead =" << m_frameRead << ", frameSize =" << m_frameSize;
m_readStatus = READ_ERROR;
return;
}
if (m_params.last_frame == SANE_TRUE) {
// this is where it all ends well :)
m_readStatus = READ_READY;
return;
}
else {
// start reading next frame
SANE_Status status = sane_start(m_saneHandle);
if (status != SANE_STATUS_GOOD) {
kDebug() << "sane_start =" << sane_strstatus(status);
m_readStatus = READ_ERROR;
return;
}
status = sane_get_parameters(m_saneHandle, &m_params);
if (status != SANE_STATUS_GOOD) {
kDebug() << "sane_get_parameters =" << sane_strstatus(status);
m_readStatus = READ_ERROR;
sane_cancel(m_saneHandle);
return;
}
//kDebug() << "New Frame";
m_frameRead = 0;
m_pixel_x = 0;
m_pixel_y = 0;
m_px_c_index = 0;
m_frame_t_count++;
break;
}
default:
kDebug() << "sane_read=" << status << "=" << sane_strstatus(status);
m_readStatus = READ_ERROR;
sane_cancel(m_saneHandle);
return;
}
copyToPreviewImg(readBytes);
}
#define inc_pixel(x,y,ppl) { x++; if (x>=ppl) { y++; x=0;} }
#define inc_color_index(index) { index++; if (index==3) index=0;}
#define index_red8_to_argb8(i) (i*4 + 2)
#define index_red16_to_argb8(i) (i*2 + 2)
#define index_green8_to_argb8(i) (i*4 + 1)
#define index_green16_to_argb8(i) (i*2 + 1)
#define index_blue8_to_argb8(i) (i*4)
#define index_blue16_to_argb8(i) (i*2)
void KSanePreviewThread::copyToPreviewImg(int read_bytes)
{
QMutexLocker locker(&imgMutex);
int index;
uchar *imgBits = m_img->bits();
if (m_invertColors) {
if (m_params.depth >= 8) {
for(int i=0; i<read_bytes; i++) {
m_readData[i] = 255 - m_readData[i];
}
}
if (m_params.depth == 1) {
for(int i=0; i<read_bytes; i++) {
m_readData[i] = ~m_readData[i];
}
}
}
switch (m_params.format)
{
case SANE_FRAME_GRAY:
if (m_params.depth == 1) {
int i, j;
for (i=0; i<read_bytes; i++) {
if (m_pixel_y >= m_img->height()) {
// resize the image
*m_img = m_img->copy(0, 0, m_img->width(), m_img->height() + m_img->width());
m_imageResized = true;
}
for (j=7; j>=0; --j) {
if ((m_readData[i] & (1<<j)) == 0) {
m_img->setPixel(m_pixel_x,
m_pixel_y,
qRgb(255,255,255));
}
else {
m_img->setPixel(m_pixel_x,
m_pixel_y,
qRgb(0,0,0));
}
m_pixel_x++;
if(m_pixel_x >= m_params.pixels_per_line) {
m_pixel_x = 0;
m_pixel_y++;
break;
}
if (m_pixel_y >= m_params.lines) break;
}
m_frameRead++;
}
return;
}
else if (m_params.depth == 8) {
for (int i=0; i<read_bytes; i++) {
index = m_frameRead * 4;
if ((index + 2) >m_img->numBytes()) {
// resize the image
*m_img = m_img->copy(0, 0, m_img->width(), m_img->height() + m_img->width());
imgBits = m_img->bits();
m_imageResized = true;
}
imgBits[index ] = m_readData[i];
imgBits[index + 1] = m_readData[i];
imgBits[index + 2] = m_readData[i];
m_frameRead++;
}
return;
}
else if (m_params.depth == 16) {
for (int i=0; i<read_bytes; i++) {
if (m_frameRead%2 == 0) {
index = m_frameRead * 2;
if ((index + 2) > m_img->numBytes()) {
// resize the image
*m_img = m_img->copy(0, 0, m_img->width(), m_img->height() + m_img->width());
imgBits = m_img->bits();
m_imageResized = true;
}
imgBits[index ] = m_readData[i+1];
imgBits[index + 1] = m_readData[i+1];
imgBits[index + 2] = m_readData[i+1];
}
m_frameRead++;
}
return;
}
break;
case SANE_FRAME_RGB:
if (m_params.depth == 8) {
for (int i=0; i<read_bytes; i++) {
m_px_colors[m_px_c_index] = m_readData[i];
inc_color_index(m_px_c_index);
m_frameRead++;
if (m_px_c_index == 0) {
if (m_pixel_y >= m_img->height()) {
// resize the image
*m_img = m_img->copy(0, 0, m_img->width(), m_img->height() + m_img->width());
m_imageResized = true;
}
m_img->setPixel(m_pixel_x,
m_pixel_y,
qRgb(m_px_colors[0],
m_px_colors[1],
m_px_colors[2]));
inc_pixel(m_pixel_x, m_pixel_y, m_params.pixels_per_line);
}
}
return;
}
else if (m_params.depth == 16) {
for (int i=0; i<read_bytes; i++) {
m_frameRead++;
if (m_frameRead%2==0) {
m_px_colors[m_px_c_index] = m_readData[i];
inc_color_index(m_px_c_index);
if (m_px_c_index == 0) {
if (m_pixel_y >= m_img->height()) {
// resize the image
*m_img = m_img->copy(0, 0, m_img->width(), m_img->height() + m_img->width());
m_imageResized = true;
}
m_img->setPixel(m_pixel_x,
m_pixel_y,
qRgb(m_px_colors[0],
m_px_colors[1],
m_px_colors[2]));
inc_pixel(m_pixel_x, m_pixel_y, m_params.pixels_per_line);
}
}
}
return;
}
break;
case SANE_FRAME_RED:
if (m_params.depth == 8) {
for (int i=0; i<read_bytes; i++) {
if (index_red8_to_argb8(m_frameRead) > m_img->numBytes()) {
// resize the image
*m_img = m_img->copy(0, 0, m_img->width(), m_img->height() + m_img->width());
imgBits = m_img->bits();
m_imageResized = true;
}
imgBits[index_red8_to_argb8(m_frameRead)] = m_readData[i];
m_frameRead++;
}
return;
}
else if (m_params.depth == 16) {
for (int i=0; i<read_bytes; i++) {
if (m_frameRead%2 == 0) {
if (index_red16_to_argb8(m_frameRead) > m_img->numBytes()) {
// resize the image
*m_img = m_img->copy(0, 0, m_img->width(), m_img->height() + m_img->width());
imgBits = m_img->bits();
m_imageResized = true;
}
imgBits[index_red16_to_argb8(m_frameRead)] = m_readData[i+1];
}
m_frameRead++;
}
return;
}
break;
case SANE_FRAME_GREEN:
if (m_params.depth == 8) {
for (int i=0; i<read_bytes; i++) {
if (index_green8_to_argb8(m_frameRead) > m_img->numBytes()) {
// resize the image
*m_img = m_img->copy(0, 0, m_img->width(), m_img->height() + m_img->width());
imgBits = m_img->bits();
m_imageResized = true;
}
imgBits[index_green8_to_argb8(m_frameRead)] = m_readData[i];
m_frameRead++;
}
return;
}
else if (m_params.depth == 16) {
for (int i=0; i<read_bytes; i++) {
if (m_frameRead%2 == 0) {
if (index_green16_to_argb8(m_frameRead) > m_img->numBytes()) {
// resize the image
*m_img = m_img->copy(0, 0, m_img->width(), m_img->height() + m_img->width());
imgBits = m_img->bits();
m_imageResized = true;
}
imgBits[index_green16_to_argb8(m_frameRead)] = m_readData[i+1];
}
m_frameRead++;
}
return;
}
break;
case SANE_FRAME_BLUE:
if (m_params.depth == 8) {
for (int i=0; i<read_bytes; i++) {
if (index_blue8_to_argb8(m_frameRead) > m_img->numBytes()) {
// resize the image
*m_img = m_img->copy(0, 0, m_img->width(), m_img->height() + m_img->width());
imgBits = m_img->bits();
m_imageResized = true;
}
imgBits[index_blue8_to_argb8(m_frameRead)] = m_readData[i];
m_frameRead++;
}
return;
}
else if (m_params.depth == 16) {
for (int i=0; i<read_bytes; i++) {
if (m_frameRead%2 == 0) {
if (index_blue16_to_argb8(m_frameRead) > m_img->numBytes()) {
// resize the image
*m_img = m_img->copy(0, 0, m_img->width(), m_img->height() + m_img->width());
imgBits = m_img->bits();
m_imageResized = true;
}
imgBits[index_blue16_to_argb8(m_frameRead)] = m_readData[i+1];
}
m_frameRead++;
}
return;
}
break;
}
kWarning() << "Format" << m_params.format
<< "and depth" << m_params.format
<< "is not yet suppoeted by libksane!";
m_readStatus = READ_ERROR;
return;
}
bool KSanePreviewThread::saneStartDone()
{
return m_saneStartDone;
}
bool KSanePreviewThread::imageResized()
{
if (m_imageResized) {
m_imageResized = false;
return true;
}
return false;
}
} // NameSpace KSaneIface

View file

@ -0,0 +1,94 @@
/* ============================================================
*
* This file is part of the KDE project
*
* Date : 2009-11-13
* Description : Sane interface for KDE
*
* Copyright (C) 2009 by Kare Sars <kare dot sars at iki dot fi>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================ */
#ifndef KSANE_PREVIEW_THREAD_H
#define KSANE_PREVIEW_THREAD_H
// Sane includes
extern "C"
{
#include <sane/saneopts.h>
#include <sane/sane.h>
}
#include <QThread>
#include <QMutex>
#include <QImage>
#define PREVIEW_READ_CHUNK_SIZE 100000
namespace KSaneIface
{
class KSanePreviewThread: public QThread
{
Q_OBJECT
public:
typedef enum
{
READ_ON_GOING,
READ_ERROR,
READ_CANCEL,
READ_READY
} ReadStatus;
KSanePreviewThread(SANE_Handle handle, QImage *img);
void run();
void setPreviewInverted(bool);
void cancelScan();
int scanProgress();
bool saneStartDone();
bool imageResized();
SANE_Status status;
QMutex imgMutex;
private:
void readData();
void copyToPreviewImg(int readBytes);
SANE_Byte m_readData[PREVIEW_READ_CHUNK_SIZE];
int m_frameSize;
int m_frameRead;
int m_dataSize;
int m_frame_t_count;
int m_pixel_x;
int m_pixel_y;
int m_px_colors[3];
int m_px_c_index;
SANE_Parameters m_params;
QImage *m_img;
SANE_Handle m_saneHandle;
bool m_invertColors;
ReadStatus m_readStatus;
// int m_scanProgress;
bool m_saneStartDone;
bool m_imageResized;
};
}
#endif

View file

@ -0,0 +1,311 @@
/* ============================================================
*
* This file is part of the KDE project
*
* Date : 2009-11-13
* Description : Sane interface for KDE
*
* Copyright (C) 2009 by Kare Sars <kare dot sars at iki dot fi>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================ */
// Local includes
#include "ksane_scan_thread.moc"
#include <KDebug>
namespace KSaneIface
{
KSaneScanThread::KSaneScanThread(SANE_Handle handle, QByteArray *data):
QThread(),
m_data(data),
m_saneHandle(handle),
m_frameSize(0),
m_frameRead(0),
m_frame_t_count(0),
m_dataSize(0),
m_saneStatus(SANE_STATUS_GOOD),
m_readStatus(READ_READY),
m_invertColors(false),
m_saneStartDone(false)
{}
void KSaneScanThread::setImageInverted(bool inverted)
{
m_invertColors = inverted;
}
SANE_Status KSaneScanThread::saneStatus()
{
return m_saneStatus;
}
KSaneScanThread::ReadStatus KSaneScanThread::frameStatus()
{
return m_readStatus;
}
void KSaneScanThread::cancelScan()
{
m_readStatus = READ_CANCEL;
}
int KSaneScanThread::scanProgress()
{
if (m_dataSize == 0) return 0;
int bytesRead;
if (m_frameSize < m_dataSize) {
bytesRead = m_frameRead + (m_frameSize * m_frame_t_count);
}
else {
bytesRead = m_frameRead;
}
return (int)(((float)bytesRead * 100.0)/m_dataSize);
}
SANE_Parameters KSaneScanThread::saneParameters()
{
return m_params;
}
void KSaneScanThread::run()
{
m_dataSize = 0;
m_readStatus = READ_ON_GOING;
m_saneStartDone = false;
// Start the scanning with sane_start
m_saneStatus = sane_start(m_saneHandle);
m_saneStartDone = true;
if (m_readStatus == READ_CANCEL) {
return;
}
if (m_saneStatus != SANE_STATUS_GOOD) {
kDebug() << "sane_start=" << sane_strstatus(m_saneStatus);
m_readStatus = READ_ERROR;
// oneFinalScanDone() does the sane_cancel()
return;
}
// Read image parameters
m_saneStatus = sane_get_parameters(m_saneHandle, &m_params);
if (m_saneStatus != SANE_STATUS_GOOD) {
kDebug() << "sane_get_parameters=" << sane_strstatus(m_saneStatus);
m_readStatus = READ_ERROR;
// oneFinalScanDone() does the sane_cancel()
return;
}
// calculate data size
m_frameSize = m_params.lines * m_params.bytes_per_line;
if ((m_params.format == SANE_FRAME_RED) ||
(m_params.format == SANE_FRAME_GREEN) ||
(m_params.format == SANE_FRAME_BLUE))
{
m_dataSize = m_frameSize*3;
}
else {
m_dataSize = m_frameSize;
}
m_data->clear();
if (m_dataSize > 0) {
m_data->reserve(m_dataSize);
}
m_frameRead = 0;
m_frame_t_count = 0;
m_readStatus = READ_ON_GOING;
while (m_readStatus == READ_ON_GOING) {
readData();
}
}
void KSaneScanThread::readData()
{
SANE_Int readBytes = 0;
m_saneStatus = sane_read(m_saneHandle, m_readData, SCAN_READ_CHUNK_SIZE, &readBytes);
switch (m_saneStatus)
{
case SANE_STATUS_GOOD:
// continue to parsing the data
break;
case SANE_STATUS_EOF:
if (m_frameRead < m_frameSize) {
kDebug() << "frameRead =" << m_frameRead << ", frameSize =" << m_frameSize << "readBytes =" << readBytes;
if ((readBytes > 0) && ((m_frameRead + readBytes) <= m_frameSize)) {
kDebug() << "This is not a standard compliant backend";
copyToScanData(readBytes);
}
m_readStatus = READ_READY; // It is better to return a broken image than nothing
return;
}
if (m_params.last_frame == SANE_TRUE) {
// this is where it all ends well :)
m_readStatus = READ_READY;
return;
}
else {
// start reading next frame
m_saneStatus = sane_start(m_saneHandle);
if (m_saneStatus != SANE_STATUS_GOOD) {
kDebug() << "sane_start =" << sane_strstatus(m_saneStatus);
m_readStatus = READ_ERROR;
return;
}
m_saneStatus = sane_get_parameters(m_saneHandle, &m_params);
if (m_saneStatus != SANE_STATUS_GOOD) {
kDebug() << "sane_get_parameters =" << sane_strstatus(m_saneStatus);
m_readStatus = READ_ERROR;
sane_cancel(m_saneHandle);
return;
}
//kDebug() << "New Frame";
m_frameRead = 0;
m_frame_t_count++;
break;
}
default:
kDebug() << "sane_read=" << m_saneStatus << "=" << sane_strstatus(m_saneStatus);
m_readStatus = READ_ERROR;
sane_cancel(m_saneHandle);
return;
}
copyToScanData(readBytes);
}
#define index_red8_to_rgb8(i) (i*3)
#define index_red16_to_rgb16(i) ((i/2)*6 + i%2)
#define index_green8_to_rgb8(i) (i*3 + 1)
#define index_green16_to_rgb16(i) ((i/2)*6 + i%2 + 2)
#define index_blue8_to_rgb8(i) (i*3 + 2)
#define index_blue16_to_rgb16(i) ((i/2)*6 + i%2 + 4)
void KSaneScanThread::copyToScanData(int readBytes)
{
if (m_invertColors) {
if (m_params.depth == 16) {
//if (readBytes%2) qDebug() << "readBytes=" << readBytes;
quint16 *u16ptr = reinterpret_cast<quint16*>(m_readData);
for(int i=0; i<readBytes/2; i++) {
u16ptr[i] = 0xFFFF - u16ptr[i];
}
}
else if (m_params.depth == 8) {
for(int i=0; i<readBytes; i++) {
m_readData[i] = 0xFF - m_readData[i];
}
}
else if (m_params.depth == 1) {
for(int i=0; i<readBytes; i++) {
m_readData[i] = ~m_readData[i];
}
}
}
switch (m_params.format)
{
case SANE_FRAME_GRAY:
m_data->append((const char*)m_readData, readBytes);
m_frameRead += readBytes;
return;
case SANE_FRAME_RGB:
if (m_params.depth == 1) {
break;
}
m_data->append((const char*)m_readData, readBytes);
m_frameRead += readBytes;
return;
case SANE_FRAME_RED:
if (m_params.depth == 8) {
for (int i=0; i<readBytes; i++) {
(*m_data)[index_red8_to_rgb8(m_frameRead)] = m_readData[i];
m_frameRead++;
}
return;
}
else if (m_params.depth == 16) {
for (int i=0; i<readBytes; i++) {
(*m_data)[index_red16_to_rgb16(m_frameRead)] = m_readData[i];
m_frameRead++;
}
return;
}
break;
case SANE_FRAME_GREEN:
if (m_params.depth == 8) {
for (int i=0; i<readBytes; i++) {
(*m_data)[index_green8_to_rgb8(m_frameRead)] = m_readData[i];
m_frameRead++;
}
return;
}
else if (m_params.depth == 16) {
for (int i=0; i<readBytes; i++) {
(*m_data)[index_green16_to_rgb16(m_frameRead)] = m_readData[i];
m_frameRead++;
}
return;
}
break;
case SANE_FRAME_BLUE:
if (m_params.depth == 8) {
for (int i=0; i<readBytes; i++) {
(*m_data)[index_blue8_to_rgb8(m_frameRead)] = m_readData[i];
m_frameRead++;
}
return;
}
else if (m_params.depth == 16) {
for (int i=0; i<readBytes; i++) {
(*m_data)[index_blue16_to_rgb16(m_frameRead)] = m_readData[i];
m_frameRead++;
}
return;
}
break;
}
kDebug() << "Format" << m_params.format
<< "and depth" << m_params.format
<< "is not yet suppoeted by libksane!";
m_readStatus = READ_ERROR;
return;
}
bool KSaneScanThread::saneStartDone()
{
return m_saneStartDone;
}
} // NameSpace KSaneIface

View file

@ -0,0 +1,88 @@
/* ============================================================
*
* This file is part of the KDE project
*
* Date : 2009-11-13
* Description : Sane interface for KDE
*
* Copyright (C) 2009 by Kare Sars <kare dot sars at iki dot fi>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================ */
#ifndef KSANE_SCAN_THREAD_H
#define KSANE_SCAN_THREAD_H
// Sane includes
extern "C"
{
#include <sane/saneopts.h>
#include <sane/sane.h>
}
#include <QThread>
#include <QByteArray>
#define SCAN_READ_CHUNK_SIZE 100000
namespace KSaneIface
{
class KSaneScanThread: public QThread
{
Q_OBJECT
public:
typedef enum
{
READ_ON_GOING,
READ_ERROR,
READ_CANCEL,
READ_READY
} ReadStatus;
KSaneScanThread(SANE_Handle handle, QByteArray *data);
void run();
void setImageInverted(bool);
void cancelScan();
int scanProgress();
bool saneStartDone();
ReadStatus frameStatus();
SANE_Status saneStatus();
SANE_Parameters saneParameters();
private:
void readData();
void copyToScanData(int readBytes);
SANE_Byte m_readData[SCAN_READ_CHUNK_SIZE];
QByteArray *m_data;
SANE_Handle m_saneHandle;
SANE_Parameters m_params;
int m_frameSize;
int m_frameRead;
int m_frame_t_count;
int m_dataSize;
SANE_Status m_saneStatus;
ReadStatus m_readStatus;
bool m_invertColors;
bool m_saneStartDone;
};
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,128 @@
/* ============================================================
*
* This file is part of the KDE project
*
* Date : 2008-11-15
* Description : Preview image viewer that can handle a selection.
*
* Copyright (C) 2008 by Kare Sars <kare dot sars at iki dot fi>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================ */
#ifndef KSANE_VIEWER_H
#define KSANE_VIEWER_H
#include <QGraphicsView>
#include <QWheelEvent>
namespace KSaneIface
{
class KSaneViewer : public QGraphicsView
{
Q_OBJECT
public:
explicit KSaneViewer(QImage *img, QWidget *parent = 0);
~KSaneViewer();
void setQImage(QImage *img);
void updateImage();
/** Find selections in the picture
* \param area this parameter determine the area of the reduced sized image. */
void findSelections(float area = 10000.0);
virtual QSize sizeHint() const;
public Q_SLOTS:
void setTLX(float ratio);
void setTLY(float ratio);
void setBRX(float ratio);
void setBRY(float ratio);
/** This function is used to set a selection without the user setting it.
* \note all parameters must be in the range 0.0 -> 1.0.
* \param tl_x is the x coordinate of the top left corner 0=0 1=image with.
* \param tl_y is the y coordinate of the top left corner 0=0 1=image height.
* \param br_x is the x coordinate of the bottom right corner 0=0 1=image with.
* \param br_y is the y coordinate of the bottom right corner 0=0 1=image height. */
void setSelection(float tl_x, float tl_y, float br_x, float br_y);
void clearActiveSelection();
void clearSavedSelections();
void clearSelections();
/** This function is used to darken everything except what is inside the given area.
* \note all parameters must be in the range 0.0 -> 1.0.
* \param tl_x is the x coordinate of the top left corner 0=0 1=image with.
* \param tl_y is the y coordinate of the top left corner 0=0 1=image height.
* \param br_x is the x coordinate of the bottom right corner 0=0 1=image with.
* \param br_y is the y coordinate of the bottom right corner 0=0 1=image height. */
void setHighlightArea(float tl_x, float tl_y, float br_x, float br_y);
/** This function sets the percentage of the highlighted area that is visible. The rest is hidden.
* \param percentage is the percentage of the highlighted area that is shown.
* \param hideColor is the color to use to hide the highlighted area of the image.*/
void setHighlightShown(int percentage, QColor hideColor = Qt::white);
/** This function removes the highlight area. */
void clearHighlight();
void zoomIn();
void zoomOut();
void zoomSel();
void zoom2Fit();
int selListSize();
/* This function returns the active visible selection in index 0 and after that the "saved" ones */
bool selectionAt(int index, float &tl_x, float &tl_y, float &br_x, float &br_y);
Q_SIGNALS:
void newSelection(float tl_x, float tl_y, float br_x, float br_y);
protected:
void wheelEvent(QWheelEvent *e);
void mousePressEvent(QMouseEvent *e);
void mouseReleaseEvent(QMouseEvent *e);
void mouseMoveEvent(QMouseEvent *e);
void drawBackground(QPainter *painter, const QRectF &rect);
private:
void updateSelVisibility();
void updateHighlight();
bool activeSelection(float &tl_x, float &tl_y, float &br_x, float &br_y);
void refineSelections(int pixelMargin);
// fromRow is the row to start the iterations from. fromRow can be grater than toRow.
// rowStart is the x1 coordinate of the row
// all parameters are corrected to be valid pixel indexes,
// but start must be < end
int refineRow(int fromRow, int toRow, int rowStart, int rowEnd);
int refineColumn(int fromCol, int toCol, int colStart, int colEnd);
struct Private;
Private * const d;
};
} // NameSpace KSaneIface
#endif

View file

@ -0,0 +1,52 @@
/* ============================================================
*
* This file is part of the KDE project
*
* Date : 2010-03-17
* Description : Preview image viewer that can handle a selection.
*
* Copyright (C) 2010 by Kare Sars <kare dot sars at iki dot fi>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================ */
#include "ksane_viewer.h"
#include <KDebug>
#include <QApplication>
int main (int argc, char *argv[])
{
QApplication app(argc, argv);
if (argc != 2) {
kDebug() << "An image filename is needed.";
return 1;
}
QImage img(argv[1]);
KSaneIface::KSaneViewer viewer(&img);
viewer.findSelections();
viewer.show();
viewer.zoom2Fit();
return app.exec();
}

View file

@ -0,0 +1,931 @@
/* ============================================================
*
* This file is part of the KDE project
*
* Date : 2009-01-24
* Description : Sane interface for KDE
*
* Copyright (C) 2007-2010 by Kare Sars <kare dot sars at iki dot fi>
* Copyright (C) 2009 by Matthias Nagl <matthias at nagl dot info>
* Copyright (C) 2009 by Grzegorz Kurtyka <grzegorz dot kurtyka at gmail dot com>
* Copyright (C) 2007-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================ */
#include "ksane.h"
#include "ksane.moc"
#include <unistd.h>
// Qt includes
#include <QApplication>
#include <QVarLengthArray>
#include <QLabel>
#include <QSplitter>
#include <QMutex>
#include <QPointer>
// KDE includes
#include <kpassworddialog.h>
#include <kwallet.h>
#include <kpushbutton.h>
// Local includes
#include "ksane_widget_private.h"
#include "ksane_option.h"
#include "ksane_opt_button.h"
#include "ksane_opt_checkbox.h"
#include "ksane_opt_combo.h"
#include "ksane_opt_entry.h"
#include "ksane_opt_fslider.h"
#include "ksane_opt_gamma.h"
#include "ksane_opt_slider.h"
#include "ksane_device_dialog.h"
#include "labeled_gamma.h"
namespace KSaneIface
{
static int s_objectCount = 0;
static QMutex s_objectMutex;
static const QString InvetColorsOption = QString("KSane::InvertColors");
KSaneWidget::KSaneWidget(QWidget* parent)
: QWidget(parent), d(new KSaneWidgetPrivate(this))
{
SANE_Int version;
SANE_Status status;
//kDebug() << "The language is:" << KGlobal::locale()->language();
//kDebug() << "Languagelist" << KGlobal::locale()->languageList();
KGlobal::locale()->insertCatalog("libksane");
KGlobal::locale()->insertCatalog("sane-backends");
s_objectMutex.lock();
s_objectCount++;
if (s_objectCount == 1) {
// only call sane init for the first instance
status = sane_init(&version, &KSaneAuth::authorization);
if (status != SANE_STATUS_GOOD) {
kDebug() << "libksane: sane_init() failed("
<< sane_strstatus(status) << ")";
}
else {
//kDebug() << "Sane Version = "
// << SANE_VERSION_MAJOR(version) << "."
// << SANE_VERSION_MINORparent(version) << "."
// << SANE_VERSION_BUILD(version);
}
}
s_objectMutex.unlock();
// read the device list to get a list of vendor and model info
d->m_findDevThread->start();
d->m_readValsTmr.setSingleShot(true);
connect(&d->m_readValsTmr, SIGNAL(timeout()), d, SLOT(valReload()));
d->m_updProgressTmr.setSingleShot(false);
d->m_updProgressTmr.setInterval(300);
connect(&d->m_updProgressTmr, SIGNAL(timeout()), d, SLOT(updateProgress()));
// Create the static UI
// create the preview
d->m_previewViewer = new KSaneViewer(&(d->m_previewImg), this);
connect(d->m_previewViewer, SIGNAL(newSelection(float,float,float,float)),
d, SLOT(handleSelection(float,float,float,float)));
d->m_warmingUp = new QLabel;
d->m_warmingUp->setText(i18n("Waiting for the scan to start."));
d->m_warmingUp->setAlignment(Qt::AlignCenter);
d->m_warmingUp->setAutoFillBackground(true);
d->m_warmingUp->setBackgroundRole(QPalette::Highlight);
//d->m_warmingUp->setForegroundRole(QPalette::HighlightedText);
d->m_warmingUp->hide();
d->m_progressBar = new QProgressBar;
d->m_progressBar->setMaximum(100);
d->m_cancelBtn = new KPushButton;
d->m_cancelBtn->setIcon(KIcon("process-stop"));
d->m_cancelBtn->setToolTip(i18n("Cancel current scan operation"));
connect(d->m_cancelBtn, SIGNAL(clicked()), this, SLOT(scanCancel()));
d->m_activityFrame = new QWidget;
QHBoxLayout *progress_lay = new QHBoxLayout(d->m_activityFrame);
progress_lay->setContentsMargins(0,0,0,0);
progress_lay->addWidget(d->m_progressBar, 100);
progress_lay->addWidget(d->m_cancelBtn, 0);
d->m_activityFrame->hide();
d->m_zInBtn = new QToolButton(this);
d->m_zInBtn->setAutoRaise(true);
d->m_zInBtn->setIcon(KIcon("zoom-in"));
d->m_zInBtn->setToolTip(i18n("Zoom In"));
connect(d->m_zInBtn, SIGNAL(clicked()), d->m_previewViewer, SLOT(zoomIn()));
d->m_zOutBtn = new QToolButton(this);
d->m_zOutBtn->setAutoRaise(true);
d->m_zOutBtn->setIcon(KIcon("zoom-out"));
d->m_zOutBtn->setToolTip(i18n("Zoom Out"));
connect(d->m_zOutBtn, SIGNAL(clicked()), d->m_previewViewer, SLOT(zoomOut()));
d->m_zSelBtn = new QToolButton(this);
d->m_zSelBtn->setAutoRaise(true);
d->m_zSelBtn->setIcon(KIcon("zoom-fit-best"));
d->m_zSelBtn->setToolTip(i18n("Zoom to Selection"));
connect(d->m_zSelBtn, SIGNAL(clicked()), d->m_previewViewer, SLOT(zoomSel()));
d->m_zFitBtn = new QToolButton(this);
d->m_zFitBtn->setAutoRaise(true);
d->m_zFitBtn->setIcon(KIcon("document-preview"));
d->m_zFitBtn->setToolTip(i18n("Zoom to Fit"));
connect(d->m_zFitBtn, SIGNAL(clicked()), d->m_previewViewer, SLOT(zoom2Fit()));
d->m_clearSelBtn = new QToolButton(this);
d->m_clearSelBtn->setAutoRaise(true);
d->m_clearSelBtn->setIcon(KIcon("edit-clear"));
d->m_clearSelBtn->setToolTip(i18n("Clear Selections"));
connect(d->m_clearSelBtn, SIGNAL(clicked()), d->m_previewViewer, SLOT(clearSelections()));
d->m_prevBtn = new KPushButton(this);
d->m_prevBtn->setIcon(KIcon("document-import"));
d->m_prevBtn->setToolTip(i18n("Scan Preview Image"));
d->m_prevBtn->setText(i18nc("Preview button text", "Preview"));
connect(d->m_prevBtn, SIGNAL(clicked()), d, SLOT(startPreviewScan()));
d->m_scanBtn = new KPushButton(this);
d->m_scanBtn->setIcon(KIcon("document-save"));
d->m_scanBtn->setToolTip(i18n("Scan Final Image"));
d->m_scanBtn->setText(i18nc("Final scan button text", "Scan"));
d->m_scanBtn->setFocus(Qt::OtherFocusReason);
connect(d->m_scanBtn, SIGNAL(clicked()), d, SLOT(startFinalScan()));
d->m_btnFrame = new QWidget;
QHBoxLayout *btn_lay = new QHBoxLayout(d->m_btnFrame);
btn_lay->setContentsMargins(0,0,0,0);
btn_lay->addWidget(d->m_zInBtn);
btn_lay->addWidget(d->m_zOutBtn);
btn_lay->addWidget(d->m_zSelBtn);
btn_lay->addWidget(d->m_zFitBtn);
btn_lay->addWidget(d->m_clearSelBtn);
btn_lay->addStretch(100);
btn_lay->addWidget(d->m_prevBtn);
btn_lay->addWidget(d->m_scanBtn);
// calculate the height of the waiting/scanning/buttons frames to avoid jumpiness.
int minHeight = d->m_btnFrame->sizeHint().height();
if (d->m_activityFrame->sizeHint().height() > minHeight) minHeight = d->m_activityFrame->sizeHint().height();
if (d->m_warmingUp->sizeHint().height() > minHeight) minHeight = d->m_warmingUp->sizeHint().height();
d->m_btnFrame->setMinimumHeight(minHeight);
d->m_activityFrame->setMinimumHeight(minHeight);
d->m_warmingUp->setMinimumHeight(minHeight);
d->m_previewFrame = new QWidget;
QVBoxLayout *preview_layout = new QVBoxLayout(d->m_previewFrame);
preview_layout->setContentsMargins(0,0,0,0);
preview_layout->addWidget(d->m_previewViewer, 100);
preview_layout->addWidget(d->m_warmingUp, 0);
preview_layout->addWidget(d->m_activityFrame, 0);
preview_layout->addWidget(d->m_btnFrame, 0);
// Create Options Widget
d->m_optsTabWidget = new KTabWidget;
// Add the basic options tab
d->m_basicScrollA = new QScrollArea;
d->m_basicScrollA->setWidgetResizable(true);
d->m_basicScrollA->setFrameShape(QFrame::NoFrame);
d->m_optsTabWidget->addTab(d->m_basicScrollA, i18n("Basic Options"));
// Add the other options tab
d->m_otherScrollA = new QScrollArea;
d->m_otherScrollA->setWidgetResizable(true);
d->m_otherScrollA->setFrameShape(QFrame::NoFrame);
d->m_optsTabWidget->addTab(d->m_otherScrollA, i18n("Scanner Specific Options"));
d->m_splitter = new QSplitter(this);
d->m_splitter->addWidget(d->m_optsTabWidget);
d->m_splitter->setStretchFactor(0,0);
d->m_splitter->addWidget(d->m_previewFrame);
d->m_splitter->setStretchFactor(1,100);
d->m_optionsCollapser = new SplitterCollapser(d->m_splitter, d->m_optsTabWidget);
QHBoxLayout *base_layout = new QHBoxLayout(this);
base_layout->addWidget(d->m_splitter);
base_layout->setContentsMargins(0,0,0,0);
// disable the interface in case no device is opened.
d->m_optsTabWidget->setDisabled(true);
d->m_previewViewer->setDisabled(true);
d->m_btnFrame->setDisabled(true);
}
KSaneWidget::~KSaneWidget()
{
while (!closeDevice()) usleep(1000);
// wait for any thread to exit
s_objectMutex.lock();
s_objectCount--;
if (s_objectCount <= 0) {
// only delete the find-devices and authorization singletons and call sane_exit
// if this is the last instance
delete d->m_findDevThread;
delete d->m_auth;
sane_exit();
}
s_objectMutex.unlock();
delete d;
}
QString KSaneWidget::vendor() const
{
d->m_findDevThread->wait();
d->devListUpdated(); // this is just a wrapped if (m_vendor.isEmpty()) statement if the vendor is known
// devListUpdated here is to ensure that we do not come in between finished and the devListUpdated slot
return d->m_vendor;
}
QString KSaneWidget::make() const
{
return vendor();
}
QString KSaneWidget::model() const
{
d->m_findDevThread->wait();
d->devListUpdated(); // this is just a wrapped if (m_vendor.isEmpty()) statement if the vendor is known
// devListUpdated here is to ensure that we do not come in between finished and the devListUpdated slot
return d->m_model;
}
QString KSaneWidget::selectDevice(QWidget* parent)
{
QString selected_name;
QPointer<KSaneDeviceDialog> sel = new KSaneDeviceDialog(parent);
// sel.setDefault(prev_backend); // set default scanner - perhaps application using libksane should remember that
if(sel->exec() == KDialog::Accepted) {
selected_name = sel->getSelectedName();
}
delete sel;
return selected_name;
}
void KSaneWidget::initGetDeviceList() const
{
// update the device list if needed to get the vendor and model info
if (d->m_findDevThread->devicesList().size() == 0) {
//kDebug() << "initGetDeviceList() starting thread...";
d->m_findDevThread->start();
}
else {
//kDebug() << "initGetDeviceList() have existing data...";
d->signalDevListUpdate();
}
}
bool KSaneWidget::openDevice(const QString &deviceName)
{
int i=0;
const SANE_Option_Descriptor *optDesc;
SANE_Status status;
SANE_Word numSaneOptions;
SANE_Int res;
KPasswordDialog *dlg;
KWallet::Wallet *saneWallet;
QString myFolderName("ksane");
QMap<QString, QString> wallet_entry;
if (d->m_saneHandle != 0) {
// this KSaneWidget already has an open device
return false;
}
// don't bother trying to open if the device string is empty
if (deviceName.isEmpty()) {
return false;
}
// save the device name
d->m_devName = deviceName;
// Try to open the device
status = sane_open(deviceName.toLatin1(), &d->m_saneHandle);
bool password_dialog_ok = true;
// prepare wallet for authentication and create password dialog
if(status == SANE_STATUS_ACCESS_DENIED) {
saneWallet = KWallet::Wallet::openWallet(KWallet::Wallet::LocalWallet(), winId() );
if(saneWallet) {
dlg = new KPasswordDialog(this, KPasswordDialog::ShowUsernameLine | KPasswordDialog::ShowKeepPassword);
if(!saneWallet->hasFolder(myFolderName)) {
saneWallet->createFolder(myFolderName);
}
saneWallet->setFolder(myFolderName);
saneWallet->readMap(deviceName.toLatin1(), wallet_entry);
if(!wallet_entry.empty() || true) {
dlg->setUsername( wallet_entry["username"] );
dlg->setPassword( wallet_entry["password"] );
dlg->setKeepPassword( true );
}
} else {
dlg = new KPasswordDialog(this, KPasswordDialog::ShowUsernameLine);
}
dlg->setPrompt(i18n("Authentication required for resource: %1", deviceName ) );
}
// sane_open failed due to insufficient authorization
// retry opening device with user provided data assisted with kwallet records
while (status == SANE_STATUS_ACCESS_DENIED) {
password_dialog_ok = dlg->exec();
if(!password_dialog_ok) {
delete dlg;
d->m_devName.clear();
return false; //the user canceled
}
// add/update the device user-name and password for authentication
d->m_auth->setDeviceAuth(d->m_devName, dlg->username(), dlg->password());
status = sane_open(deviceName.toLatin1(), &d->m_saneHandle);
// store password in wallet on successful authentication
if(dlg->keepPassword() && status != SANE_STATUS_ACCESS_DENIED) {
QMap<QString, QString> entry;
entry["username"] = dlg->username().toUtf8();
entry["password"] = dlg->password().toUtf8();
if(saneWallet) {
saneWallet->writeMap(deviceName.toLatin1(), entry);
}
}
}
if (status != SANE_STATUS_GOOD) {
kDebug() << "sane_open(\"" << deviceName << "\", &handle) failed! status = " << sane_strstatus(status);
d->m_auth->clearDeviceAuth(d->m_devName);
d->m_devName.clear();
return false;
}
// update the device list if needed to get the vendor and model info
if (d->m_findDevThread->devicesList().size() == 0) {
d->m_findDevThread->start();
}
else {
// use the "old" existing list
d->devListUpdated();
// if m_vendor is not updated it means that the list needs to be updated.
if (d->m_vendor.isEmpty()) {
d->m_findDevThread->start();
}
}
// Read the options (start with option 0 the number of parameters)
optDesc = sane_get_option_descriptor(d->m_saneHandle, 0);
if (optDesc == 0) {
d->m_auth->clearDeviceAuth(d->m_devName);
d->m_devName.clear();
return false;
}
QVarLengthArray<char> data(optDesc->size);
status = sane_control_option(d->m_saneHandle, 0, SANE_ACTION_GET_VALUE, data.data(), &res);
if (status != SANE_STATUS_GOOD) {
d->m_auth->clearDeviceAuth(d->m_devName);
d->m_devName.clear();
return false;
}
numSaneOptions = *reinterpret_cast<SANE_Word*>(data.data());
// read the rest of the options
for (i=1; i<numSaneOptions; ++i) {
switch (KSaneOption::optionType(sane_get_option_descriptor(d->m_saneHandle, i))) {
case KSaneOption::TYPE_DETECT_FAIL:
d->m_optList.append(new KSaneOption(d->m_saneHandle, i));
break;
case KSaneOption::TYPE_CHECKBOX:
d->m_optList.append(new KSaneOptCheckBox(d->m_saneHandle, i));
break;
case KSaneOption::TYPE_SLIDER:
d->m_optList.append(new KSaneOptSlider(d->m_saneHandle, i));
break;
case KSaneOption::TYPE_F_SLIDER:
d->m_optList.append(new KSaneOptFSlider(d->m_saneHandle, i));
break;
case KSaneOption::TYPE_COMBO:
d->m_optList.append(new KSaneOptCombo(d->m_saneHandle, i));
break;
case KSaneOption::TYPE_ENTRY:
d->m_optList.append(new KSaneOptEntry(d->m_saneHandle, i));
break;
case KSaneOption::TYPE_GAMMA:
d->m_optList.append(new KSaneOptGamma(d->m_saneHandle, i));
break;
case KSaneOption::TYPE_BUTTON:
d->m_optList.append(new KSaneOptButton(d->m_saneHandle, i));
break;
}
}
// do the connections of the option parameters
for (i=1; i<d->m_optList.size(); ++i) {
//kDebug() << d->m_optList.at(i)->name();
connect (d->m_optList.at(i), SIGNAL(optsNeedReload()), d, SLOT(optReload()));
connect (d->m_optList.at(i), SIGNAL(valsNeedReload()), d, SLOT(scheduleValReload()));
if (d->m_optList.at(i)->needsPolling()) {
//kDebug() << d->m_optList.at(i)->name() << " needs polling";
d->m_pollList.append(d->m_optList.at(i));
KSaneOptCheckBox *buttonOption = qobject_cast<KSaneOptCheckBox *>(d->m_optList.at(i));
if (buttonOption) {
connect(buttonOption, SIGNAL(buttonPressed(QString,QString,bool)),
this, SIGNAL(buttonPressed(QString,QString,bool)));
}
}
}
// start polling the poll options
if (d->m_pollList.size() > 0) {
d->m_optionPollTmr.start();
}
// Create the preview thread
d->m_previewThread = new KSanePreviewThread(d->m_saneHandle, &d->m_previewImg);
connect(d->m_previewThread, SIGNAL(finished()), d, SLOT(previewScanDone()));
// Create the read thread
d->m_scanThread = new KSaneScanThread(d->m_saneHandle, &d->m_scanData);
connect(d->m_scanThread, SIGNAL(finished()), d, SLOT(oneFinalScanDone()));
// Create the options interface
d->createOptInterface();
// try to set KSaneWidget default values
d->setDefaultValues();
// Enable the interface
d->m_optsTabWidget->setDisabled(false);
d->m_previewViewer->setDisabled(false);
d->m_btnFrame->setDisabled(false);
// estimate the preview size and create an empty image
// this is done so that you can select scan area without
// having to scan a preview.
d->updatePreviewSize();
QTimer::singleShot(1000, d->m_previewViewer, SLOT(zoom2Fit()));
return true;
}
bool KSaneWidget::closeDevice()
{
if (!d->m_saneHandle) {
return true;
}
if (d->m_scanThread->isRunning()) {
d->m_scanThread->cancelScan();
d->m_closeDevicePending = true;
return false;
}
if (d->m_previewThread->isRunning()) {
d->m_previewThread->cancelScan();
d->m_closeDevicePending = true;
return false;
}
d->m_auth->clearDeviceAuth(d->m_devName);
// else
sane_close(d->m_saneHandle);
d->m_saneHandle = 0;
d->clearDeviceOptions();
// disable the interface until a new device is opened.
d->m_optsTabWidget->setDisabled(true);
d->m_previewViewer->setDisabled(true);
d->m_btnFrame->setDisabled(true);
return true;
}
#define inc_pixel(x,y,ppl) { x++; if (x>=ppl) { y++; x=0;} }
QImage KSaneWidget::toQImageSilent(const QByteArray &data,
int width,
int height,
int bytes_per_line,
ImageFormat format)
{
QImage img;
int j=0;
QVector<QRgb> table;
QRgb *imgLine;
switch (format)
{
case FormatBlackWhite:
img = QImage((uchar*)data.data(),
width,
height,
bytes_per_line,
QImage::Format_Mono);
// The color table must be set
table.append(0xFFFFFFFF);
table.append(0xFF000000);
img.setColorTable(table);
break;
case FormatGrayScale8:
{
img = QImage(width, height, QImage::Format_RGB32);
int dI = 0;
for (int i=0; (i<img.height() && dI<data.size()); i++) {
imgLine = reinterpret_cast<QRgb*>(img.scanLine(i));
for (j=0; (j<img.width() && dI<data.size()); j++) {
imgLine[j] = qRgb(data[dI], data[dI], data[dI]);
dI++;
}
}
break;
}
case FormatGrayScale16:
{
img = QImage(width, height, QImage::Format_RGB32);
int dI = 1;
for (int i=0; (i<img.height() && dI<data.size()); i++) {
imgLine = reinterpret_cast<QRgb*>(img.scanLine(i));
for (j=0; (j<img.width() && dI<data.size()); j++) {
imgLine[j] = qRgb(data[dI], data[dI], data[dI]);
dI+=2;
}
}
break;
}
case FormatRGB_8_C:
{
img = QImage(width, height, QImage::Format_RGB32);
int dI = 0;
for (int i=0; (i<img.height() && dI<data.size()); i++) {
imgLine = reinterpret_cast<QRgb*>(img.scanLine(i));
for (j=0; (j<img.width() && dI<data.size()); j++) {
imgLine[j] = qRgb(data[dI], data[dI+1], data[dI+2]);
dI+=3;
}
}
break;
}
case FormatRGB_16_C:
{
img = QImage(width, height, QImage::Format_RGB32);
int dI = 1;
for (int i=0; (i<img.height() && dI<data.size()); i++) {
imgLine = reinterpret_cast<QRgb*>(img.scanLine(i));
for (j=0; (j<img.width() && dI<data.size()); j++) {
imgLine[j] = qRgb(data[dI], data[dI+2], data[dI+4]);
dI+=6;
}
}
break;
}
case FormatNone:
default:
kDebug() << "Unsupported conversion";
break;
}
float dpm = currentDPI() * (1000.0 / 25.4);
img.setDotsPerMeterX(dpm);
img.setDotsPerMeterY(dpm);
return img;
}
QImage KSaneWidget::toQImage(const QByteArray &data,
int width,
int height,
int bytes_per_line,
ImageFormat format)
{
if ((format == FormatRGB_16_C) || (format == FormatGrayScale16)) {
d->alertUser(KSaneWidget::ErrorGeneral, i18n("The image data contained 16 bits per color, "
"but the color depth has been truncated to 8 bits per color."));
}
return toQImageSilent(data, width, height, bytes_per_line, format);
}
void KSaneWidget::scanFinal()
{
if (d->m_btnFrame->isEnabled()) {
d->startFinalScan();
}
else {
// if the button frame is disabled, there is no open device to scan from
emit scanDone(KSaneWidget::ErrorGeneral, "");
}
}
void KSaneWidget::scanCancel()
{
if (d->m_scanThread->isRunning()) {
d->m_scanThread->cancelScan();
}
if (d->m_previewThread->isRunning()) {
d->m_previewThread->cancelScan();
}
}
void KSaneWidget::setPreviewResolution(float dpi)
{
d->m_previewDPI = dpi;
}
void KSaneWidget::getOptVals(QMap <QString, QString> &opts)
{
KSaneOption *option;
opts.clear();
QString tmp;
for (int i=1; i<d->m_optList.size(); i++) {
option = d->m_optList.at(i);
if (option->getValue(tmp)) {
opts[option->name()] = tmp;
}
}
// Special handling for non sane option
opts[InvetColorsOption] = d->m_invertColors->isChecked() ? "true" : "false";
}
bool KSaneWidget::getOptVal(const QString &optname, QString &value)
{
KSaneOption *option;
if ((option = d->getOption(optname)) != 0) {
return option->getValue(value);
}
// Special handling for non sane option
if (optname == InvetColorsOption) {
value = d->m_invertColors->isChecked() ? "true" : "false";
return true;
}
return false;
}
int KSaneWidget::setOptVals(const QMap <QString, QString> &opts)
{
QString tmp;
int i;
int ret=0;
for (i=0; i<d->m_optList.size(); i++) {
if (opts.contains(d->m_optList.at(i)->name())) {
tmp = opts[d->m_optList.at(i)->name()];
if (d->m_optList.at(i)->setValue(tmp) == false) {
ret++;
}
}
}
if ((d->m_splitGamChB) &&
(d->m_optGamR) &&
(d->m_optGamG) &&
(d->m_optGamB))
{
// check if the current gamma values are identical. if they are identical,
// uncheck the "Separate color intensity tables" checkbox
QString redGamma;
QString greenGamma;
QString blueGamma;
d->m_optGamR->getValue(redGamma);
d->m_optGamG->getValue(greenGamma);
d->m_optGamB->getValue(blueGamma);
if ((redGamma == greenGamma) && (greenGamma == blueGamma)) {
d->m_splitGamChB->setChecked(false);
// set the values to the common gamma widget
d->m_commonGamma->setValues(redGamma);
}
else {
d->m_splitGamChB->setChecked(true);
}
}
// special handling for non-sane option
if (opts.contains(InvetColorsOption)) {
tmp = opts[InvetColorsOption];
if ((tmp.compare("true", Qt::CaseInsensitive) == 0) ||
(tmp.compare("1") == 0))
{
d->m_invertColors->setChecked(true);
}
else {
d->m_invertColors->setChecked(false);
}
}
return ret;
}
bool KSaneWidget::setOptVal(const QString &option, const QString &value)
{
KSaneOption *opt;
if ((opt = d->getOption(option)) != 0) {
if (opt->setValue(value)) {
if ((d->m_splitGamChB) &&
(d->m_optGamR) &&
(d->m_optGamG) &&
(d->m_optGamB) &&
((opt == d->m_optGamR) ||
(opt == d->m_optGamG) ||
(opt == d->m_optGamB)))
{
// check if the current gamma values are identical. if they are identical,
// uncheck the "Separate color intensity tables" checkbox
QString redGamma;
QString greenGamma;
QString blueGamma;
d->m_optGamR->getValue(redGamma);
d->m_optGamG->getValue(greenGamma);
d->m_optGamB->getValue(blueGamma);
if ((redGamma == greenGamma) && (greenGamma == blueGamma)) {
d->m_splitGamChB->setChecked(false);
// set the values to the common gamma widget
d->m_commonGamma->setValues(redGamma);
}
else {
d->m_splitGamChB->setChecked(true);
}
}
return true;
}
}
// special handling for non-sane option
if (option == InvetColorsOption) {
if ((value.compare("true", Qt::CaseInsensitive) == 0) ||
(value.compare("1") == 0))
{
d->m_invertColors->setChecked(true);
}
else {
d->m_invertColors->setChecked(false);
}
return true;
}
return false;
}
void KSaneWidget::setScanButtonText(const QString &scanLabel)
{
if (d->m_scanBtn == 0) {
kError() << "setScanButtonText was called before KSaneWidget was initialized";
return;
}
d->m_scanBtn->setText(scanLabel);
}
void KSaneWidget::setPreviewButtonText(const QString &previewLabel)
{
if (d->m_scanBtn == 0) {
kError() << "setPreviewButtonText was called before KSaneWidget was initialized";
return;
}
d->m_prevBtn->setText(previewLabel);
}
void KSaneWidget::enableAutoSelect(bool enable)
{
d->m_autoSelect = enable;
}
float KSaneWidget::currentDPI()
{
if (d->m_optRes) {
float value;
if (d->m_optRes->getValue(value)) {
return value;
}
}
return 0.0;
}
float KSaneWidget::scanAreaWidth()
{
float result = 0.0;
if (d->m_optBrX) {
if (d->m_optBrX->getUnit() == SANE_UNIT_PIXEL) {
d->m_optBrX->getMaxValue(result);
result = result / currentDPI() / 25.4;
}
else if (d->m_optBrX->getUnit() == SANE_UNIT_MM) {
d->m_optBrX->getMaxValue(result);
}
}
return result;
}
float KSaneWidget::scanAreaHeight()
{
float result = 0.0;
if (d->m_optBrY) {
if (d->m_optBrY->getUnit() == SANE_UNIT_PIXEL) {
d->m_optBrY->getMaxValue(result);
result = result / currentDPI() / 25.4;
}
else if (d->m_optBrY->getUnit() == SANE_UNIT_MM) {
d->m_optBrY->getMaxValue(result);
}
}
return result;
}
void KSaneWidget::setSelection(QPointF topLeft, QPointF bottomRight)
{
if (!d->m_optBrX || !d->m_optBrY || !d->m_optTlX || !d->m_optTlY) {
return;
}
float xmax, ymax;
d->m_optBrX->getMaxValue(xmax);
d->m_optBrY->getMaxValue(ymax);
if (topLeft.x() < 0.0 || topLeft.y() < 0.0 || bottomRight.x() < 0.0 || bottomRight.y() < 0.0) {
d->m_previewViewer->clearActiveSelection();
d->m_optTlX->setValue(0.0);
d->m_optTlY->setValue(0.0);
d->m_optBrX->setValue(xmax);
d->m_optBrY->setValue(ymax);
}
if (d->m_optBrY->getUnit() == SANE_UNIT_MM) {
// clear selection if values are out of bounds
if (topLeft.x() > xmax || topLeft.y() > ymax || bottomRight.x() > xmax || bottomRight.y() > ymax) {
d->m_previewViewer->clearActiveSelection();
d->m_optTlX->setValue(0.0);
d->m_optTlY->setValue(0.0);
d->m_optBrX->setValue(xmax);
d->m_optBrY->setValue(ymax);
}
d->m_previewViewer->setSelection(topLeft.x(), topLeft.y(), bottomRight.x(), bottomRight.y());
d->m_optTlX->setValue(topLeft.x());
d->m_optTlY->setValue(topLeft.y());
d->m_optBrX->setValue(bottomRight.x());
d->m_optBrY->setValue(bottomRight.y());
}
else if (d->m_optBrY->getUnit() == SANE_UNIT_PIXEL) {
const float mmperinch = 25.4;
const float dpi = currentDPI();
const float m = dpi / mmperinch;
if (m*topLeft.x() > xmax || m*topLeft.y() > ymax || m*bottomRight.x() > xmax || m*bottomRight.y() > ymax) {
d->m_previewViewer->clearActiveSelection();
d->m_optTlX->setValue(0.0);
d->m_optTlY->setValue(0.0);
d->m_optBrX->setValue(xmax);
d->m_optBrY->setValue(ymax);
}
d->m_previewViewer->setSelection(m*topLeft.x(), m*topLeft.y(), m*bottomRight.x(), m*bottomRight.y());
d->m_optTlX->setValue(m*topLeft.x());
d->m_optTlY->setValue(m*topLeft.y());
d->m_optBrX->setValue(m*bottomRight.x());
d->m_optBrY->setValue(m*bottomRight.y());
}
}
void KSaneWidget::setOptionsCollapsed(bool collapse)
{
if (collapse) {
QTimer::singleShot(0, d->m_optionsCollapser, SLOT(slotCollapse()));
}
else {
QTimer::singleShot(0, d->m_optionsCollapser, SLOT(slotRestore()));
}
}
void KSaneWidget::setScanButtonHidden(bool hidden)
{
d->m_scanBtn->setHidden(hidden);
}
} // NameSpace KSaneIface

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,204 @@
/* ============================================================
*
* This file is part of the KDE project
*
* Date : 2009-01-21
* Description : Sane interface for KDE
*
* Copyright (C) 2009 by Kare Sars <kare dot sars at iki dot fi>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================ */
#ifndef KSANE_WIDGET_PRIVATE_H
#define KSANE_WIDGET_PRIVATE_H
// Sane includes
extern "C"
{
#include <sane/saneopts.h>
#include <sane/sane.h>
}
// Qt includes
#include <QtGui/QWidget>
#include <QCheckBox>
#include <QTimer>
#include <QTime>
#include <QProgressBar>
// KDE includes
#include <KTabWidget>
#include <KLocale>
#include <KDebug>
#include <KMessageBox>
#include <KPushButton>
#include <KToolBar>
// Local includes
#include "ksane.h"
#include "ksane_option.h"
#include "ksane_viewer.h"
#include "labeled_gamma.h"
#include "labeled_checkbox.h"
#include "splittercollapser.h"
#include "ksane_scan_thread.h"
#include "ksane_preview_thread.h"
#include "ksane_find_devices_thread.h"
#include "ksane_auth.h"
#define IMG_DATA_R_SIZE 100000
/** This namespace collects all methods and classes in LibKSane. */
namespace KSaneIface
{
class KSaneWidgetPrivate: public QObject
{
Q_OBJECT
public:
KSaneWidgetPrivate(KSaneWidget *);
void clearDeviceOptions();
void createOptInterface();
void updatePreviewSize();
void setDefaultValues();
void setBusy(bool busy);
KSaneOption *getOption(const QString &name);
KSaneWidget::ImageFormat getImgFormat(SANE_Parameters &params);
int getBytesPerLines(SANE_Parameters &params);
public Q_SLOTS:
void devListUpdated();
void signalDevListUpdate();
void startFinalScan();
void previewScanDone();
void oneFinalScanDone();
void updateProgress();
private Q_SLOTS:
void scheduleValReload();
void optReload();
void valReload();
void handleSelection(float tl_x, float tl_y, float br_x, float br_y);
void setTLX(float x);
void setTLY(float y);
void setBRX(float x);
void setBRY(float y);
void startPreviewScan();
void checkInvert();
void invertPreview();
void pollPollOptions();
public:
void alertUser(int type, const QString &strStatus);
public:
// backend independent
KTabWidget *m_optsTabWidget;
QScrollArea *m_basicScrollA;
QWidget *m_basicOptsTab;
QWidget *m_colorOpts;
QScrollArea *m_otherScrollA;
QWidget *m_otherOptsTab;
LabeledCheckbox *m_invertColors;
QSplitter *m_splitter;
SplitterCollapser *m_optionsCollapser;
QWidget *m_previewFrame;
KSaneViewer *m_previewViewer;
QWidget *m_btnFrame;
QToolButton *m_zInBtn;
QToolButton *m_zOutBtn;
QToolButton *m_zSelBtn;
QToolButton *m_zFitBtn;
QToolButton *m_clearSelBtn;
KPushButton *m_scanBtn;
KPushButton *m_prevBtn;
QWidget *m_activityFrame;
QLabel *m_warmingUp;
QProgressBar *m_progressBar;
KPushButton *m_cancelBtn;
// device info
SANE_Handle m_saneHandle;
QString m_devName;
QString m_vendor;
QString m_model;
// Option variables
QList<KSaneOption*> m_optList;
QList<KSaneOption*> m_pollList;
KSaneOption *m_optSource;
KSaneOption *m_optNegative;
KSaneOption *m_optFilmType;
KSaneOption *m_optMode;
KSaneOption *m_optDepth;
KSaneOption *m_optRes;
KSaneOption *m_optResX;
KSaneOption *m_optResY;
KSaneOption *m_optTlX;
KSaneOption *m_optTlY;
KSaneOption *m_optBrX;
KSaneOption *m_optBrY;
KSaneOption *m_optPreview;
KSaneOption *m_optGamR;
KSaneOption *m_optGamG;
KSaneOption *m_optGamB;
LabeledCheckbox *m_splitGamChB;
LabeledGamma *m_commonGamma;
KSaneOption *m_optWaitForBtn;
// preview variables
float m_previewWidth;
float m_previewHeight;
float m_previewDPI;
QImage m_previewImg;
bool m_isPreview;
bool m_autoSelect;
int m_selIndex;
bool m_scanOngoing;
bool m_closeDevicePending;
// final image data
QByteArray m_scanData;
// option handling
QTimer m_readValsTmr;
QTimer m_updProgressTmr;
QTimer m_optionPollTmr;
KSaneScanThread *m_scanThread;
KSanePreviewThread *m_previewThread;
QString m_saneUserName;
QString m_sanePassword;
FindSaneDevicesThread *m_findDevThread;
KSaneAuth *m_auth;
KSaneWidget *q;
};
} // NameSpace KSaneIface
#endif // SANE_WIDGET_H

View file

@ -0,0 +1,40 @@
/* This file is part of the KDE project
Copyright (C) 2007 David Faure <faure@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef LIBKSANE_EXPORT_H
#define LIBKSANE_EXPORT_H
/* needed for KDE_EXPORT and KDE_IMPORT macros */
#include <kdemacros.h>
#ifndef LIBKSANE_EXPORT
# if defined(MAKE_KSANE_LIB)
/* We are building this library */
# define LIBKSANE_EXPORT KDE_EXPORT
# else
/* We are using this library */
# define LIBKSANE_EXPORT KDE_IMPORT
# endif
#endif
# ifndef LIBKSANE_EXPORT_DEPRECATED
# define LIBKSANE_EXPORT_DEPRECATED KDE_DEPRECATED LIBKSANE_EXPORT
# endif
#endif

View file

@ -0,0 +1,71 @@
/* ============================================================
*
* This file is part of the KDE project
*
* Date : 2009-01-21
* Description : Sane interface for KDE
*
* Copyright (C) 2009 by Kare Sars <kare dot sars at iki dot fi>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================ */
// Local includes
#include "ksane_opt_button.h"
#include "ksane_opt_button.moc"
#include "ksane_button.h"
// KDE includes
#include <KDebug>
#include <KLocale>
namespace KSaneIface
{
KSaneOptButton::KSaneOptButton(const SANE_Handle handle, const int index)
: KSaneOption(handle, index), m_button(0)
{
}
void KSaneOptButton::createWidget(QWidget *parent)
{
if (m_widget) return;
readOption();
if (!m_optDesc) {
kDebug() << "This is a bug";
m_widget = new KSaneOptionWidget(parent, "");
return;
}
m_widget = m_button = new KSaneButton(parent, i18n(m_optDesc->title));
m_widget->setToolTip(i18n(m_optDesc->desc));
connect(m_button, SIGNAL(clicked()), this, SLOT(buttonClicked()));
updateVisibility();
readValue();
}
void KSaneOptButton::buttonClicked()
{
unsigned char data[4];
writeData(data);
}
} // NameSpace KSaneIface

View file

@ -0,0 +1,58 @@
/* ============================================================
*
* This file is part of the KDE project
*
* Date : 2009-01-21
* Description : Sane interface for KDE
*
* Copyright (C) 2009 by Kare Sars <kare dot sars at iki dot fi>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================ */
#ifndef KSANE_OPT_BUTTON_H
#define KSANE_OPT_BUTTON_H
#include "ksane_option.h"
namespace KSaneIface
{
class KSaneButton;
class KSaneOptButton : public KSaneOption
{
Q_OBJECT
public:
KSaneOptButton(const SANE_Handle handle, const int index);
void createWidget(QWidget *parent);
bool hasGui() {return true;}
private Q_SLOTS:
void buttonClicked();
private:
KSaneButton *m_button;
};
} // NameSpace KSaneIface
#endif // KSANE_BUTTON_OPT_H

View file

@ -0,0 +1,138 @@
/* ============================================================
*
* This file is part of the KDE project
*
* Date : 2009-01-21
* Description : Sane interface for KDE
*
* Copyright (C) 2009 by Kare Sars <kare dot sars at iki dot fi>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================ */
// Local includes
#include "ksane_opt_checkbox.h"
#include "ksane_opt_checkbox.moc"
#include "labeled_checkbox.h"
// Qt includes
#include <QtCore/QVarLengthArray>
// KDE includes
#include <KDebug>
#include <KLocale>
namespace KSaneIface
{
KSaneOptCheckBox::KSaneOptCheckBox(const SANE_Handle handle, const int index)
: KSaneOption(handle, index), m_checkbox(0), m_checked(false)
{
}
void KSaneOptCheckBox::createWidget(QWidget *parent)
{
if (m_widget) return;
readOption();
if (!m_optDesc) {
kDebug() << "This is a bug";
m_widget = new KSaneOptionWidget(parent, "");
return;
}
m_widget = m_checkbox = new LabeledCheckbox(parent, i18n(m_optDesc->title));
m_widget->setToolTip(i18n(m_optDesc->desc));
connect(m_checkbox, SIGNAL(toggled(bool)), this, SLOT(checkboxChanged(bool)));
updateVisibility();
readValue();
}
void KSaneOptCheckBox::checkboxChanged(bool toggled)
{
unsigned char data[4];
m_checked = toggled;
fromSANE_Word(data, (toggled) ? 1:0);
writeData(data);
}
void KSaneOptCheckBox::readValue()
{
if (state() == STATE_HIDDEN) return;
// read the current value
QVarLengthArray<unsigned char> data(m_optDesc->size);
SANE_Status status;
SANE_Int res;
status = sane_control_option (m_handle, m_index, SANE_ACTION_GET_VALUE, data.data(), &res);
if (status != SANE_STATUS_GOOD) {
return;
}
bool old = m_checked;
m_checked = (toSANE_Word(data.data()) != 0) ? true:false;
if (m_checkbox) {
m_checkbox->setChecked(m_checked);
}
if ((old != m_checked) && ((m_optDesc->cap & SANE_CAP_SOFT_SELECT) == 0)) {
emit buttonPressed(name(), i18n(m_optDesc->title), m_checked);
}
}
bool KSaneOptCheckBox::getValue(float &val)
{
if (state() == STATE_HIDDEN) return false;
val = m_checked ? 1.0 : 0.0;
return true;
}
bool KSaneOptCheckBox::setValue(float val)
{
if (state() == STATE_HIDDEN) return false;
checkboxChanged(val == 0);
readValue();
return true;
}
bool KSaneOptCheckBox::getValue(QString &val)
{
if (state() == STATE_HIDDEN) return false;
val = m_checked ? "true" : "false";
return true;
}
bool KSaneOptCheckBox::setValue(const QString &val)
{
if (state() == STATE_HIDDEN) return false;
if ((val.compare("true", Qt::CaseInsensitive) == 0) ||
(val.compare("1") == 0))
{
checkboxChanged(true);
}
else {
checkboxChanged(false);
}
readValue();
return true;
}
} // NameSpace KSaneIface

View file

@ -0,0 +1,68 @@
/* ============================================================
*
* This file is part of the KDE project
*
* Date : 2009-01-21
* Description : Sane interface for KDE
*
* Copyright (C) 2009 by Kare Sars <kare dot sars at iki dot fi>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================ */
#ifndef KSANE_OPT_CHECKBOX_H
#define KSANE_OPT_CHECKBOX_H
#include "ksane_option.h"
namespace KSaneIface
{
class LabeledCheckbox;
class KSaneOptCheckBox : public KSaneOption
{
Q_OBJECT
public:
KSaneOptCheckBox(const SANE_Handle handle, const int index);
void createWidget(QWidget *parent);
void readValue();
bool getValue(float &val);
bool setValue(float val);
bool getValue(QString &val);
bool setValue(const QString &val);
bool hasGui() {return true;}
private Q_SLOTS:
void checkboxChanged(bool toggled);
Q_SIGNALS:
void buttonPressed(const QString &optionName, const QString &optionLabel, bool pressed);
private:
LabeledCheckbox *m_checkbox;
bool m_checked;
};
} // NameSpace KSaneIface
#endif

View file

@ -0,0 +1,380 @@
/* ============================================================
*
* This file is part of the KDE project
*
* Date : 2009-01-21
* Description : Sane interface for KDE
*
* Copyright (C) 2009 by Kare Sars <kare dot sars at iki dot fi>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================ */
// Local includes
#include "ksane_opt_combo.h"
#include "ksane_opt_combo.moc"
#include "labeled_combo.h"
// Qt includes
#include <QtCore/QVarLengthArray>
// KDE includes
#include <kicon.h>
#include <KDebug>
#include <KLocale>
namespace KSaneIface
{
static const char tmp_binary[] = "Binary";
KSaneOptCombo::KSaneOptCombo(const SANE_Handle handle, const int index)
: KSaneOption(handle, index), m_combo(0)
{
}
void KSaneOptCombo::createWidget(QWidget *parent)
{
if (m_widget) return;
m_widget = m_combo = new LabeledCombo(parent, "", QStringList());
readOption();
m_widget->setToolTip(i18n(m_optDesc->desc));
connect(m_combo, SIGNAL(activated(int)), this, SLOT(comboboxChangedIndex(int)));
readValue();
}
void KSaneOptCombo::readValue()
{
if (state() == STATE_HIDDEN) return;
// read that current value
QVarLengthArray<unsigned char> data(m_optDesc->size);
SANE_Status status;
SANE_Int res;
status = sane_control_option (m_handle, m_index, SANE_ACTION_GET_VALUE, data.data(), &res);
if (status != SANE_STATUS_GOOD) {
return;
}
m_currentText = getSaneComboString(data.data());
if (m_combo != 0) {
if (m_combo->currentText() != m_currentText) {
m_combo->setCurrentText(m_currentText);
emit valueChanged();
}
}
}
void KSaneOptCombo::readOption()
{
KSaneOption::readOption();
if (!m_combo) return;
QString saved = m_combo->currentText();
m_strList = genComboStringList();
m_combo->clear();
m_combo->setLabelText(i18n(m_optDesc->title));
m_combo->addItems(m_strList);
m_combo->setIcon(KIcon("color"), getSaneComboString((unsigned char*)SANE_VALUE_SCAN_MODE_COLOR));
m_combo->setIcon(KIcon("gray-scale"),
getSaneComboString((unsigned char*)SANE_VALUE_SCAN_MODE_GRAY));
m_combo->setIcon(KIcon("black-white"),
getSaneComboString((unsigned char*)SANE_VALUE_SCAN_MODE_LINEART));
// The epkowa/epson backend uses "Binary" which is the same as "Lineart"
m_combo->setIcon(KIcon("black-white"), i18n(tmp_binary));
// set the previous value
m_combo->setCurrentText(saved);
}
QStringList &KSaneOptCombo::genComboStringList()
{
int i;
m_strList.clear();
switch (m_optDesc->type)
{
case SANE_TYPE_INT:
for (i=1; i<=m_optDesc->constraint.word_list[0]; ++i) {
m_strList += getSaneComboString((int)m_optDesc->constraint.word_list[i]);
}
break;
case SANE_TYPE_FIXED:
for (i=1; i<=m_optDesc->constraint.word_list[0]; ++i) {
m_strList += getSaneComboString((float)SANE_UNFIX(m_optDesc->constraint.word_list[i]));
}
break;
case SANE_TYPE_STRING:
i=0;
while (m_optDesc->constraint.string_list[i] != 0) {
m_strList += getSaneComboString((unsigned char *)m_optDesc->constraint.string_list[i]);
i++;
}
break;
default :
m_strList += "NOT HANDELED";
break;
}
return m_strList;
}
QString KSaneOptCombo::getSaneComboString(int ival)
{
switch(m_optDesc->unit)
{
case SANE_UNIT_NONE: break;
case SANE_UNIT_PIXEL: return i18np("%1 Pixel","%1 Pixels", ival);
case SANE_UNIT_BIT: return i18np("%1 Bit","%1 Bits", ival);
case SANE_UNIT_MM: return i18np("%1 mm","%1 mm", ival);
case SANE_UNIT_DPI: return i18np("%1 DPI","%1 DPI", ival);
case SANE_UNIT_PERCENT: return i18np("%1 %","%1 %", ival);
case SANE_UNIT_MICROSECOND: return i18np("%1 µs","%1 µs", ival);
}
return QString::number(ival);
}
QString KSaneOptCombo::getSaneComboString(float fval)
{
switch(m_optDesc->unit)
{
case SANE_UNIT_NONE: break;
case SANE_UNIT_PIXEL: return i18ncp("Parameter and Unit","%1 Pixel", "%1 Pixels", fval);
case SANE_UNIT_BIT: return i18ncp("Parameter and Unit","%1 Bit","%1 Bits", fval);
case SANE_UNIT_MM: return i18nc("Parameter and Unit (Millimeter)","%1 mm", fval);
case SANE_UNIT_DPI: return i18nc("Parameter and Unit (Dots Per Inch)","%1 DPI", fval);
case SANE_UNIT_PERCENT: return i18nc("Parameter and Unit (Percentage)","%1 %", fval);
case SANE_UNIT_MICROSECOND: return i18nc("Parameter and Unit (Microseconds)","%1 µs", fval);
}
return QString::number(fval, 'F', 4);
}
QString KSaneOptCombo::getSaneComboString(unsigned char *data)
{
QString tmp;
if (data == 0) return QString();
switch (m_optDesc->type)
{
case SANE_TYPE_INT:
return getSaneComboString((int)toSANE_Word(data));
case SANE_TYPE_FIXED:
return getSaneComboString((float)SANE_UNFIX(toSANE_Word(data)));
case SANE_TYPE_STRING:
tmp = i18n(reinterpret_cast<char*>(data));
tmp = tmp.simplified();
return tmp;
default :
break;
}
return QString();
}
void KSaneOptCombo::comboboxChangedIndex(int i)
{
if (m_combo && (m_combo->currentText() == m_currentText)) {
return;
}
unsigned char data[4];
void *dataPtr;
switch (m_optDesc->type)
{
case SANE_TYPE_INT:
case SANE_TYPE_FIXED:
fromSANE_Word(data, m_optDesc->constraint.word_list[i+1]);
dataPtr = data;
break;
case SANE_TYPE_STRING:
dataPtr = (void *)m_optDesc->constraint.string_list[i];
break;
default:
kDebug() << "can not handle type:" << m_optDesc->type;
return;
}
writeData(dataPtr);
readValue();
emit valueChanged();
}
bool KSaneOptCombo::getMinValue(float &val)
{
if (state() == STATE_HIDDEN) return false;
switch (m_optDesc->type)
{
case SANE_TYPE_INT:
val = (float)m_optDesc->constraint.word_list[1];
for (int i=2; i<=m_optDesc->constraint.word_list[0]; i++) {
val = qMin((float)m_optDesc->constraint.word_list[i], val);
}
break;
case SANE_TYPE_FIXED:
val = (float)SANE_UNFIX(m_optDesc->constraint.word_list[1]);
for (int i=2; i<=m_optDesc->constraint.word_list[0]; i++) {
val = qMin((float)SANE_UNFIX(m_optDesc->constraint.word_list[i]), val);
}
break;
default:
kDebug() << "can not handle type:" << m_optDesc->type;
return false;
}
return true;
}
bool KSaneOptCombo::getValue(float &val)
{
if (state() == STATE_HIDDEN) return false;
// read that current value
QVarLengthArray<unsigned char> data(m_optDesc->size);
SANE_Status status;
SANE_Int res;
status = sane_control_option (m_handle, m_index, SANE_ACTION_GET_VALUE, data.data(), &res);
if (status != SANE_STATUS_GOOD) {
kDebug() << m_optDesc->name << "sane_control_option returned" << status;
return false;
}
switch (m_optDesc->type)
{
case SANE_TYPE_INT:
val = (float)toSANE_Word(data.data());
return true;
case SANE_TYPE_FIXED:
val = SANE_UNFIX(toSANE_Word(data.data()));
return true;
default:
kDebug() << "Type" << m_optDesc->type << "not supported!";
break;
}
return false;
}
bool KSaneOptCombo::setValue(float value)
{
unsigned char data[4];
float tmp;
float minDiff;
int i;
int minIndex = 1;
switch (m_optDesc->type)
{
case SANE_TYPE_INT:
tmp = (float)m_optDesc->constraint.word_list[minIndex];
minDiff = qAbs(value - tmp);
for (i=2; i<=m_optDesc->constraint.word_list[0]; ++i) {
tmp = (float)m_optDesc->constraint.word_list[i];
if (qAbs(value - tmp) < minDiff) {
minDiff = qAbs(value - tmp);
minIndex = i;
}
}
fromSANE_Word(data, m_optDesc->constraint.word_list[minIndex]);
writeData(data);
readValue();
return (minDiff < 1.0);
case SANE_TYPE_FIXED:
tmp = (float)SANE_UNFIX(m_optDesc->constraint.word_list[minIndex]);
minDiff = qAbs(value - tmp);
for (i=2; i<=m_optDesc->constraint.word_list[0]; ++i) {
tmp = (float)SANE_UNFIX(m_optDesc->constraint.word_list[i]);
if (qAbs(value - tmp) < minDiff) {
minDiff = qAbs(value - tmp);
minIndex = i;
}
}
fromSANE_Word(data, m_optDesc->constraint.word_list[minIndex]);
writeData(data);
readValue();
return (minDiff < 1.0);
default:
kDebug() << "can not handle type:" << m_optDesc->type;
break;
}
return false;
}
bool KSaneOptCombo::getValue(QString &val)
{
if (state() == STATE_HIDDEN) return false;
val = m_currentText;
return true;
}
bool KSaneOptCombo::setValue(const QString &val)
{
if (state() == STATE_HIDDEN) return false;
if (val == m_currentText) return true;
unsigned char data[4];
void *data_ptr;
SANE_Word fixed;
int i;
float f;
bool ok;
QString tmp;
switch (m_optDesc->type)
{
case SANE_TYPE_INT:
tmp = val.left(val.indexOf(' ')); // strip the unit
// accept float formating of the string
i = (int)(tmp.toFloat(&ok));
if (ok == false) return false;
fromSANE_Word(data, i);
data_ptr = data;
break;
case SANE_TYPE_FIXED:
tmp = val.left(val.indexOf(' ')); // strip the unit
f = tmp.toFloat(&ok);
if (ok == false) return false;
fixed = SANE_FIX(f);
fromSANE_Word(data, fixed);
data_ptr = data;
break;
case SANE_TYPE_STRING:
i = 0;
while (m_optDesc->constraint.string_list[i] != 0) {
tmp = getSaneComboString((unsigned char *)m_optDesc->constraint.string_list[i]);
if (val == tmp) {
data_ptr = (void *)m_optDesc->constraint.string_list[i];
break;
}
i++;
}
if (m_optDesc->constraint.string_list[i] == 0) return false;
break;
default:
kDebug() << "can only handle SANE_TYPE: INT, FIXED and STRING";
return false;
}
writeData(data_ptr);
readValue();
return true;
}
} // NameSpace KSaneIface

View file

@ -0,0 +1,76 @@
/* ============================================================
*
* This file is part of the KDE project
*
* Date : 2009-01-21
* Description : Sane interface for KDE
*
* Copyright (C) 2009 by Kare Sars <kare dot sars at iki dot fi>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================ */
#ifndef KSANE_OPT_COMBO_H
#define KSANE_OPT_COMBO_H
#include "ksane_option.h"
namespace KSaneIface
{
class LabeledCombo;
class KSaneOptCombo : public KSaneOption
{
Q_OBJECT
public:
KSaneOptCombo(const SANE_Handle handle, const int index);
void createWidget(QWidget *parent);
void readValue();
void readOption();
bool getMinValue(float &max);
bool getValue(float &val);
bool setValue(float val);
bool getValue(QString &val);
bool setValue(const QString &val);
bool hasGui() {return true;}
private Q_SLOTS:
void comboboxChangedIndex(int val);
Q_SIGNALS:
void valueChanged();
private:
QStringList &genComboStringList();
QString getSaneComboString(int ival);
QString getSaneComboString(float fval);
QString getSaneComboString(unsigned char *data);
LabeledCombo *m_combo;
QString m_currentText;
QStringList m_strList;
};
} // NameSpace KSaneIface
#endif

View file

@ -0,0 +1,114 @@
/* ============================================================
*
* This file is part of the KDE project
*
* Date : 2009-01-21
* Description : Sane interface for KDE
*
* Copyright (C) 2009 by Kare Sars <kare dot sars at iki dot fi>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================ */
// Local includes
#include "ksane_opt_entry.h"
#include "ksane_opt_entry.moc"
#include "labeled_entry.h"
// Qt includes
#include <QtCore/QVarLengthArray>
// KDE includes
#include <KDebug>
#include <KLocale>
namespace KSaneIface
{
KSaneOptEntry::KSaneOptEntry(const SANE_Handle handle, const int index)
: KSaneOption(handle, index), m_entry(0)
{
}
void KSaneOptEntry::createWidget(QWidget *parent)
{
if (m_widget) return;
readOption();
if (!m_optDesc) {
kDebug() << "This is a bug";
m_widget = new KSaneOptionWidget(parent, "");
return;
}
m_widget = m_entry = new LabeledEntry(parent, i18n(m_optDesc->title));
m_widget->setToolTip(i18n(m_optDesc->desc));
connect(m_entry, SIGNAL(entryEdited(QString)), this, SLOT(entryChanged(QString)));
updateVisibility();
readValue();
}
void KSaneOptEntry::entryChanged(const QString& text)
{
QString tmp;
tmp += text.left(m_optDesc->size);
if (tmp != text) {
m_entry->setText(tmp);
writeData(tmp.toLatin1().data());
}
}
void KSaneOptEntry::readValue()
{
if (state() == STATE_HIDDEN) return;
// read that current value
QVarLengthArray<unsigned char> data(m_optDesc->size);
SANE_Status status;
SANE_Int res;
status = sane_control_option (m_handle, m_index, SANE_ACTION_GET_VALUE, data.data(), &res);
if (status != SANE_STATUS_GOOD) {
return;
}
m_string = QString(reinterpret_cast<char*>(data.data()));
if (m_entry != 0) {
m_entry->setText(m_string);
}
}
bool KSaneOptEntry::getValue(float &) {return false;}
bool KSaneOptEntry::setValue(float) {return false;}
bool KSaneOptEntry::getValue(QString &val)
{
if (state() == STATE_HIDDEN) return false;
val = m_string;
return true;
}
bool KSaneOptEntry::setValue(const QString &val)
{
if (state() == STATE_HIDDEN) return false;
entryChanged(val);
readValue();
return true;
}
} // NameSpace KSaneIface

View file

@ -0,0 +1,65 @@
/* ============================================================
*
* This file is part of the KDE project
*
* Date : 2009-01-21
* Description : Sane interface for KDE
*
* Copyright (C) 2009 by Kare Sars <kare dot sars at iki dot fi>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================ */
#ifndef KSANE_OPT_ENTRY_H
#define KSANE_OPT_ENTRY_H
#include "ksane_option.h"
namespace KSaneIface
{
class LabeledEntry;
class KSaneOptEntry : public KSaneOption
{
Q_OBJECT
public:
KSaneOptEntry(const SANE_Handle handle, const int index);
void createWidget(QWidget *parent);
void readValue();
bool getValue(float &val);
bool setValue(float val);
bool getValue(QString &val);
bool setValue(const QString &val);
bool hasGui() {return true;}
private Q_SLOTS:
void entryChanged(const QString &text);
private:
LabeledEntry *m_entry;
QString m_string;
};
} // NameSpace KSaneIface
#endif

View file

@ -0,0 +1,176 @@
/* ============================================================
*
* This file is part of the KDE project
*
* Date : 2009-01-21
* Description : Sane interface for KDE
*
* Copyright (C) 2009 by Kare Sars <kare dot sars at iki dot fi>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================ */
// Local includes
#include "ksane_opt_fslider.h"
#include "ksane_opt_fslider.moc"
#include "labeled_fslider.h"
// Qt includes
#include <QtCore/QVarLengthArray>
// KDE includes
#include <KDebug>
#include <KLocale>
static const float FIXED_MAX = 32767.0;
static const float FIXED_MIN =-32768.0;
static const float MIN_FIXED_STEP = 0.0001;
namespace KSaneIface
{
KSaneOptFSlider::KSaneOptFSlider(const SANE_Handle handle, const int index)
: KSaneOption(handle, index), m_slider(0), m_fVal(0), m_minChange(MIN_FIXED_STEP)
{
}
void KSaneOptFSlider::createWidget(QWidget *parent)
{
if (m_widget) return;
m_widget = m_slider = new LabeledFSlider(parent, "", FIXED_MIN, FIXED_MAX, MIN_FIXED_STEP);
readOption();
m_widget->setToolTip(i18n(m_optDesc->desc));
connect(m_slider, SIGNAL(valueChanged(float)), this, SLOT(sliderChanged(float)));
readValue();
}
void KSaneOptFSlider::readOption()
{
KSaneOption::readOption();
if (!m_slider) return;
if (m_optDesc->constraint_type == SANE_CONSTRAINT_RANGE) {
m_slider->setRange(SANE_UNFIX(m_optDesc->constraint.range->min),
SANE_UNFIX(m_optDesc->constraint.range->max));
float tmpStep = SANE_UNFIX(m_optDesc->constraint.range->quant);
if (tmpStep < MIN_FIXED_STEP) tmpStep = MIN_FIXED_STEP;
m_slider->setStep(tmpStep);
}
else {
m_slider->setRange(FIXED_MIN, FIXED_MAX);
m_slider->setStep(MIN_FIXED_STEP);
}
m_minChange = m_slider->step()/2;
m_slider->setSuffix(unitDoubleString());
m_slider->setLabelText(i18n(m_optDesc->title));
}
void KSaneOptFSlider::readValue()
{
if (state() == STATE_HIDDEN) return;
// read that current value
QVarLengthArray<unsigned char> data(m_optDesc->size);
SANE_Status status;
SANE_Int res;
status = sane_control_option (m_handle, m_index, SANE_ACTION_GET_VALUE, data.data(), &res);
if (status != SANE_STATUS_GOOD) {
return;
}
m_fVal = SANE_UNFIX(toSANE_Word(data.data()));
if (m_slider != 0) {
if (((m_slider->value() - m_fVal) >= m_minChange) ||
((m_fVal- m_slider->value()) >= m_minChange))
{
m_slider->setValue(m_fVal);
}
}
emit fValueRead(m_fVal);
}
void KSaneOptFSlider::sliderChanged(float val)
{
if (((val-m_fVal) >= m_minChange) || ((m_fVal-val) >= m_minChange)) {
unsigned char data[4];
SANE_Word fixed;
//kDebug() <<m_optDesc->name << fVal << "!=" << val;
m_fVal = val;
fixed = SANE_FIX(val);
fromSANE_Word(data, fixed);
writeData(data);
}
}
bool KSaneOptFSlider::getMinValue(float &val)
{
if (m_optDesc->constraint_type == SANE_CONSTRAINT_RANGE) {
val = SANE_UNFIX(m_optDesc->constraint.range->min);
}
else {
val = FIXED_MIN;
}
return true;
}
bool KSaneOptFSlider::getMaxValue(float &max)
{
if (m_optDesc->constraint_type == SANE_CONSTRAINT_RANGE) {
max = SANE_UNFIX(m_optDesc->constraint.range->max);
}
else {
max = FIXED_MAX;
}
return true;
}
bool KSaneOptFSlider::getValue(float &val)
{
if (state() == STATE_HIDDEN) return false;
val = m_fVal;
return true;
}
bool KSaneOptFSlider::setValue(float val)
{
if (state() == STATE_HIDDEN) return false;
sliderChanged(val);
readValue();
return true;
}
bool KSaneOptFSlider::getValue(QString &val)
{
if (state() == STATE_HIDDEN) return false;
val = QString::number(m_fVal, 'F', 6);
return true;
}
bool KSaneOptFSlider::setValue(const QString &val)
{
if (state() == STATE_HIDDEN) return false;
sliderChanged(val.toFloat());
readValue();
return true;
}
} // NameSpace KSaneIface

View file

@ -0,0 +1,72 @@
/* ============================================================
*
* This file is part of the KDE project
*
* Date : 2009-01-21
* Description : Sane interface for KDE
*
* Copyright (C) 2009 by Kare Sars <kare dot sars at iki dot fi>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================ */
#ifndef KSANE_OPT_FSLIDER_H
#define KSANE_OPT_FSLIDER_H
#include "ksane_option.h"
namespace KSaneIface
{
class LabeledFSlider;
class KSaneOptFSlider : public KSaneOption
{
Q_OBJECT
public:
KSaneOptFSlider(const SANE_Handle handle, const int index);
void createWidget(QWidget *parent);
void readValue();
void readOption();
bool getMinValue(float &max);
bool getMaxValue(float &max);
bool getValue(float &val);
bool setValue(float val);
bool getValue(QString &val);
bool setValue(const QString &val);
bool hasGui() {return true;}
Q_SIGNALS:
void fValueRead(float);
private Q_SLOTS:
void sliderChanged(float val);
private:
LabeledFSlider *m_slider;
float m_fVal;
float m_minChange;
};
} // NameSpace KSaneIface
#endif

View file

@ -0,0 +1,109 @@
/* ============================================================
*
* This file is part of the KDE project
*
* Date : 2009-01-31
* Description : Sane interface for KDE
*
* Copyright (C) 2009 by Kare Sars <kare dot sars at iki dot fi>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================ */
// Local includes
#include "ksane_opt_gamma.h"
#include "ksane_opt_gamma.moc"
#include "labeled_gamma.h"
// Qt includes
#include <QtCore/QVarLengthArray>
// KDE includes
#include <KDebug>
#include <KLocale>
namespace KSaneIface
{
KSaneOptGamma::KSaneOptGamma(const SANE_Handle handle, const int index)
: KSaneOption(handle, index), m_gamma(0)
{
}
void KSaneOptGamma::createWidget(QWidget *parent)
{
if (m_widget) return;
readOption();
if (!m_optDesc) {
kDebug() << "This is a bug";
m_widget = new KSaneOptionWidget(parent, "");
return;
}
m_widget = m_gamma = new LabeledGamma(parent, i18n(m_optDesc->title),
m_optDesc->size/sizeof(SANE_Word));
connect(m_gamma, SIGNAL(gammaTableChanged(QVector<int>)),
this, SLOT(gammaTableChanged(QVector<int>)));
if (strcmp(m_optDesc->name, SANE_NAME_GAMMA_VECTOR_R) == 0) m_gamma->setColor(Qt::red);
if (strcmp(m_optDesc->name, SANE_NAME_GAMMA_VECTOR_G) == 0) m_gamma->setColor(Qt::green);
if (strcmp(m_optDesc->name, SANE_NAME_GAMMA_VECTOR_B) == 0) m_gamma->setColor(Qt::blue);
m_widget->setToolTip(i18n(m_optDesc->desc));
updateVisibility();
readValue();
}
void KSaneOptGamma::gammaTableChanged(const QVector<int> &gam_tbl)
{
QVector<int> copy = gam_tbl;
writeData(copy.data());
}
void KSaneOptGamma::readValue()
{
// Unfortunately gamma table to brigthness, contrast and gamma is
// not easy nor fast.. ergo not done
}
bool KSaneOptGamma::getValue(float &) {return false;}
bool KSaneOptGamma::setValue(float) {return false;}
bool KSaneOptGamma::getValue(QString &val)
{
if (!m_gamma) return false;
if (state() == STATE_HIDDEN) return false;
int bri;
int con;
int gam;
m_gamma->getValues(bri, con, gam);
val = QString().sprintf("%d:%d:%d", bri, con, gam);
return true;
}
bool KSaneOptGamma::setValue(const QString &val)
{
if (!m_gamma) return false;
if (state() == STATE_HIDDEN) return false;
m_gamma->setValues(val);
return true;
}
} // NameSpace KSaneIface

View file

@ -0,0 +1,64 @@
/* ============================================================
*
* This file is part of the KDE project
*
* Date : 2009-01-31
* Description : Sane interface for KDE
*
* Copyright (C) 2009 by Kare Sars <kare dot sars at iki dot fi>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================ */
#ifndef KSANE_OPT_GAMMA_H
#define KSANE_OPT_GAMMA_H
#include "ksane_option.h"
namespace KSaneIface
{
class LabeledGamma;
class KSaneOptGamma : public KSaneOption
{
Q_OBJECT
public:
KSaneOptGamma(const SANE_Handle handle, const int index);
void createWidget(QWidget *parent);
void readValue();
bool getValue(float &val);
bool setValue(float val);
bool getValue(QString &val);
bool setValue(const QString &val);
bool hasGui() {return true;}
private Q_SLOTS:
void gammaTableChanged(const QVector<int> &gam_tbl);
private:
LabeledGamma *m_gamma;
};
} // NameSpace KSaneIface
#endif

View file

@ -0,0 +1,164 @@
/* ============================================================
*
* This file is part of the KDE project
*
* Date : 2009-01-21
* Description : Sane interface for KDE
*
* Copyright (C) 2009 by Kare Sars <kare dot sars at iki dot fi>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================ */
// Local includes
#include "ksane_opt_slider.h"
#include "ksane_opt_slider.moc"
#include "labeled_slider.h"
// Qt includes
#include <QtCore/QVarLengthArray>
// KDE includes
#include <KDebug>
#include <KLocale>
static const int KSW_INT_MAX = 2147483647;
static const int KSW_INT_MIN = -2147483647-1; // prevent warning
namespace KSaneIface
{
KSaneOptSlider::KSaneOptSlider(const SANE_Handle handle, const int index)
: KSaneOption(handle, index), m_slider(0), m_iVal(0)
{
}
void KSaneOptSlider::createWidget(QWidget *parent)
{
if (m_widget) return;
m_widget = m_slider = new LabeledSlider(parent, "", KSW_INT_MIN, KSW_INT_MAX, 1);
readOption();
m_widget->setToolTip(i18n(m_optDesc->desc));
connect(m_slider, SIGNAL(valueChanged(int)), this, SLOT(sliderChanged(int)));
readValue();
}
void KSaneOptSlider::readValue()
{
if (state() == STATE_HIDDEN) return;
// read that current value
QVarLengthArray<unsigned char> data(m_optDesc->size);
SANE_Status status;
SANE_Int res;
status = sane_control_option (m_handle, m_index, SANE_ACTION_GET_VALUE, data.data(), &res);
if (status != SANE_STATUS_GOOD) {
return;
}
m_iVal = toSANE_Word(data.data());
if ((m_slider != 0) && (m_slider->value() != m_iVal)) {
m_slider->setValue(m_iVal);
}
emit fValueRead((float)m_iVal);
}
void KSaneOptSlider::readOption()
{
KSaneOption::readOption();
if (!m_slider) return;
if (m_optDesc->constraint_type == SANE_CONSTRAINT_RANGE) {
m_slider->setRange(m_optDesc->constraint.range->min, m_optDesc->constraint.range->max);
m_slider->setStep(m_optDesc->constraint.range->quant);
}
else {
m_slider->setRange(KSW_INT_MIN, KSW_INT_MAX);
m_slider->setStep(1);
}
m_slider->setSuffix(unitString());
m_slider->setLabelText(i18n(m_optDesc->title));
}
void KSaneOptSlider::sliderChanged(int val)
{
if (val == m_iVal) return;
unsigned char data[4];
m_iVal = val;
fromSANE_Word(data, val);
writeData(data);
}
bool KSaneOptSlider::getMinValue(float &val)
{
if (m_optDesc->constraint_type == SANE_CONSTRAINT_RANGE) {
val = (float)m_optDesc->constraint.range->min;
}
else {
val = (float)KSW_INT_MIN;
}
return true;
}
bool KSaneOptSlider::getMaxValue(float &val)
{
if (m_optDesc->constraint_type == SANE_CONSTRAINT_RANGE) {
val = (float)m_optDesc->constraint.range->max;
}
else {
val = (float)KSW_INT_MAX;
}
return true;
}
bool KSaneOptSlider::getValue(float &val)
{
if (state() == STATE_HIDDEN) return false;
val = (float)m_iVal;
return true;
}
bool KSaneOptSlider::setValue(float val)
{
if (state() == STATE_HIDDEN) return false;
sliderChanged((int)val);
readValue();
return true;
}
bool KSaneOptSlider::getValue(QString &val)
{
if (state() == STATE_HIDDEN) return false;
val = QString::number(m_iVal);
return true;
}
bool KSaneOptSlider::setValue(const QString &val)
{
if (state() == STATE_HIDDEN) return false;
sliderChanged(val.toInt());
readValue();
return true;
}
} // NameSpace KSaneIface

View file

@ -0,0 +1,71 @@
/* ============================================================
*
* This file is part of the KDE project
*
* Date : 2009-01-21
* Description : Sane interface for KDE
*
* Copyright (C) 2009 by Kare Sars <kare dot sars at iki dot fi>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================ */
#ifndef KSANE_OPT_SLIDER_H
#define KSANE_OPT_SLIDER_H
#include "ksane_option.h"
namespace KSaneIface
{
class LabeledSlider;
class KSaneOptSlider : public KSaneOption
{
Q_OBJECT
public:
KSaneOptSlider(const SANE_Handle handle, const int index);
void createWidget(QWidget *parent);
void readValue();
void readOption();
bool getMinValue(float &max);
bool getMaxValue(float &max);
bool getValue(float &val);
bool setValue(float val);
bool getValue(QString &val);
bool setValue(const QString &val);
bool hasGui() {return true;}
Q_SIGNALS:
void fValueRead(float);
private Q_SLOTS:
void sliderChanged(int val);
private:
LabeledSlider *m_slider;
int m_iVal;
};
} // NameSpace KSaneIface
#endif

View file

@ -0,0 +1,343 @@
/* ============================================================
*
* This file is part of the KDE project
*
* Date : 2009-01-21
* Description : Sane interface for KDE
*
* Copyright (C) 2009 by Kare Sars <kare dot sars at iki dot fi>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================ */
// Local includes
#include "ksane_option.h"
#include "ksane_option.moc"
// KDE includes
#include <KDebug>
#include <KLocale>
#include "ksane_option_widget.h"
namespace KSaneIface
{
KSaneOption::KSaneOption(const SANE_Handle handle, const int index)
: QObject(), m_handle(handle), m_index(index)
{
m_widget = 0;
m_data = 0;
readOption();
}
KSaneOption::~KSaneOption()
{
if (m_data) {
free(m_data);
m_data = 0;
}
// delete the frame, just in case if no parent is set
delete m_widget;
m_widget = 0;
}
void KSaneOption::createWidget(QWidget *parent)
{
if (!m_widget) {
m_widget = new KSaneOptionWidget(parent, "");
}
if (m_optDesc) {
m_widget->setToolTip(i18n(m_optDesc->desc));
}
readOption();
readValue();
}
void KSaneOption::readOption()
{
m_optDesc = sane_get_option_descriptor(m_handle, m_index);
updateVisibility();
}
void KSaneOption::updateVisibility()
{
if (!m_widget) return;
if (state() == STATE_HIDDEN) {
m_widget->hide();
}
else {
m_widget->show();
m_widget->setEnabled(state() == STATE_SHOWN);
}
}
KSaneOption::KSaneOptWState KSaneOption::state()
{
if (!m_optDesc) return STATE_HIDDEN;
if (((m_optDesc->cap & SANE_CAP_SOFT_DETECT) == 0) ||
(m_optDesc->cap & SANE_CAP_INACTIVE) ||
((m_optDesc->size == 0) && (optionType(m_optDesc) != TYPE_BUTTON)))
{
return STATE_HIDDEN;
}
else if ((m_optDesc->cap & SANE_CAP_SOFT_SELECT) == 0) {
return STATE_DISABLED;
}
return STATE_SHOWN;
}
bool KSaneOption::needsPolling()
{
if (!m_optDesc) return false;
if ((m_optDesc->cap & SANE_CAP_SOFT_DETECT) && !(m_optDesc->cap & SANE_CAP_SOFT_SELECT)) {
kDebug() << name() << "optDesc->cap =" << m_optDesc->cap;
return true;
}
return false;
}
QString KSaneOption::name()
{
if (m_optDesc == 0) return QString("");
return QString(m_optDesc->name);
}
bool KSaneOption::writeData(void *data)
{
SANE_Status status;
SANE_Int res;
if (state() == STATE_DISABLED) {
return false;
}
status = sane_control_option (m_handle, m_index, SANE_ACTION_SET_VALUE, data, &res);
if (status != SANE_STATUS_GOOD) {
kDebug() << m_optDesc->name << "sane_control_option returned:" << sane_strstatus(status);
// write failed. re read the current setting
readValue();
return false;
}
if ((res & SANE_INFO_INEXACT) && (m_widget != 0)) {
//kDebug() << "write was inexact. Reload value just in case...";
readValue();
}
if (res & SANE_INFO_RELOAD_OPTIONS) {
emit optsNeedReload();
// optReload reloads also the values
}
else if (res & SANE_INFO_RELOAD_PARAMS) {
// 'else if' because with optReload we force also valReload :)
emit valsNeedReload();
}
return true;
}
void KSaneOption::readValue() {}
SANE_Word KSaneOption::toSANE_Word(unsigned char *data)
{
SANE_Word tmp;
// if __BYTE_ORDER is not defined we get #if 0 == 0
#if __BYTE_ORDER == __LITTLE_ENDIAN
tmp = (data[0]&0xff);
tmp += ((SANE_Word)(data[1]&0xff))<<8;
tmp += ((SANE_Word)(data[2]&0xff))<<16;
tmp += ((SANE_Word)(data[3]&0xff))<<24;
#else
tmp = (data[3]&0xff);
tmp += ((SANE_Word)(data[2]&0xff))<<8;
tmp += ((SANE_Word)(data[1]&0xff))<<16;
tmp += ((SANE_Word)(data[0]&0xff))<<24;
#endif
return tmp;
}
void KSaneOption::fromSANE_Word(unsigned char *data, SANE_Word from)
{
// if __BYTE_ORDER is not defined we get #if 0 == 0
#if __BYTE_ORDER == __LITTLE_ENDIAN
data[0] = (from & 0x000000FF);
data[1] = (from & 0x0000FF00)>>8;
data[2] = (from & 0x00FF0000)>>16;
data[3] = (from & 0xFF000000)>>24;
#else
data[3] = (from & 0x000000FF);
data[2] = (from & 0x0000FF00)>>8;
data[1] = (from & 0x00FF0000)>>16;
data[0] = (from & 0xFF000000)>>24;
#endif
}
bool KSaneOption::getMinValue(float &) {return false;}
bool KSaneOption::getMaxValue(float &) {return false;}
bool KSaneOption::getValue(float &) {return false;}
bool KSaneOption::setValue(float) {return false;}
bool KSaneOption::getValue(QString &) {return false;}
bool KSaneOption::setValue(const QString &) {return false;}
int KSaneOption::getUnit() {return m_optDesc->unit;}
bool KSaneOption::storeCurrentData()
{
SANE_Status status;
SANE_Int res;
// check if we can read the value
if (!hasGui()) return false;
if (state() == STATE_HIDDEN) return false;
// read that current value
if (m_data != 0) free(m_data);
m_data = (unsigned char *)malloc(m_optDesc->size);
status = sane_control_option (m_handle, m_index, SANE_ACTION_GET_VALUE, m_data, &res);
if (status != SANE_STATUS_GOOD) {
kDebug() << m_optDesc->name << "sane_control_option returned" << status;
return false;
}
return true;
}
bool KSaneOption::restoreSavedData()
{
// check if we have saved any data
if (m_data == 0) return false;
// check if we can write the value
if (!hasGui()) return false;
if (state() == STATE_HIDDEN) return false;
if (state() == STATE_DISABLED) return false;
writeData(m_data);
readValue();
return true;
}
KSaneOption::KSaneOptType KSaneOption::optionType(const SANE_Option_Descriptor *optDesc)
{
if (!optDesc) return TYPE_DETECT_FAIL;
switch (optDesc->constraint_type) {
case SANE_CONSTRAINT_NONE:
switch(optDesc->type)
{
case SANE_TYPE_BOOL:
return TYPE_CHECKBOX;
case SANE_TYPE_INT:
if (optDesc->size == sizeof(SANE_Word)) return TYPE_SLIDER;
kDebug() << "Can not handle:"<< optDesc->title;
kDebug() << "SANE_CONSTRAINT_NONE && SANE_TYPE_INT";
kDebug() << "size" << optDesc->size<< "!= sizeof(SANE_Word)";
break;
case SANE_TYPE_FIXED:
if (optDesc->size == sizeof(SANE_Word)) return TYPE_F_SLIDER;
kDebug() << "Can not handle:"<< optDesc->title;
kDebug() << "SANE_CONSTRAINT_NONE && SANE_TYPE_FIXED";
kDebug() << "size" << optDesc->size<< "!= sizeof(SANE_Word)";
break;
case SANE_TYPE_BUTTON:
return TYPE_BUTTON;
case SANE_TYPE_STRING:
return TYPE_ENTRY;
case SANE_TYPE_GROUP:
return TYPE_DETECT_FAIL;
}
break;
case SANE_CONSTRAINT_RANGE:
switch(optDesc->type) {
case SANE_TYPE_BOOL:
return TYPE_CHECKBOX;
case SANE_TYPE_INT:
if (optDesc->size == sizeof(SANE_Word)) return TYPE_SLIDER;
if ((strcmp(optDesc->name, SANE_NAME_GAMMA_VECTOR) == 0) ||
(strcmp(optDesc->name, SANE_NAME_GAMMA_VECTOR_R) == 0) ||
(strcmp(optDesc->name, SANE_NAME_GAMMA_VECTOR_G) == 0) ||
(strcmp(optDesc->name, SANE_NAME_GAMMA_VECTOR_B) == 0))
{
return TYPE_GAMMA;
}
kDebug() << "Can not handle:"<< optDesc->title;
kDebug() << "SANE_CONSTRAINT_RANGE && SANE_TYPE_INT && !SANE_NAME_GAMMA_VECTOR...";
kDebug() << "size" << optDesc->size<< "!= sizeof(SANE_Word)";
break;
case SANE_TYPE_FIXED:
if (optDesc->size == sizeof(SANE_Word)) return TYPE_F_SLIDER;
kDebug() << "Can not handle:"<< optDesc->title;
kDebug() << "SANE_CONSTRAINT_RANGE && SANE_TYPE_FIXED";
kDebug() << "size" << optDesc->size<< "!= sizeof(SANE_Word)";
kDebug() << "Analog Gamma vector?";
break;
case SANE_TYPE_STRING:
kDebug() << "Can not handle:" << optDesc->title;
kDebug() << "SANE_CONSTRAINT_RANGE && SANE_TYPE_STRING";
return TYPE_DETECT_FAIL;
case SANE_TYPE_BUTTON:
return TYPE_BUTTON;
case SANE_TYPE_GROUP:
return TYPE_DETECT_FAIL;
}
break;
case SANE_CONSTRAINT_WORD_LIST:
case SANE_CONSTRAINT_STRING_LIST:
return TYPE_COMBO;
}
return TYPE_DETECT_FAIL;
}
KLocalizedString KSaneOption::unitString()
{
switch(m_optDesc->unit)
{
case SANE_UNIT_NONE: return KLocalizedString();
case SANE_UNIT_PIXEL: return ki18ncp("SpinBox parameter unit", " Pixel", " Pixels");
case SANE_UNIT_BIT: return ki18ncp("SpinBox parameter unit", " Bit", " Bits");
case SANE_UNIT_MM: return ki18nc("SpinBox parameter unit (Millimeter)", " mm");
case SANE_UNIT_DPI: return ki18nc("SpinBox parameter unit (Dots Per Inch)", " DPI");
case SANE_UNIT_PERCENT: return ki18nc("SpinBox parameter unit (Percentage)", " %");
case SANE_UNIT_MICROSECOND: return ki18nc("SpinBox parameter unit (Microseconds)", " µs");
}
return KLocalizedString();
}
QString KSaneOption::unitDoubleString()
{
switch(m_optDesc->unit)
{
case SANE_UNIT_NONE: return QString("");
case SANE_UNIT_PIXEL: return i18nc("Double numbers. SpinBox parameter unit", " Pixels");
case SANE_UNIT_BIT: return i18nc("Double numbers. SpinBox parameter unit", " Bits");
case SANE_UNIT_MM: return i18nc("Double numbers. SpinBox parameter unit (Millimeter)", " mm");
case SANE_UNIT_DPI: return i18nc("Double numbers. SpinBox parameter unit (Dots Per Inch)", " DPI");
case SANE_UNIT_PERCENT: return i18nc("Double numbers. SpinBox parameter unit (Percentage)", " %");
case SANE_UNIT_MICROSECOND: return i18nc("Double numbers. SpinBox parameter unit (Microseconds)", " µs");
}
return QString("");
}
} // NameSpace KSaneIface

View file

@ -0,0 +1,122 @@
/* ============================================================
*
* This file is part of the KDE project
*
* Date : 2009-01-21
* Description : Sane interface for KDE
*
* Copyright (C) 2009 by Kare Sars <kare dot sars at iki dot fi>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================ */
#ifndef KSANE_OPTION_H
#define KSANE_OPTION_H
// Qt includes
#include <QFrame>
//KDE includes
#include <KLocalizedString>
// Sane includes
extern "C"
{
#include <sane/sane.h>
#include <sane/saneopts.h>
}
namespace KSaneIface
{
class KSaneOptionWidget;
class KSaneOption : public QObject
{
Q_OBJECT
public:
typedef enum
{
TYPE_DETECT_FAIL,
TYPE_CHECKBOX,
TYPE_SLIDER,
TYPE_F_SLIDER,
TYPE_COMBO,
TYPE_ENTRY,
TYPE_GAMMA,
TYPE_BUTTON
} KSaneOptType;
typedef enum
{
STATE_HIDDEN,
STATE_DISABLED,
STATE_SHOWN
} KSaneOptWState;
KSaneOption(const SANE_Handle handle, const int index);
~KSaneOption();
static KSaneOptType optionType(const SANE_Option_Descriptor *optDesc);
KSaneOptionWidget *widget() {return m_widget;}
virtual bool hasGui() {return false;}
bool needsPolling();
KSaneOptWState state();
QString name();
virtual void createWidget(QWidget *parent);
virtual void readOption();
virtual void readValue();
virtual bool getMinValue(float &max);
virtual bool getMaxValue(float &max);
virtual bool getValue(float &val);
virtual bool setValue(float val);
virtual bool getValue(QString &val);
virtual bool setValue(const QString &val);
virtual int getUnit();
bool storeCurrentData();
bool restoreSavedData();
Q_SIGNALS:
void optsNeedReload();
void valsNeedReload();
protected:
SANE_Word toSANE_Word(unsigned char *data);
void fromSANE_Word(unsigned char *data, SANE_Word from);
bool writeData(void *data);
KLocalizedString unitString();
QString unitDoubleString();
void updateVisibility();
SANE_Handle m_handle;
int m_index;
const SANE_Option_Descriptor *m_optDesc; ///< This pointer is provided by sane
unsigned char *m_data;
KSaneOptionWidget *m_widget;
};
} // NameSpace KSaneIface
#endif // KSANE_OPTION_H

View file

@ -0,0 +1,262 @@
/* ============================================================
*
* This file is part of the KDE project
*
* Date : 2008-11-15
* Description :Selection QGraphicsItem for the image viewer.
*
* Copyright (C) 2008 by Kare Sars <kare dot sars at iki dot fi>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================ */
#include "selectionitem.h"
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QCursor>
#include <QList>
namespace KSaneIface
{
static const qreal selMargin = 4.0;
static const QPointF boundMargin(selMargin,selMargin);
static const qreal addRemMargin = 8.0;
static const QPointF addRemMarginPoint(addRemMargin, addRemMargin);
struct SelectionItem::Private
{
QPen penDark;
QPen penLight;
QPen penAddRemFg;
QRectF rect;
qreal maxX;
qreal maxY;
bool hasMaxX;
bool hasMaxY;
bool hasMax;
bool isSaved;
bool showAddRem;
qreal invZoom;
qreal selMargin;
QRectF addRemRect;
};
SelectionItem::SelectionItem(QRectF rect) : QGraphicsItem(), d(new Private)
{
d->hasMaxX = false;
d->hasMaxY = false;
d->hasMax = false;
setRect(rect);
d->penDark.setColor(Qt::black);
d->penDark.setStyle(Qt::SolidLine);
d->penLight.setColor(Qt::white);
d->penLight.setStyle(Qt::DashLine);
// FIXME We should probably use some standard KDE color here and not hard code it
d->penAddRemFg.setColor(Qt::darkGreen);
d->penAddRemFg.setStyle(Qt::SolidLine);
d->penAddRemFg.setWidth(3);
d->isSaved = false;
d->showAddRem = false;
d->invZoom = 1;
d->selMargin = selMargin;
d->addRemRect = QRectF(0,0,0,0);
}
SelectionItem::~SelectionItem()
{
delete d;
}
void SelectionItem::saveZoom(qreal zoom)
{
if (zoom < 0.00001) zoom = 0.00001;
d->invZoom = 1/zoom;
d->selMargin = selMargin * d->invZoom;
qreal margin = addRemMargin * d->invZoom;
QPointF pMargin = addRemMarginPoint * d->invZoom;
d->addRemRect = QRectF(d->rect.center()-pMargin, QSizeF(margin*2.0, margin*2.0));
d->penAddRemFg.setWidthF(3.0 * d->invZoom);
}
void SelectionItem::setSaved(bool isSaved)
{
if (isSaved) {
d->penDark.setColor(Qt::darkBlue);
d->penLight.setColor(Qt::red);
d->penAddRemFg.setColor(Qt::darkRed);
d->isSaved = true;
}
else {
d->penDark.setColor(Qt::black);
d->penLight.setColor(Qt::white);
d->penAddRemFg.setColor(Qt::darkGreen);
d->isSaved = false;
}
}
void SelectionItem::setMaxRight(qreal maxX)
{
d->maxX = maxX;
d->hasMaxX = true;
if (d->hasMaxY) d->hasMax = true;
}
void SelectionItem::setMaxBottom(qreal maxY)
{
d->maxY = maxY;
d->hasMaxY = true;
if (d->hasMaxX) d->hasMax = true;
}
SelectionItem::Intersects SelectionItem::intersects(QPointF point)
{
bool oldState = d->showAddRem;
d->showAddRem = false;
if ((point.x() < (d->rect.left()-d->selMargin)) ||
(point.x() > (d->rect.right()+d->selMargin)) ||
(point.y() < (d->rect.top()-d->selMargin)) ||
(point.y() > (d->rect.bottom()+d->selMargin)))
{
if (oldState != d->showAddRem) update();
return None;
}
if (point.x() < (d->rect.left()+d->selMargin)) {
if (oldState != d->showAddRem) update();
if (point.y() < (d->rect.top()+d->selMargin)) return TopLeft;
if (point.y() > (d->rect.bottom()-d->selMargin)) return BottomLeft;
return Left;
}
if (point.x() > (d->rect.right()-d->selMargin)) {
if (oldState != d->showAddRem) update();
if (point.y() < (d->rect.top()+d->selMargin)) return TopRight;
if (point.y() > (d->rect.bottom()-d->selMargin)) return BottomRight;
return Right;
}
if (point.y() < (d->rect.top()+d->selMargin)) {
if (oldState != d->showAddRem) update();
return Top;
}
if (point.y() > (d->rect.bottom()-d->selMargin)) {
if (oldState != d->showAddRem) update();
return Bottom;
}
d->showAddRem = true;
if (oldState != d->showAddRem) update();
if ((point.x() > d->addRemRect.left()) &&
(point.x() < d->addRemRect.right()) &&
(point.y() > d->addRemRect.top()) &&
(point.y() < d->addRemRect.bottom()))
{
return AddRemove;
}
return Move;
}
void SelectionItem::setRect(QRectF rect)
{
prepareGeometryChange();
d->rect = rect;
d->rect = d->rect.normalized();
if (d->hasMax) {
if (d->rect.top() < 0) d->rect.setTop(0);
if (d->rect.left() < 0) d->rect.setLeft(0);
if (d->rect.right() > d->maxX) d->rect.setRight(d->maxX);
if (d->rect.bottom() > d->maxY) d->rect.setBottom(d->maxY);
}
// calculate the add/remove rectangle
qreal margin = addRemMargin * d->invZoom;
QPointF pMargin = addRemMarginPoint * d->invZoom;
d->addRemRect = QRectF(d->rect.center()-pMargin, QSizeF(margin*2, margin*2));
}
QPointF SelectionItem::fixTranslation(QPointF dp)
{
if ((d->rect.left() + dp.x()) < 0) dp.setX(-d->rect.left());
if ((d->rect.top() + dp.y()) < 0) dp.setY(-d->rect.top());
if ((d->rect.right() + dp.x()) > d->maxX) dp.setX(d->maxX - d->rect.right());
if ((d->rect.bottom() + dp.y()) > d->maxY) dp.setY(d->maxY - d->rect.bottom());
return dp;
}
QRectF SelectionItem::rect()
{
return d->rect;
}
QRectF SelectionItem::boundingRect() const
{
QRectF tmp(d->rect.topLeft()-boundMargin, d->rect.bottomRight()+boundMargin);
if (tmp.top() > d->addRemRect.top()) {
tmp.setTop(d->addRemRect.top());
}
if (tmp.left() > d->addRemRect.left()) {
tmp.setLeft(d->addRemRect.left());
}
if (tmp.bottom() < d->addRemRect.bottom()) {
tmp.setBottom(d->addRemRect.bottom());
}
if (tmp.right() < d->addRemRect.right()) {
tmp.setRight(d->addRemRect.right());
}
return tmp;
}
void SelectionItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
{
painter->setPen(d->penDark);
painter->drawRect(d->rect);
painter->setPen(d->penLight);
painter->drawRect(d->rect);
if (d->showAddRem) {
painter->fillRect(d->addRemRect, QBrush(Qt::white));
QLineF minus(d->addRemRect.left()+3*d->invZoom, d->rect.center().y(),
d->addRemRect.right()-3*d->invZoom, d->rect.center().y());
painter->setPen(d->penAddRemFg);
painter->drawLine(minus);
if (!d->isSaved) {
QLineF plus(d->rect.center().x(), d->addRemRect.top()+3*d->invZoom,
d->rect.center().x(), d->addRemRect.bottom()-3*d->invZoom);
painter->drawLine(plus);
}
}
}
} // NameSpace KSaneIface

View file

@ -0,0 +1,82 @@
/* ============================================================
*
* This file is part of the KDE project
*
* Date : 2008-11-15
* Description :Selection QGraphicsItem for the image viewer.
*
* Copyright (C) 2008 by Kare Sars <kare dot sars at iki dot fi>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================ */
#ifndef SELECTIONITEM_H
#define SELECTIONITEM_H
#include <QGraphicsPixmapItem>
#include <QPainter>
namespace KSaneIface
{
class SelectionItem : public QGraphicsItem
{
public:
typedef enum
{
None,
Top,
TopRight,
Right,
BottomRight,
Bottom,
BottomLeft,
Left,
TopLeft,
Move,
AddRemove
} Intersects;
explicit SelectionItem(QRectF rect);
~SelectionItem();
void setMaxRight(qreal maxRight);
void setMaxBottom(qreal maxBottom);
void setSaved(bool isSaved);
Intersects intersects(QPointF point);
void saveZoom(qreal zoom);
void setRect(QRectF rect);
QPointF fixTranslation(QPointF dp);
QRectF rect();
public:
// Graphics Item methods
QRectF boundingRect() const;
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
private:
struct Private;
Private * const d;
};
} // NameSpace KSaneIface
#endif

View file

@ -0,0 +1,307 @@
// vim: set tabstop=4 shiftwidth=4 noexpandtab:
/*
Gwenview: an image viewer
Copyright 2009 Aurélien Gâteau <agateau@kde.org>
Copyright 2009 Kåre Sårs <kare.sars@iki.fi>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) version 3, or any
later version accepted by the membership of KDE e.V. (or its
successor approved by the membership of KDE e.V.), which shall
act as a proxy defined in Section 6 of version 3 of the license.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// Self
#include "splittercollapser.moc"
// Qt
#include <QApplication>
#include <QEvent>
#include <QMouseEvent>
#include <QSplitter>
#include <QStyleOptionToolButton>
#include <QStylePainter>
#include <QTimeLine>
// KDE
#include <kdebug.h>
// Local
namespace KSaneIface {
enum Direction {
LTR = 1 << 0,
RTL = 1 << 1,
Vertical = 1 << 2,
TTB = Vertical + (1 << 0),
BTT = Vertical + (1 << 1)
};
const int TIMELINE_DURATION = 500;
const qreal MINIMUM_OPACITY = 0.3;
struct ArrowTypes {
ArrowTypes()
: visible(Qt::NoArrow), notVisible(Qt::NoArrow){}
ArrowTypes(Qt::ArrowType t1, Qt::ArrowType t2)
: visible(t1), notVisible(t2) {}
Qt::ArrowType visible,
notVisible;
Qt::ArrowType get(bool isVisible) {
return isVisible ? visible : notVisible;
}
};
struct SplitterCollapserPrivate {
SplitterCollapser* q;
QSplitter* mSplitter;
QWidget* mWidget;
Direction mDirection;
QTimeLine* mOpacityTimeLine;
int mSizeAtCollaps;
bool isVertical() const {
return mDirection & Vertical;
}
bool isVisible() const {
bool isVisible = mWidget->isVisible();
QRect widgetRect = mWidget->geometry();
if (isVisible) {
QPoint br = widgetRect.bottomRight();
if ((br.x() <= 0) || (br.y() <=0)) {
isVisible = false;
}
}
return isVisible;
}
void updatePosition() {
int x, y;
QRect widgetRect = mWidget->geometry();
int splitterWidth = mSplitter->width();
int handleWidth = mSplitter->handleWidth();
int width = q->width();
if (!isVertical()) {
// FIXME: Make this configurable
y = 30;
if (mDirection == LTR) {
if (isVisible()) {
x = widgetRect.right() + handleWidth;
} else {
x = 0;
}
} else { // RTL
if (isVisible()) {
x = widgetRect.left() - handleWidth - width;
} else {
x = splitterWidth - handleWidth - width;
}
}
} else {
// FIXME
x = 0;
y = 0;
}
q->move(x, y);
}
void updateArrow() {
static QMap<Direction, ArrowTypes> arrowForDirection;
if (arrowForDirection.isEmpty()) {
arrowForDirection[LTR] = ArrowTypes(Qt::LeftArrow, Qt::RightArrow);
arrowForDirection[RTL] = ArrowTypes(Qt::RightArrow, Qt::LeftArrow);
arrowForDirection[TTB] = ArrowTypes(Qt::UpArrow, Qt::DownArrow);
arrowForDirection[BTT] = ArrowTypes(Qt::DownArrow, Qt::UpArrow);
}
q->setArrowType(arrowForDirection[mDirection].get(isVisible()));
}
void widgetEventFilter(QEvent* event) {
switch (event->type()) {
case QEvent::Resize:
updatePosition();
updateOpacity();
break;
case QEvent::Move:
case QEvent::Show:
case QEvent::Hide:
updatePosition();
updateOpacity();
updateArrow();
break;
default:
break;
}
}
void updateOpacity() {
QPoint pos = q->parentWidget()->mapFromGlobal(QCursor::pos());
QRect opaqueRect = q->geometry();
bool opaqueCollapser = opaqueRect.contains(pos);
int frame = mOpacityTimeLine->currentFrame();
if (opaqueCollapser && frame == mOpacityTimeLine->startFrame()) {
mOpacityTimeLine->setDirection(QTimeLine::Forward);
startTimeLine();
} else if (!opaqueCollapser && frame == mOpacityTimeLine->endFrame()) {
mOpacityTimeLine->setDirection(QTimeLine::Backward);
startTimeLine();
}
}
void startTimeLine() {
if (mOpacityTimeLine->state() != QTimeLine::Running) {
mOpacityTimeLine->start();
}
}
};
SplitterCollapser::SplitterCollapser(QSplitter* splitter, QWidget* widget)
: QToolButton(),
d(new SplitterCollapserPrivate)
{
d->q = this;
// We do not want our collapser to be added as a regular widget in the
// splitter!
setAttribute(Qt::WA_NoChildEventsForParent);
d->mOpacityTimeLine = new QTimeLine(TIMELINE_DURATION, this);
d->mOpacityTimeLine->setFrameRange(int(MINIMUM_OPACITY * 1000), 1000);
connect(d->mOpacityTimeLine, SIGNAL(valueChanged(qreal)), SLOT(update()));
d->mWidget = widget;
d->mWidget->installEventFilter(this);
qApp->installEventFilter(this);
d->mSplitter = splitter;
setParent(d->mSplitter);
if (splitter->indexOf(widget) < splitter->count() / 2) {
d->mDirection = LTR;
} else {
d->mDirection = RTL;
}
if (splitter->orientation() == Qt::Vertical) {
// FIXME: Ugly!
d->mDirection = static_cast<Direction>(int(d->mDirection) + int(TTB));
}
connect(this, SIGNAL(clicked()), SLOT(slotClicked()));
show();
}
SplitterCollapser::~SplitterCollapser() {
delete d;
}
bool SplitterCollapser::eventFilter(QObject* object, QEvent* event) {
if (object == d->mWidget) {
d->widgetEventFilter(event);
} else { /* app */
if (event->type() == QEvent::MouseMove) {
d->updateOpacity();
}
}
return false;
}
QSize SplitterCollapser::sizeHint() const {
int extent = style()->pixelMetric(QStyle::PM_ScrollBarExtent);
QSize sh(extent * 3 / 4, extent * 240 / 100);
if (d->isVertical()) {
sh.transpose();
}
return sh;
}
void SplitterCollapser::slotClicked() {
QList<int> sizes = d->mSplitter->sizes();
int index = d->mSplitter->indexOf(d->mWidget);
if (d->isVisible()) {
d->mSizeAtCollaps = sizes[index];
sizes[index] = 0;
}
else {
if (d->mSizeAtCollaps != 0) {
sizes[index] = d->mSizeAtCollaps;
}
else {
if (d->isVertical()) {
sizes[index] = d->mWidget->sizeHint().height();
}
else {
sizes[index] = d->mWidget->sizeHint().width();
}
}
}
d->mSplitter->setSizes(sizes);
}
void SplitterCollapser::slotCollapse() {
if (d->isVisible()) slotClicked();
// else do nothing
}
void SplitterCollapser::slotRestore() {
if (!d->isVisible()) slotClicked();
// else do nothing
}
void SplitterCollapser::slotSetCollapsed(bool collapse) {
if (collapse == d->isVisible()) slotClicked();
// else do nothing
}
void SplitterCollapser::paintEvent(QPaintEvent*) {
QStylePainter painter(this);
qreal opacity = d->mOpacityTimeLine->currentFrame() / 1000.;
painter.setOpacity(opacity);
QStyleOptionToolButton opt;
initStyleOption(&opt);
if (d->mDirection == LTR) {
opt.rect.setLeft(-width());
} else {
opt.rect.setWidth(width() * 2);
}
painter.drawPrimitive(QStyle::PE_PanelButtonTool, opt);
QStyleOptionToolButton opt2;
initStyleOption(&opt2);
painter.drawControl(QStyle::CE_ToolButtonLabel, opt2);
}
} // namespace

View file

@ -0,0 +1,69 @@
// vim: set tabstop=4 shiftwidth=4 noexpandtab:
/*
Gwenview: an image viewer
Copyright 2009 Aurélien Gâteau <agateau@kde.org>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) version 3, or any
later version accepted by the membership of KDE e.V. (or its
successor approved by the membership of KDE e.V.), which shall
act as a proxy defined in Section 6 of version 3 of the license.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef SPLITTERCOLLAPSER_H
#define SPLITTERCOLLAPSER_H
// Qt
#include <QToolButton>
// KDE
class QSplitter;
namespace KSaneIface {
struct SplitterCollapserPrivate;
/**
* A button which appears on the side of a splitter handle and allows easy
* collapsing of the widget on the opposite side
*/
class SplitterCollapser : public QToolButton {
Q_OBJECT
public:
SplitterCollapser(QSplitter*, QWidget* widget);
~SplitterCollapser();
virtual QSize sizeHint() const;
public Q_SLOTS:
void slotCollapse();
void slotRestore();
void slotSetCollapsed(bool collapsed);
protected:
virtual bool eventFilter(QObject*, QEvent*);
virtual void paintEvent(QPaintEvent*);
private:
SplitterCollapserPrivate* const d;
private Q_SLOTS:
void slotClicked();
};
} // namespace
#endif /* SPLITTERCOLLAPSER_H */

View file

@ -0,0 +1,30 @@
/* ============================================================
*
* This file is a part of kipi-plugins project
* http://www.digikam.org
*
* Date : 2007-02-12
* Description : Sane interface for KDE
*
* Copyright (C) 2007 by Gilles Caulier <caulier dot gilles at gmail dot com>
*
* This program is free software; you can redistribute it
* and/or modify it under the terms of the GNU General
* Public License as published by the Free Software Foundation;
* either version 2, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* ============================================================ */
#ifndef KSANE_VERSION_H
#define KSANE_VERSION_H
static const char ksane_version[] = "${KSANE_LIB_VERSION_STRING}";
#define KSANE_VERSION ${KSANE_LIB_VERSION_ID}
#endif // KSANE_VERSION_H

View file

@ -0,0 +1,90 @@
/* ============================================================
*
* This file is part of the KDE project
*
* Date : 2007-09-13
* Description : Sane interface for KDE
*
* Copyright (C) 2007-2008 by Kare Sars <kare.sars@iki .fi>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================ */
// Local includes
#include "gamma_disp.h"
#include "gamma_disp.moc"
// Qt includes
#include <QPainter>
namespace KSaneIface
{
GammaDisp::GammaDisp(QWidget *parent, QVector<int> *tbl)
: QWidget(parent)
{
gam_tbl = tbl;
gam_color.setRgb(0,0,0);
}
QSize GammaDisp::minimumSizeHint() const
{
return QSize(75, 75);
}
QSize GammaDisp::sizeHint() const
{
return QSize(75, 75);
}
void GammaDisp::setColor(const QColor &color)
{
gam_color = color;
}
void GammaDisp::resizeEvent (QResizeEvent*)
{
repaint();
}
void GammaDisp::paintEvent(QPaintEvent *)
{
/* QMemArray<QRect> rects = event->region().rects();
for (int i = 0; i < (int)rects.size(); i++) {
bitBlt(this, rects[i].topLeft(), &pixmap, rects[i]);
}*/
QPointF p1, p2;
QPainter painter(this);
painter.fillRect(rect(), QBrush(Qt::white));
double xscale = (double)(size().width()-1) / (double)gam_tbl->size();
double yscale = (double)(size().height()-1) / (double)gam_tbl->size();
painter.setPen(gam_color);
for (int i=0; i<gam_tbl->size()-1; i++) {
p1.setX(i*xscale);
p1.setY(size().height()- 1 - (gam_tbl->at(i) * yscale));
p2.setX((i+1)*xscale);
p2.setY(size().height()- 1 - (gam_tbl->at(i+1) * yscale));
painter.drawLine(p1, p2);
}
}
} // NameSpace KSaneIface

View file

@ -0,0 +1,76 @@
/* ============================================================
*
* This file is part of the KDE project
*
* Date : 2007-09-13
* Description : Sane interface for KDE
*
* Copyright (C) 2007-2008 by Kare Sars <kare.sars@iki .fi>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================ */
#ifndef GAMMA_DISP_H
#define GAMMA_DISP_H
// Qt includes
#include <QWidget>
/**
*@author Kåre Särs
*
* This is the widget that displays the gamma table.
*/
namespace KSaneIface
{
class GammaDisp : public QWidget
{
Q_OBJECT
public:
/**
* Create a gamma display.
* \param parent parent widget
*/
GammaDisp(QWidget *parent, QVector<int> *tbl);
~GammaDisp() {};
QSize sizeHint() const;
QSize minimumSizeHint() const;
void setColor(const QColor &color);
protected:
void paintEvent (QPaintEvent *);
void resizeEvent(QResizeEvent *);
private:
QVector<int> *gam_tbl;
QColor gam_color;
};
} // NameSpace KSaneIface
#endif // GAMMA_DISP_H

View file

@ -0,0 +1,51 @@
/* ============================================================
*
* This file is part of the KDE project
*
* Copyright (C) 2008-2011 by Kare Sars <kare.sars@iki.fi>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================ */
// Local includes
#include "ksane_button.h"
#include "ksane_button.moc"
// Qt includes
#include <KDebug>
namespace KSaneIface
{
KSaneButton::KSaneButton(QWidget *parent, const QString& ltext)
: KSaneOptionWidget(parent, QString())
{
m_button = new QPushButton(ltext, this);
m_layout->addWidget(m_button, 0, 1);
m_layout->addWidget(new QWidget(this), 0, 2);
m_layout->setColumnStretch(1, 0);
m_layout->setColumnStretch(2, 50);
connect(m_button, SIGNAL(clicked(bool)), this, SIGNAL(clicked()));
}
KSaneButton::~KSaneButton()
{
}
} // NameSpace KSaneIface

View file

@ -0,0 +1,67 @@
/* ============================================================
*
* This file is part of the KDE project
*
* Copyright (C) 2008-2011 by Kare Sars <kare.sars@iki .fi>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================ */
#ifndef KSANE_BUTTON_H
#define KSANE_BUTTON_H
#include "ksane_option_widget.h"
// Qt includes
#include <QPushButton>
#include <QGridLayout>
namespace KSaneIface
{
/**
*@author Kåre Särs
*/
/**
* A wrapper for a checkbox
*/
class KSaneButton : public KSaneOptionWidget
{
Q_OBJECT
public:
/**
* Create the checkbox.
*
* \param parent parent widget
* \param text is the text describing the checkbox.
*/
KSaneButton(QWidget *parent, const QString& text);
~KSaneButton();
Q_SIGNALS:
void clicked();
private:
QPushButton *m_button;
};
} // NameSpace KSaneIface
#endif // KSANE_BUTTON_H

View file

@ -0,0 +1,74 @@
/* ============================================================
*
* This file is part of the KDE project
*
* Description : Base class for option widgets
*
* Copyright (C) 2011 by Kare Sars <kare.sars@iki.fi>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================ */
// Local includes
#include "ksane_option_widget.h"
#include "ksane_option_widget.moc"
// Qt includes
#include <KDebug>
#include <KLocale>
namespace KSaneIface
{
KSaneOptionWidget::KSaneOptionWidget(QWidget *parent, const QString& labelText)
: QWidget(parent)
{
m_label = new QLabel;
setLabelText(labelText);
m_layout = new QGridLayout(this);
m_layout->addWidget(m_label, 0, 0, Qt::AlignRight);
m_layout->setColumnStretch(0, 0);
m_layout->setContentsMargins(0,0,0,0);
}
KSaneOptionWidget::~KSaneOptionWidget()
{
}
void KSaneOptionWidget::setLabelText(const QString &text)
{
if (text.isEmpty()) {
m_label->setText(QString());
} else {
m_label->setText(i18nc("Label for a scanner option", "%1:", text));
}
}
int KSaneOptionWidget::labelWidthHint()
{
return m_label->sizeHint().width();
}
void KSaneOptionWidget::setLabelWidth(int labelWidth)
{
m_layout->setColumnMinimumWidth(0, labelWidth);
}
} // NameSpace KSaneIface

View file

@ -0,0 +1,70 @@
/* ============================================================
*
* This file is part of the KDE project
*
* Description : Base class for option widgets
*
* Copyright (C) 2011 by Kare Sars <kare.sars@iki.fi>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================ */
#ifndef KSANE_OPTION_WIDGET_H
#define KSANE_OPTION_WIDGET_H
// Qt includes
#include <QWidget>
#include <QLabel>
#include <QGridLayout>
namespace KSaneIface
{
/**
*@author Kåre Särs
*/
/**
* A wrapper for a checkbox
*/
class KSaneOptionWidget : public QWidget
{
Q_OBJECT
public:
/**
* Create the Wodget.
* \param parent parent widget
* \param Label text.
*/
KSaneOptionWidget(QWidget *parent, const QString &labelText);
~KSaneOptionWidget();
void setLabelText(const QString &text);
int labelWidthHint();
void setLabelWidth(int labelWidth);
protected:
QLabel *m_label;
QGridLayout *m_layout;
};
} // NameSpace KSaneIface
#endif // KSANE_OPTION_WIDGET_H

View file

@ -0,0 +1,62 @@
/* ============================================================
*
* This file is part of the KDE project
*
* Date : 2007-09-13
* Description : Sane interface for KDE
*
* Copyright (C) 2007-2011 by Kare Sars <kare.sars@iki .fi>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================ */
// Local includes
#include "labeled_checkbox.h"
#include "labeled_checkbox.moc"
// Qt includes
#include <KDebug>
namespace KSaneIface
{
LabeledCheckbox::LabeledCheckbox(QWidget *parent, const QString& ltext)
: KSaneOptionWidget(parent, QString())
{
chbx = new QCheckBox(ltext, this);
m_layout->addWidget(chbx, 0, 1);
m_layout->setColumnStretch(1, 50);
connect(chbx, SIGNAL(toggled(bool)), this, SIGNAL(toggled(bool)));
}
LabeledCheckbox::~LabeledCheckbox()
{
}
void LabeledCheckbox::setChecked(bool is_checked)
{
if (is_checked != chbx->isChecked()) chbx->setChecked(is_checked);
}
bool LabeledCheckbox::isChecked()
{
return chbx->isChecked();
}
} // NameSpace KSaneIface

View file

@ -0,0 +1,74 @@
/* ============================================================
*
* This file is part of the KDE project
*
* Date : 2007-09-13
* Description : Sane interface for KDE
*
* Copyright (C) 2007-2011 by Kare Sars <kare.sars@iki .fi>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================ */
#ifndef LABELED_CHECKBOX_H
#define LABELED_CHECKBOX_H
#include "ksane_option_widget.h"
// Qt includes
#include <QCheckBox>
#include <QGridLayout>
namespace KSaneIface
{
/**
*@author Kåre Särs
*/
/**
* A wrapper for a checkbox
*/
class LabeledCheckbox : public KSaneOptionWidget
{
Q_OBJECT
public:
/**
* Create the checkbox.
*
* \param parent parent widget
* \param text is the text describing the checkbox.
*/
LabeledCheckbox(QWidget *parent, const QString& text);
~LabeledCheckbox();
void setChecked(bool);
bool isChecked();
Q_SIGNALS:
void toggled(bool);
private:
QCheckBox *chbx;
};
} // NameSpace KSaneIface
#endif // LABELED_CHECKBOX_H

View file

@ -0,0 +1,101 @@
/* ============================================================
*
* This file is part of the KDE project
*
* Date : 2007-09-13
* Description : Sane interface for KDE
*
* Copyright (C) 2007-2011 by Kare Sars <kare.sars@iki .fi>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================ */
#include "labeled_combo.h"
#include "labeled_combo.moc"
// Qt includes
#include <QLabel>
// KDE includes
#include <KComboBox>
#include <KDebug>
namespace KSaneIface
{
LabeledCombo::LabeledCombo(QWidget *parent, const QString& ltext, const QStringList& list)
: KSaneOptionWidget(parent, ltext)
{
m_combo = new KComboBox(this);
m_combo->addItems(list);
m_label->setBuddy(m_combo);
connect(m_combo, SIGNAL(activated(int)), this, SIGNAL(activated(int)));
m_layout->addWidget(m_combo, 0, 1);
m_layout->addWidget(new QWidget(this), 0, 2);
m_layout->setColumnStretch(1, 0);
m_layout->setColumnStretch(2, 50);
setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Fixed);
}
void LabeledCombo::addItems(const QStringList &list)
{
m_combo->addItems(list);
QString tmp;
for (int i=0; i<m_combo->count(); i++) {
tmp = m_combo->itemText(i);
m_combo->setItemData(i, tmp, Qt::ToolTipRole);
}
}
void LabeledCombo::setCurrentText(const QString &t)
{
int i;
for (i=0; i<m_combo->count(); i++) {
if (m_combo->itemText(i) == t) {
m_combo->setCurrentIndex(i);
}
}
}
QString LabeledCombo::currentText()
{
return m_combo->currentText();
}
bool LabeledCombo::setIcon(const QIcon &icon, const QString& str)
{
for (int i=0; i < m_combo->count(); i++) {
if (m_combo->itemText(i) == str) {
m_combo->setItemIcon(i, icon);
return true;
}
}
return false;
}
void LabeledCombo::setCurrentIndex(int i)
{
m_combo->setCurrentIndex(i);
}
} // NameSpace KSaneIface

View file

@ -0,0 +1,100 @@
/* ============================================================
*
* This file is part of the KDE project
*
* Description : Sane interface for KDE
*
* Copyright (C) 2007-2011 by Kare Sars <kare.sars@iki .fi>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================ */
#ifndef LABELED_COMBO_H
#define LABELED_COMBO_H
#include "ksane_option_widget.h"
// KDE includes
#include <KComboBox>
namespace KSaneIface
{
/**
* A label and a combobox.
*/
class LabeledCombo : public KSaneOptionWidget
{
Q_OBJECT
public:
/**
* create a label and combobox combination.
* \param parent parent widget
* \param label is the lext for the label
* \param list a stringlist with values the list should contain.
*/
LabeledCombo(QWidget *parent, const QString& label, const QStringList& list);
public Q_SLOTS:
/**
* Add string entries to the combobox
*/
void addItems(const QStringList &list);
/**
* Remove all string entries
*/
void clear() { m_combo->clear(); }
/**
* If the given string can be found in the comobox, activate that entry.
* If not, the entry is not changed.
*/
void setCurrentText(const QString &);
/**
* This function is used to read the current string of the combobox
*/
QString currentText();
/**
* set the current item of the combobox.
*/
void setCurrentIndex(int);
/**
* add an icon for a string in the combobox
* @param icon the icon to set.
* @param str the string for which the pixmap should be set.
*/
bool setIcon(const QIcon& icon, const QString& str);
Q_SIGNALS:
void activated(int);
private:
KComboBox *m_combo;
};
} // NameSpace KSaneIface
#endif // LABELED_COMBO_H

View file

@ -0,0 +1,81 @@
/* ============================================================
*
* This file is part of the KDE project
*
* Date : 2007-09-13
* Description : Sane interface for KDE
*
* Copyright (C) 2007-2011 by Kare Sars <kare.sars@iki .fi>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================ */
// Local includes
#include "labeled_entry.h"
#include "labeled_entry.moc"
// Qt includes
#include <QHBoxLayout>
#include <QLabel>
#include <KLineEdit>
#include <KLocale>
#include <QPushButton>
namespace KSaneIface
{
LabeledEntry::LabeledEntry(QWidget *parent, const QString& ltext)
: KSaneOptionWidget(parent, ltext)
{
m_entry = new KLineEdit(this);
m_reset = new QPushButton(this);
m_reset->setText(i18nc("Label for button to reset text in a KLineEdit", "Reset"));
m_set = new QPushButton(this);
m_set->setText(i18nc("Label for button to write text in a KLineEdit to sane", "Set"));
m_layout->addWidget(m_entry, 1, 0, 1, 2);
m_layout->addWidget(m_reset, 1, 2);
m_layout->addWidget(m_set, 1, 3);
m_layout->setColumnStretch(1, 50);
connect(m_reset, SIGNAL(clicked()), this, SLOT(resetClicked()));
connect(m_set, SIGNAL(clicked()), this, SLOT(setClicked()));
}
LabeledEntry::~LabeledEntry()
{
}
void LabeledEntry::setText(const QString& text)
{
m_eText = text;
m_entry->setText(text);
}
void LabeledEntry::resetClicked()
{
m_entry->setText(m_eText);
}
void LabeledEntry::setClicked()
{
m_eText = m_entry->text();
emit entryEdited(m_eText);
}
} // NameSpace KSaneIface

View file

@ -0,0 +1,81 @@
/* ============================================================
*
* This file is part of the KDE project
*
* Date : 2007-09-13
* Description : Sane interface for KDE
*
* Copyright (C) 2007-2011 by Kare Sars <kare.sars@iki .fi>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================ */
#ifndef LABELED_ENTRY_H
#define LABELED_ENTRY_H
#include "ksane_option_widget.h"
/**
*@author Kåre Särs
*/
class QPushButton;
class KLineEdit;
namespace KSaneIface
{
/**
* A text entry field with a set and reset button
*/
class LabeledEntry : public KSaneOptionWidget
{
Q_OBJECT
public:
/**
* Create the entry.
*
* \param parent parent widget
* \param text is the text describing the entry.
*/
LabeledEntry(QWidget *parent, const QString& text);
~LabeledEntry();
void setText(const QString& text);
private Q_SLOTS:
void setClicked();
void resetClicked();
Q_SIGNALS:
void entryEdited(const QString& text);
private:
KLineEdit *m_entry;
QPushButton *m_set;
QPushButton *m_reset;
QString m_eText;
};
} // NameSpace KSaneIface
#endif // LABELED_ENTRY_H

View file

@ -0,0 +1,176 @@
/* ============================================================
*
* This file is part of the KDE project
*
* Date : 2007-09-13
* Description : Sane interface for KDE
*
* Copyright (C) 2007-2011 by Kare Sars <kare.sars@iki .fi>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================ */
// Local includes
#include "labeled_fslider.h"
#include "labeled_fslider.moc"
#define FLOAT_MULTIP 32768.0
#define TO_FLOAT(v) ((float)v / FLOAT_MULTIP)
#define TO_FIX(v) ((int)(v * FLOAT_MULTIP))
namespace KSaneIface
{
LabeledFSlider::LabeledFSlider(QWidget *parent, const QString& ltext,
float min, float max, float step)
: KSaneOptionWidget(parent, ltext)
{
int imin = TO_FIX(min);
int imax = TO_FIX(max);
m_istep = TO_FIX(step);
m_fstep = step;
if (m_istep == 0) {
m_istep = 1;
m_fstep = TO_FLOAT(m_istep);
}
//std::cout << "min=" << min << ", max=" << max << ", m_fstep="<<m_fstep<<std::endl;
//std::cout << "imin=" << imin << ", imax=" << imax << ", m_istep="<<m_istep<<std::endl;
m_slider = new QSlider(this);
m_slider->setOrientation(Qt::Horizontal);
m_slider->setMinimum(imin);
m_slider->setMaximum(imax);
m_slider->setSingleStep(m_istep);
m_slider->setValue(imin);
m_spinb = new QDoubleSpinBox(this);
m_spinb->setMinimum(min);
m_spinb->setMaximum(max);
m_spinb->setSingleStep(m_fstep);
int decimals=0;
float tmp_step = m_fstep;
while (tmp_step < 1) {
tmp_step *= 10;
decimals++;
if (decimals > 5) break;
}
m_spinb->setDecimals(decimals);
m_spinb->setValue(max);
//m_spinb->setMinimumWidth(m_spinb->sizeHint().width()+35);
m_spinb->setMinimumWidth(m_spinb->sizeHint().width());
m_spinb->setAlignment(Qt::AlignRight);
m_spinb->setValue(min);
m_label->setBuddy(m_spinb);
connect(m_spinb, SIGNAL(valueChanged(double)), this, SLOT(syncValues(double)));
connect(m_slider, SIGNAL(valueChanged(int)), this, SLOT(syncValues(int)));
connect(m_slider, SIGNAL(sliderReleased()), this, SLOT(fixValue()));
m_layout->addWidget(m_slider, 0,2);
m_layout->addWidget(m_spinb, 0, 1);
m_layout->setColumnStretch(1, 0);
m_layout->setColumnStretch(2, 50);
m_layout->activate();
}
LabeledFSlider::~LabeledFSlider()
{
}
void LabeledFSlider::setSuffix(const QString &text)
{
m_spinb->setSuffix(text);
}
void LabeledFSlider::setRange(float min, float max)
{
//kDebug() << "min,max(" << m_spinb->minimum() << " - " << m_spinb->maximum();
//kDebug() << ") -> (" << min << " - " << max << ")" << std::endl;
int imin=TO_FIX(min);
int imax=TO_FIX(max);
m_slider->setRange(imin, imax);
//std::cout << "fixedmin=" << imin << " fixedmax=" << imax << std::endl;
m_spinb->setRange(min, max);
}
void LabeledFSlider::setStep(float step)
{
m_istep = TO_FIX(step);
m_fstep = step;
if (m_istep == 0) {
m_istep = 1;
m_fstep = TO_FLOAT(m_istep);
}
m_slider->setSingleStep(m_istep);
m_spinb->setSingleStep(m_fstep);
int decimals=0;
float tmp_step = m_fstep;
while (tmp_step < 1) {
tmp_step *= 10;
decimals++;
if (decimals > 5) break;
}
m_spinb->setDecimals(decimals);
}
void LabeledFSlider::setValue(float value)
{
int ivalue = TO_FIX(value);
if (((value - m_spinb->value()) > m_fstep) || ((m_spinb->value() - value) > m_fstep)) {
m_spinb->setValue(value);
}
else if (ivalue != m_slider->value()) m_slider->setValue(ivalue);
}
void LabeledFSlider::syncValues(int ivalue)
{
double value = TO_FLOAT(ivalue);
if (((value - m_spinb->value()) > m_fstep) || ((m_spinb->value() - value) > m_fstep)) {
m_spinb->setValue(value);
}
else if (ivalue != m_slider->value())m_slider->setValue(ivalue);
else emit valueChanged(value);
}
void LabeledFSlider::syncValues(double value)
{
int ivalue = TO_FIX(value);
if (((value - m_spinb->value()) > m_fstep) || ((m_spinb->value() - value) > m_fstep)) {
m_spinb->setValue(value);
}
else if (ivalue != m_slider->value())m_slider->setValue(ivalue);
else emit valueChanged((float)value);
}
void LabeledFSlider::fixValue()
{
//ensure that the value step is followed also for the m_slider
int rest = (m_slider->value() - m_slider->minimum())%m_istep;
if (rest != 0) {
if (rest > (m_istep/2)) m_slider->setValue(m_slider->value()+(m_istep-rest));
else m_slider->setValue(m_slider->value()-rest);
m_spinb->setValue(TO_FLOAT(m_slider->value()));
}
}
} // NameSpace KSaneIface

View file

@ -0,0 +1,110 @@
/* ============================================================
*
* This file is part of the KDE project
*
* Date : 2007-09-13
* Description : Sane interface for KDE
*
* Copyright (C) 2007-2011 by Kare Sars <kare.sars@iki .fi>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================ */
#ifndef LABELED_FSLIDER_H
#define LABELED_FSLIDER_H
#include "ksane_option_widget.h"
// Qt includes
#include <QSlider>
#include <QDoubleSpinBox>
/**
*@author Kåre Särs
*/
namespace KSaneIface
{
/**
* A combination of a label a slider and a spinbox.
* The slider is connected to the spinbox so that they have the same value.
*/
class LabeledFSlider : public KSaneOptionWidget
{
Q_OBJECT
public:
/**
* Create the slider.
*
* \param parent parent widget
* \param text is the text describing the slider value. If the text
* contains a '&', a buddy for the slider will be created.
* \param min minimum slider value
* \param max maximum slider value
* \param quant is the step between values.
*/
LabeledFSlider(QWidget *parent, const QString& text,
float min, float max, float st);
~LabeledFSlider();
/**
* \return the slider value.
*/
float value() const {return (float)m_spinb->value();}
float step() const {return m_fstep;}
public Q_SLOTS:
/** Set the slider/spinbox value */
void setValue(float);
void setRange(float, float);
void setStep(float);
/** Set the unit */
void setSuffix(const QString &text);
private Q_SLOTS:
/**
* Sync the values and emit valueChanged()
*/
// FIXME this has to be changes later
void syncValues(int);
void syncValues(double);
void fixValue();
Q_SIGNALS:
/**
* Emit the slider value changes
*/
void valueChanged(float);
private:
QSlider *m_slider;
QDoubleSpinBox *m_spinb;
float m_fstep;
int m_istep;
};
} // NameSpace KSaneIface
#endif // LABELED_SFSLIDER_H

View file

@ -0,0 +1,199 @@
/* ============================================================
*
* This file is part of the KDE project
*
* Date : 2007-09-13
* Description : Sane interface for KDE
*
* Copyright (C) 2007-2011 by Kare Sars <kare.sars@iki .fi>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================ */
// Local includes
#include "labeled_gamma.h"
#include "labeled_gamma.moc"
// C++ includes
#include <cmath>
// Qt includes
#include <QGroupBox>
// KDE includes
#include <klocale.h>
namespace KSaneIface
{
LabeledGamma::LabeledGamma(QWidget *parent, const QString& text, int size)
: KSaneOptionWidget(parent, text)
{
m_bri_slider = new LabeledSlider(this, i18n("Brightness"), -50, 50, 1);
m_bri_slider->setValue(0);
m_con_slider = new LabeledSlider(this, i18n("Contrast"), -50, 50, 1);
m_con_slider->setValue(0);
m_gam_slider = new LabeledSlider(this, i18n("Gamma"), 30, 300, 1);
m_gam_slider->setValue(100);
// Calculate the size of the widgets in the sliders
int labelMax = m_bri_slider->labelWidthHint();
labelMax = qMax(labelMax, m_con_slider->labelWidthHint());
labelMax = qMax(labelMax, m_gam_slider->labelWidthHint());
// set the calculated widths
m_bri_slider->setLabelWidth(labelMax);
m_con_slider->setLabelWidth(labelMax);
m_gam_slider->setLabelWidth(labelMax);
m_gam_tbl.resize(size);
for (int i=0; i<m_gam_tbl.size(); i++) {
m_gam_tbl[i] = i;
}
m_max_val = size-1; // assume a gamma table 0 -> max
m_gamma_disp = new GammaDisp(this, &m_gam_tbl);
QGroupBox *groupBox = new QGroupBox(text, this);
QGridLayout *gr_lay = new QGridLayout(groupBox);
gr_lay->addWidget(m_bri_slider, 0, 0);
gr_lay->addWidget(m_con_slider, 1, 0);
gr_lay->addWidget(m_gam_slider, 2, 0);
gr_lay->addWidget(m_gamma_disp, 0, 1, 3, 1);
m_label->hide();
m_layout->addWidget(groupBox, 1, 0, 1,3);
connect(m_bri_slider, SIGNAL(valueChanged(int)), this, SLOT(calculateGT()));
connect(m_con_slider, SIGNAL(valueChanged(int)), this, SLOT(calculateGT()));
connect(m_gam_slider, SIGNAL(valueChanged(int)), this, SLOT(calculateGT()));
}
LabeledGamma::~LabeledGamma()
{
}
void LabeledGamma::setColor(const QColor &color)
{
if (m_gamma_disp != 0) {
m_gamma_disp->setColor(color);
}
}
void LabeledGamma::setValues(int bri, int con, int gam)
{
m_bri_slider->blockSignals(true);
m_con_slider->blockSignals(true);
m_gam_slider->blockSignals(true);
m_bri_slider->setValue(bri);
m_con_slider->setValue(con);
m_gam_slider->setValue(gam);
calculateGT();
m_bri_slider->blockSignals(false);
m_con_slider->blockSignals(false);
m_gam_slider->blockSignals(false);
}
void LabeledGamma::setValues(const QString &values)
{
m_bri_slider->blockSignals(true);
m_con_slider->blockSignals(true);
m_gam_slider->blockSignals(true);
QStringList gammaValues;
int bri;
int con;
int gam;
bool ok = true;
gammaValues = values.split(':');
bri = gammaValues.at(0).toInt(&ok);
if (ok) con = gammaValues.at(1).toInt(&ok);
if (ok) gam = gammaValues.at(2).toInt(&ok);
if (ok) {
m_bri_slider->setValue(bri);
m_con_slider->setValue(con);
m_gam_slider->setValue(gam);
calculateGT();
}
m_bri_slider->blockSignals(false);
m_con_slider->blockSignals(false);
m_gam_slider->blockSignals(false);
}
bool LabeledGamma::getValues(int &bri, int &con, int &gam)
{
bri = m_bri_slider->value();
con = m_con_slider->value();
gam = m_gam_slider->value();
return true;
}
void LabeledGamma::setSize(int size)
{
m_gam_tbl.resize(size);
for (int i=0; i<m_gam_tbl.size(); i++) {
m_gam_tbl[i] = i;
}
m_bri_slider->setValue(0);
m_con_slider->setValue(0);
m_gam_slider->setValue(0);
}
void LabeledGamma::calculateGT()
{
double gam = 100.0/m_gam_slider->value();
double con = (200.0/(100.0 - m_con_slider->value()))-1;
double half_max = m_max_val/2.0;
double bri = (m_bri_slider->value()/half_max) * m_max_val;
double x;
for (int i = 0; i<m_gam_tbl.size(); i++) {
// apply gamma
x = std::pow(i/m_max_val, gam) * m_max_val;
// apply contrast
x = (con*(x-half_max)) + half_max;
// apply brightness + rounding
x += bri + 0.5;
// ensure correct value
if (x > m_max_val) x = m_max_val;
if (x < 0) x = 0;
m_gam_tbl[i] = (int)x;
}
m_gamma_disp->update();
emit gammaChanged(m_bri_slider->value(), m_con_slider->value(), m_gam_slider->value());
emit gammaTableChanged(m_gam_tbl);
}
} // NameSpace KSaneIface

View file

@ -0,0 +1,93 @@
/* ============================================================
*
* This file is part of the KDE project
*
* Date : 2007-09-13
* Description : Sane interface for KDE
*
* Copyright (C) 2007-2011 by Kare Sars <kare.sars@iki .fi>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================ */
#ifndef LABELED_GAMMA_H
#define LABELED_GAMMA_H
// Local includes
#include "labeled_slider.h"
#include "gamma_disp.h"
/**
*@author Kåre Särs
*/
namespace KSaneIface
{
/**
* A wrapper for a checkbox
*/
class LabeledGamma : public KSaneOptionWidget
{
Q_OBJECT
public:
/**
* Create the checkbox.
*
* \param parent parent widget
* \param text is the text describing the checkbox.
*/
LabeledGamma(QWidget *parent, const QString& text, int elements);
~LabeledGamma();
void setColor(const QColor &color);
void setSize(int size);
const QVector<int> &gammaTablePtr() { return m_gam_tbl; }
int size() {return (int)(m_max_val+1);}
bool getValues(int &bri, int &con, int &gam);
public Q_SLOTS:
void setValues(int bri, int con, int gam);
void setValues(const QString &values);
private Q_SLOTS:
void calculateGT();
Q_SIGNALS:
void gammaChanged(int bri, int con, int gam);
void gammaTableChanged(const QVector<int> &gamma_tbl);
private:
LabeledSlider *m_bri_slider;
LabeledSlider *m_con_slider;
LabeledSlider *m_gam_slider;
QVector<int> m_gam_tbl;
double m_max_val;
GammaDisp *m_gamma_disp;
};
} // NameSpace KSaneIface
#endif // LABELED_GAMMA_H

View file

@ -0,0 +1,141 @@
/* ============================================================
*
* This file is part of the KDE project
*
* Date : 2007-09-13
* Description : Sane interface for KDE
*
* Copyright (C) 2007-2011 by Kare Sars <kare.sars@iki .fi>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================ */
// Local includes
#include "labeled_slider.h"
#include "labeled_slider.moc"
// KDE includes
#include <KNumInput>
// Qt includes
#include <QLabel>
#include <QSlider>
namespace KSaneIface
{
LabeledSlider::LabeledSlider(QWidget *parent, const QString& ltext,
int min, int max, int ste)
: KSaneOptionWidget(parent, ltext)
{
m_step = ste;
if (m_step == 0) m_step = 1;
m_slider = new QSlider(this);
m_slider->setOrientation(Qt::Horizontal);
m_slider->setMinimum(min);
m_slider->setMaximum(max);
m_slider->setSingleStep(m_step);
m_spinb = new KIntSpinBox(this);
m_spinb->setMinimum(min);
m_spinb->setMaximum(max);
m_slider->setSingleStep(m_step);
m_spinb->setValue(max);
//m_spinb->setMinimumWidth(m_spinb->sizeHint().width()+35);
m_spinb->setAlignment(Qt::AlignRight);
m_spinb->setValue(min);
m_spinb->setValue(min);
m_label->setBuddy(m_spinb);
connect(m_spinb, SIGNAL(valueChanged(int)), this, SLOT(syncValues(int)));
connect(m_slider, SIGNAL(valueChanged(int)), this, SLOT(syncValues(int)));
connect(m_slider, SIGNAL(sliderReleased()), this, SLOT(fixValue()));
m_layout->addWidget(m_slider, 0, 2);
m_layout->addWidget(m_spinb, 0, 1);
m_layout->setColumnStretch(1, 0);
m_layout->setColumnStretch(2, 50);
}
LabeledSlider::~LabeledSlider()
{
}
void LabeledSlider::setSuffix(const KLocalizedString &text)
{
m_spinb->setSuffix(text);
}
void LabeledSlider::setValue(int value)
{
if (value != m_slider->value()) m_slider->setValue(value);
else if (value != m_spinb->value()) m_spinb->setValue(value);
}
void LabeledSlider::setRange(int min, int max)
{
//std::cout << "min=" << min << ", max=" << max << std::endl;
m_slider->setRange(min, max);
m_spinb->setRange(min, max);
}
void LabeledSlider::setStep(int st)
{
m_step = st;
if (m_step == 0) m_step = 1;
m_slider->setSingleStep(m_step);
m_spinb->setSingleStep(m_step);
}
void LabeledSlider::syncValues(int value)
{
if (value != m_spinb->value()) m_spinb->setValue(value);
else if (value != m_slider->value()) {
//ensure that the value m_step is followed also for the m_slider
if ((value - m_slider->minimum())%m_step != 0) {
if (value > m_spinb->value()) {
m_slider->setValue(m_slider->value()+(m_step-(value - m_spinb->value())));
}
else {
m_slider->setValue(m_slider->value()-(m_step-(m_spinb->value() - value)));
}
// this function will be reentered with the signal fom the m_slider
}
else {
m_slider->setValue(value);
}
}
else emit valueChanged(value);
}
void LabeledSlider::fixValue()
{
//ensure that the value m_step is followed also for the m_slider
int rest = (m_slider->value() - m_slider->minimum())%m_step;
if (rest != 0) {
if (rest > (m_step/2)) m_slider->setValue(m_slider->value()+(m_step-rest));
else m_slider->setValue(m_slider->value()-rest);
m_spinb->setValue(m_slider->value());
}
}
} // NameSpace KSaneIface

View file

@ -0,0 +1,104 @@
/* ============================================================
*
* This file is part of the KDE project
*
* Date : 2007-09-13
* Description : Sane interface for KDE
*
* Copyright (C) 2007-2011 by Kare Sars <kare.sars@iki .fi>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* ============================================================ */
#ifndef LABELED_SLIDER_H
#define LABELED_SLIDER_H
#include "ksane_option_widget.h"
// Qt includes
#include <QSlider>
/**
*@author Kåre Särs
*/
class KIntSpinBox;
class KLocalizedString;
namespace KSaneIface
{
/**
* A combination of a label a slider and a spinbox.
* The slider is connected to the spinbox so that they have the same value.
*/
class LabeledSlider : public KSaneOptionWidget
{
Q_OBJECT
public:
/**
* Create the slider.
*
* \param parent parent widget
* \param text is the text describing the slider value. If the text
* contains a '&', a buddy for the slider will be created.
* \param min minimum slider value
* \param max maximum slider value
* \param quant is the step between values.
*/
LabeledSlider(QWidget *parent, const QString& text,
int min, int max, int st);
~LabeledSlider();
int value() const { return( m_slider->value()); }
public Q_SLOTS:
/** Set the slider value */
void setValue(int);
void setRange(int min, int max);
void setStep(int);
/** Set the unit */
void setSuffix(const KLocalizedString &text);
private Q_SLOTS:
/** Sync the values and emit valueChanged() */
void syncValues(int);
/** Ensure step value is followed */
void fixValue();
Q_SIGNALS:
/**
* Emit the slider value changes
*/
void valueChanged(int);
private:
QSlider *m_slider;
KIntSpinBox *m_spinb;
int m_step;
};
} // NameSpace KSaneIface
#endif // LABELED_SLIDER_H

3
skanlite/.directory Normal file
View file

@ -0,0 +1,3 @@
[Dolphin]
Timestamp=2015,1,1,1,18,3
Version=3

21
skanlite/CMakeLists.txt Normal file
View file

@ -0,0 +1,21 @@
cmake_minimum_required(VERSION 2.6)
project(skanlite)
find_package(KDE4 REQUIRED)
include(KDE4Defaults)
include_directories (${KDE4_INCLUDES})
find_package(KSane REQUIRED)
find_package(PNG REQUIRED)
set(SKANLITE_VERSION_MAJOR "1")
set(SKANLITE_VERSION_MINOR "1")
set(SKANLITE_VERSION_STRING "${SKANLITE_VERSION_MAJOR}.${SKANLITE_VERSION_MINOR}")
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/src/version.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/src/version.h)
add_subdirectory(src)

View file

@ -0,0 +1,14 @@
include_directories(${KSANE_INCLUDE_DIR})
set(skanlite_SRCS main.cpp skanlite.cpp ImageViewer.cpp KSaneImageSaver.cpp SaveLocation.cpp)
kde4_add_ui_files(skanlite_SRCS settings.ui SaveLocation.ui)
kde4_add_app_icon(skanlite_SRCS "${KDE4_INSTALL_DIR}/share/icons/oxygen/*/devices/scanner.png")
kde4_add_executable(skanlite ${skanlite_SRCS})
target_link_libraries(skanlite ${KDE4_KIO_LIBS} ${KSANE_LIBRARY} ${PNG_LIBRARY})
install(TARGETS skanlite ${INSTALL_TARGETS_DEFAULT_ARGS})
install( PROGRAMS skanlite.desktop DESTINATION ${XDG_APPS_INSTALL_DIR} )

346
skanlite/src/COPYING Normal file
View file

@ -0,0 +1,346 @@
NOTE! The GPL below is copyrighted by the Free Software Foundation, but
the instance of code that it refers to (the kde programs) are copyrighted
by the authors who actually wrote it.
---------------------------------------------------------------------------
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

View file

@ -0,0 +1,138 @@
/* ============================================================
* Date : 2008-08-26
* Description : Preview image viewer.
*
* Copyright (C) 2008-2012 by Kåre Särs <kare.sars@iki .fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License.
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
* ============================================================ */
#include "ImageViewer.h"
#include "ImageViewer.moc"
#include <QGraphicsPixmapItem>
#include <QGraphicsScene>
#include <QScrollBar>
#include <QAction>
#include <KIcon>
#include <KLocale>
#include <KDebug>
struct ImageViewer::Private
{
QGraphicsScene *scene;
QImage *img;
QAction *zoomInAction;
QAction *zoomOutAction;
QAction *zoom100Action;
QAction *zoom2FitAction;
};
ImageViewer::ImageViewer(QWidget *parent) : QGraphicsView(parent), d(new Private)
{
//setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
//setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
setMouseTracking(true);
// Init the scene
d->scene = new QGraphicsScene;
setScene(d->scene);
// create context menu
d->zoomInAction = new QAction(KIcon("zoom-in"), i18n("Zoom In"), this);
connect(d->zoomInAction, SIGNAL(triggered()), this, SLOT(zoomIn()));
d->zoomOutAction = new QAction(KIcon("zoom-out"), i18n("Zoom Out"), this);
connect(d->zoomOutAction, SIGNAL(triggered()), this, SLOT(zoomOut()));
d->zoom100Action = new QAction(KIcon("zoom-fit-best"), i18n("Zoom to Actual size"), this);
connect(d->zoom100Action, SIGNAL(triggered()), this, SLOT(zoomActualSize()));
d->zoom2FitAction = new QAction(KIcon("document-preview"), i18n("Zoom to Fit"), this);
connect(d->zoom2FitAction, SIGNAL(triggered()), this, SLOT(zoom2Fit()));
addAction(d->zoomInAction);
addAction(d->zoomOutAction);
addAction(d->zoom100Action);
addAction(d->zoom2FitAction);
setContextMenuPolicy(Qt::ActionsContextMenu);
}
// ------------------------------------------------------------------------
ImageViewer::~ImageViewer()
{
delete d;
}
// ------------------------------------------------------------------------
void ImageViewer::setQImage(QImage *img)
{
if (img == 0) return;
d->img = img;
d->scene->setSceneRect(0, 0, img->width(), img->height());
}
// ------------------------------------------------------------------------
void ImageViewer::drawBackground(QPainter *painter, const QRectF &rect)
{
painter->fillRect(rect, QColor(0x70, 0x70, 0x70));
painter->drawImage(rect, *d->img, rect);
}
// ------------------------------------------------------------------------
void ImageViewer::zoomIn()
{
scale(1.5, 1.5);
}
// ------------------------------------------------------------------------
void ImageViewer::zoomOut()
{
scale(1.0 / 1.5, 1.0 / 1.5);
}
// ------------------------------------------------------------------------
void ImageViewer::zoomActualSize()
{
setMatrix(QMatrix());
}
// ------------------------------------------------------------------------
void ImageViewer::zoom2Fit()
{
fitInView(d->img->rect(), Qt::KeepAspectRatio);
}
// ------------------------------------------------------------------------
void ImageViewer::wheelEvent(QWheelEvent *e)
{
if(e->modifiers() == Qt::ControlModifier) {
if(e->delta() > 0) {
zoomIn();
} else {
zoomOut();
}
} else {
QGraphicsView::wheelEvent(e);
}
}

View file

@ -0,0 +1,58 @@
/* ============================================================
* Date : 2009-08-26
* Description : Preview image viewer.
*
* Copyright (C) 2008-2012 by Kåre Särs <kare.sars@iki .fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License.
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
* ============================================================ */
#ifndef IMAGE_VIEWER_H
#define IMAGE_VIEWER_H
#include <QGraphicsView>
#include <QWheelEvent>
class ImageViewer : public QGraphicsView
{
Q_OBJECT
public:
ImageViewer(QWidget *parent = 0);
~ImageViewer();
void setQImage(QImage *img);
public Q_SLOTS:
void zoomIn();
void zoomOut();
void zoom2Fit();
void zoomActualSize();
protected:
void wheelEvent(QWheelEvent *e);
void drawBackground(QPainter *painter, const QRectF &rect);
private:
struct Private;
Private * const d;
};
#endif

View file

@ -0,0 +1,236 @@
/* ============================================================
* Date : 2010-07-02
* Description : Image saver class for libksane image data.
*
* Copyright (C) 2010-2012 by Kåre Särs <kare.sars@iki .fi>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License.
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
* ============================================================ */
#include "KSaneImageSaver.h"
#include <png.h>
#include <KDebug>
#include <QMutex>
struct KSaneImageSaver::Private
{
enum ImageType {
ImageTypePNG,
ImageTypeTIFF
};
bool m_savedOk;
QMutex m_runMutex;
KSaneImageSaver *q;
QString m_name;
QByteArray m_data;
int m_width;
int m_height;
int m_format;
ImageType m_type;
bool savePng();
bool saveTiff();
};
// ------------------------------------------------------------------------
KSaneImageSaver::KSaneImageSaver(QObject *parent) : QThread(parent), d(new Private)
{
d->q = this;
}
// ------------------------------------------------------------------------
KSaneImageSaver::~KSaneImageSaver()
{
delete d;
}
bool KSaneImageSaver::savePng(const QString &name, const QByteArray &data, int width, int height, int format)
{
if (!d->m_runMutex.tryLock()) return false;
d->m_name = name;
d->m_data = data;
d->m_width = width;
d->m_height = height;
d->m_format = format;
d->m_type = Private::ImageTypePNG;
start();
return true;
}
bool KSaneImageSaver::savePngSync(const QString &name, const QByteArray &data, int width, int height, int format)
{
if (!savePng(name, data, width, height, format)) {
kDebug() << "fail";
return false;
}
wait();
return d->m_savedOk;
}
bool KSaneImageSaver::saveTiff(const QString &name, const QByteArray &data, int width, int height, int format)
{
if (!d->m_runMutex.tryLock()) return false;
d->m_name = name;
d->m_data = data;
d->m_width = width;
d->m_height = height;
d->m_format = format;
d->m_type = Private::ImageTypeTIFF;
kDebug() << "saving Tiff images is not yet supported";
d->m_runMutex.unlock();
return false;
}
bool KSaneImageSaver::saveTiffSync(const QString &name, const QByteArray &data, int width, int height, int format)
{
if (!saveTiff(name, data, width, height, format)) {
return false;
}
wait();
return d->m_savedOk;
}
void KSaneImageSaver::run()
{
if (d->m_type == Private::ImageTypeTIFF) {
d->m_savedOk = d->saveTiff();
emit imageSaved(d->m_savedOk);
}
else {
d->m_savedOk = d->savePng();
emit imageSaved(d->m_savedOk);
}
d->m_runMutex.unlock();
}
bool KSaneImageSaver::Private::saveTiff()
{
return false;
}
bool KSaneImageSaver::Private::savePng()
{
FILE *file;
png_structp png_ptr;
png_infop info_ptr;
png_color_8 sig_bit;
png_bytep row_ptr;
int bytesPerPixel;
// open the file
file = fopen(qPrintable(m_name), "wb");
if (!file) return false;
// create the png struct
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!png_ptr) {
fclose(file);
return false;
}
// create the image information srtuct
info_ptr = png_create_info_struct(png_ptr);
if (!png_ptr) {
fclose(file);
png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
return false;
}
// initialize IO
png_init_io(png_ptr, file);
// set the image attributes
switch ((KSaneIface::KSaneWidget::ImageFormat)m_format)
{
case KSaneIface::KSaneWidget::FormatGrayScale16:
png_set_IHDR(png_ptr, info_ptr, m_width, m_height, 16, PNG_COLOR_TYPE_GRAY,
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
sig_bit.gray = 16;
bytesPerPixel = 2;
break;
case KSaneIface::KSaneWidget::FormatRGB_16_C:
png_set_IHDR(png_ptr, info_ptr, m_width, m_height, 16, PNG_COLOR_TYPE_RGB,
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
sig_bit.red = 16;
sig_bit.green = 16;
sig_bit.blue = 16;
bytesPerPixel = 6;
break;
default:
fclose(file);
png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
return false;
}
png_set_sBIT(png_ptr, info_ptr, &sig_bit);
/* Optionally write comments into the image */
// text_ptr[0].key = "Title";
// text_ptr[0].text = "Mona Lisa";
// text_ptr[0].compression = PNG_TEXT_COMPRESSION_NONE;
// text_ptr[1].key = "Author";
// text_ptr[1].text = "Leonardo DaVinci";
// text_ptr[1].compression = PNG_TEXT_COMPRESSION_NONE;
// text_ptr[2].key = "Description";
// text_ptr[2].text = "<long text>";
// text_ptr[2].compression = PNG_TEXT_COMPRESSION_zTXt;
// png_set_text(png_ptr, info_ptr, text_ptr, 2);
/* Write the file header information. */
png_write_info(png_ptr, info_ptr);
//png_set_shift(png_ptr, &sig_bit);
//png_set_packing(png_ptr);
png_set_compression_level(png_ptr, 9);
// This is not nice :( swap bytes in the 16 bit color....
char tmp;
// Make sure we have a buffer size that is divisible by 2
int dataSize = m_data.size();
if ((dataSize % 2) > 0) dataSize--;
for (int i=0; i<dataSize; i+=2) {
tmp = m_data[i];
m_data[i] = m_data[i+1];
m_data[i+1] = tmp;
}
row_ptr = (png_bytep)m_data.data();
for (int i=0; i<m_height; i++) {
png_write_rows(png_ptr, &row_ptr, 1);
row_ptr += m_width * bytesPerPixel;
}
png_write_end(png_ptr, info_ptr);
png_destroy_write_struct(&png_ptr, (png_infopp) & info_ptr);
png_destroy_info_struct(png_ptr, (png_infopp) & info_ptr);
fclose(file);
return true;
}

Some files were not shown because too many files have changed in this diff Show more