Initial commit.
This commit is contained in:
30
CMakeLists.txt
Normal file
30
CMakeLists.txt
Normal file
@@ -0,0 +1,30 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
project(s7)
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/CMake")
|
||||
|
||||
find_package(wxWidgets COMPONENTS base core CONFIG REQUIRED)
|
||||
|
||||
# xpm include.
|
||||
add_definitions(-Wno-write-strings)
|
||||
|
||||
include_directories(${CMAKE_CURRENT_LIST_DIR}
|
||||
Resources/InsaneWidget
|
||||
Resources/Utilities
|
||||
Resources/InsaneWidget/UI
|
||||
Resources/UI/S7)
|
||||
|
||||
add_subdirectory(Resources/Utilities)
|
||||
add_subdirectory(Resources/InsaneWidget)
|
||||
|
||||
add_executable(s7
|
||||
Resources/UI/S7/s7app.cpp
|
||||
Resources/UI/S7/s7.cpp
|
||||
XS7.cpp)
|
||||
|
||||
install(TARGETS s7 RUNTIME DESTINATION bin)
|
||||
|
||||
target_link_libraries(s7 minutils insanewidget
|
||||
${wxWidgets_LIBRARIES}
|
||||
)
|
||||
55
README.md
Normal file
55
README.md
Normal file
@@ -0,0 +1,55 @@
|
||||
# S7
|
||||
|
||||
This is a simple scanning application with these goals:
|
||||
|
||||
- full page scan
|
||||
- known number of pages to scan
|
||||
- double-sided handling
|
||||
- multiple output file format: PNG, JPEG, TIFF, PNM and PDF.
|
||||
|
||||
It is based on [libinsane](https://gitlab.gnome.org/World/OpenPaperwork/libinsane) and written with [wxWidgets](https://wxwidgets.org).
|
||||
|
||||

|
||||
|
||||
### Usage
|
||||
|
||||
Inputs:
|
||||
|
||||
- a target directory
|
||||
- the basename of the output file(s)
|
||||
- the number of faces to scan
|
||||
- double-sided or not
|
||||
- the scanner and its minimal parameters (source, mode, resolution)
|
||||
- page size
|
||||
- output file format.
|
||||
|
||||
Right click on the 'New' label to specify the number of faces and whether double-sided scanning is needed.
|
||||
|
||||
'Shift + left click' on the 'New' label to update the output path.
|
||||
|
||||
Right click on the 'Scan' button to set the device properties.
|
||||
|
||||
Outputs:
|
||||
|
||||
- a single PDF file with the number of requested pages
|
||||
- multiple PNG files with a padded index as suffix.
|
||||
|
||||
### Double-sided scanning
|
||||
|
||||
This has meaning if an automatic document feeder (ADF) is used to scan multiple pages on both sides.
|
||||
|
||||
Feed in all the pages on the front face, then turn the whole pile of pages even if an odd number of pages is requested and continue scanning.
|
||||
|
||||
If only front faces are needed with an ADF, uncheck the 'Double-sided' option.
|
||||
|
||||
### Notes
|
||||
|
||||
The project targets Linux only using wxGTK3.
|
||||
|
||||
When running under Wayland, set the 'GDK_BACKEND=x11' environment variable to avoid unexpected results.
|
||||
|
||||
### Disclaimer
|
||||
|
||||
Use at your own risks.
|
||||
|
||||
|
||||
517
Resources/CeCILL-C_V1-en.txt
Normal file
517
Resources/CeCILL-C_V1-en.txt
Normal file
@@ -0,0 +1,517 @@
|
||||
|
||||
CeCILL-C FREE SOFTWARE LICENSE AGREEMENT
|
||||
|
||||
|
||||
Notice
|
||||
|
||||
This Agreement is a Free Software license agreement that is the result
|
||||
of discussions between its authors in order to ensure compliance with
|
||||
the two main principles guiding its drafting:
|
||||
|
||||
* firstly, compliance with the principles governing the distribution
|
||||
of Free Software: access to source code, broad rights granted to
|
||||
users,
|
||||
* secondly, the election of a governing law, French law, with which
|
||||
it is conformant, both as regards the law of torts and
|
||||
intellectual property law, and the protection that it offers to
|
||||
both authors and holders of the economic rights over software.
|
||||
|
||||
The authors of the CeCILL-C (for Ce[a] C[nrs] I[nria] L[ogiciel] L[ibre])
|
||||
license are:
|
||||
|
||||
Commissariat à l'Energie Atomique - CEA, a public scientific, technical
|
||||
and industrial research establishment, having its principal place of
|
||||
business at 25 rue Leblanc, immeuble Le Ponant D, 75015 Paris, France.
|
||||
|
||||
Centre National de la Recherche Scientifique - CNRS, a public scientific
|
||||
and technological establishment, having its principal place of business
|
||||
at 3 rue Michel-Ange, 75794 Paris cedex 16, France.
|
||||
|
||||
Institut National de Recherche en Informatique et en Automatique -
|
||||
INRIA, a public scientific and technological establishment, having its
|
||||
principal place of business at Domaine de Voluceau, Rocquencourt, BP
|
||||
105, 78153 Le Chesnay cedex, France.
|
||||
|
||||
|
||||
Preamble
|
||||
|
||||
The purpose of this Free Software license agreement is to grant users
|
||||
the right to modify and re-use the software governed by this license.
|
||||
|
||||
The exercising of this right is conditional upon the obligation to make
|
||||
available to the community the modifications made to the source code of
|
||||
the software so as to contribute to its evolution.
|
||||
|
||||
In consideration of access to the source code and the rights to copy,
|
||||
modify and redistribute granted by the license, users are provided only
|
||||
with a limited warranty and the software's author, the holder of the
|
||||
economic rights, and the successive licensors only have limited liability.
|
||||
|
||||
In this respect, the risks associated with loading, using, modifying
|
||||
and/or developing or reproducing the software by the user are brought to
|
||||
the user's attention, given its Free Software status, which may make it
|
||||
complicated to use, with the result that its use is reserved for
|
||||
developers and experienced professionals having in-depth computer
|
||||
knowledge. Users are therefore encouraged to load and test the
|
||||
suitability of the software as regards their requirements in conditions
|
||||
enabling the security of their systems and/or data to be ensured and,
|
||||
more generally, to use and operate it in the same conditions of
|
||||
security. This Agreement may be freely reproduced and published,
|
||||
provided it is not altered, and that no provisions are either added or
|
||||
removed herefrom.
|
||||
|
||||
This Agreement may apply to any or all software for which the holder of
|
||||
the economic rights decides to submit the use thereof to its provisions.
|
||||
|
||||
|
||||
Article 1 - DEFINITIONS
|
||||
|
||||
For the purpose of this Agreement, when the following expressions
|
||||
commence with a capital letter, they shall have the following meaning:
|
||||
|
||||
Agreement: means this license agreement, and its possible subsequent
|
||||
versions and annexes.
|
||||
|
||||
Software: means the software in its Object Code and/or Source Code form
|
||||
and, where applicable, its documentation, "as is" when the Licensee
|
||||
accepts the Agreement.
|
||||
|
||||
Initial Software: means the Software in its Source Code and possibly its
|
||||
Object Code form and, where applicable, its documentation, "as is" when
|
||||
it is first distributed under the terms and conditions of the Agreement.
|
||||
|
||||
Modified Software: means the Software modified by at least one
|
||||
Integrated Contribution.
|
||||
|
||||
Source Code: means all the Software's instructions and program lines to
|
||||
which access is required so as to modify the Software.
|
||||
|
||||
Object Code: means the binary files originating from the compilation of
|
||||
the Source Code.
|
||||
|
||||
Holder: means the holder(s) of the economic rights over the Initial
|
||||
Software.
|
||||
|
||||
Licensee: means the Software user(s) having accepted the Agreement.
|
||||
|
||||
Contributor: means a Licensee having made at least one Integrated
|
||||
Contribution.
|
||||
|
||||
Licensor: means the Holder, or any other individual or legal entity, who
|
||||
distributes the Software under the Agreement.
|
||||
|
||||
Integrated Contribution: means any or all modifications, corrections,
|
||||
translations, adaptations and/or new functions integrated into the
|
||||
Source Code by any or all Contributors.
|
||||
|
||||
Related Module: means a set of sources files including their
|
||||
documentation that, without modification to the Source Code, enables
|
||||
supplementary functions or services in addition to those offered by the
|
||||
Software.
|
||||
|
||||
Derivative Software: means any combination of the Software, modified or
|
||||
not, and of a Related Module.
|
||||
|
||||
Parties: mean both the Licensee and the Licensor.
|
||||
|
||||
These expressions may be used both in singular and plural form.
|
||||
|
||||
|
||||
Article 2 - PURPOSE
|
||||
|
||||
The purpose of the Agreement is the grant by the Licensor to the
|
||||
Licensee of a non-exclusive, transferable and worldwide license for the
|
||||
Software as set forth in Article 5 hereinafter for the whole term of the
|
||||
protection granted by the rights over said Software.
|
||||
|
||||
|
||||
Article 3 - ACCEPTANCE
|
||||
|
||||
3.1 The Licensee shall be deemed as having accepted the terms and
|
||||
conditions of this Agreement upon the occurrence of the first of the
|
||||
following events:
|
||||
|
||||
* (i) loading the Software by any or all means, notably, by
|
||||
downloading from a remote server, or by loading from a physical
|
||||
medium;
|
||||
* (ii) the first time the Licensee exercises any of the rights
|
||||
granted hereunder.
|
||||
|
||||
3.2 One copy of the Agreement, containing a notice relating to the
|
||||
characteristics of the Software, to the limited warranty, and to the
|
||||
fact that its use is restricted to experienced users has been provided
|
||||
to the Licensee prior to its acceptance as set forth in Article 3.1
|
||||
hereinabove, and the Licensee hereby acknowledges that it has read and
|
||||
understood it.
|
||||
|
||||
|
||||
Article 4 - EFFECTIVE DATE AND TERM
|
||||
|
||||
|
||||
4.1 EFFECTIVE DATE
|
||||
|
||||
The Agreement shall become effective on the date when it is accepted by
|
||||
the Licensee as set forth in Article 3.1.
|
||||
|
||||
|
||||
4.2 TERM
|
||||
|
||||
The Agreement shall remain in force for the entire legal term of
|
||||
protection of the economic rights over the Software.
|
||||
|
||||
|
||||
Article 5 - SCOPE OF RIGHTS GRANTED
|
||||
|
||||
The Licensor hereby grants to the Licensee, who accepts, the following
|
||||
rights over the Software for any or all use, and for the term of the
|
||||
Agreement, on the basis of the terms and conditions set forth hereinafter.
|
||||
|
||||
Besides, if the Licensor owns or comes to own one or more patents
|
||||
protecting all or part of the functions of the Software or of its
|
||||
components, the Licensor undertakes not to enforce the rights granted by
|
||||
these patents against successive Licensees using, exploiting or
|
||||
modifying the Software. If these patents are transferred, the Licensor
|
||||
undertakes to have the transferees subscribe to the obligations set
|
||||
forth in this paragraph.
|
||||
|
||||
|
||||
5.1 RIGHT OF USE
|
||||
|
||||
The Licensee is authorized to use the Software, without any limitation
|
||||
as to its fields of application, with it being hereinafter specified
|
||||
that this comprises:
|
||||
|
||||
1. permanent or temporary reproduction of all or part of the Software
|
||||
by any or all means and in any or all form.
|
||||
|
||||
2. loading, displaying, running, or storing the Software on any or
|
||||
all medium.
|
||||
|
||||
3. entitlement to observe, study or test its operation so as to
|
||||
determine the ideas and principles behind any or all constituent
|
||||
elements of said Software. This shall apply when the Licensee
|
||||
carries out any or all loading, displaying, running, transmission
|
||||
or storage operation as regards the Software, that it is entitled
|
||||
to carry out hereunder.
|
||||
|
||||
|
||||
5.2 RIGHT OF MODIFICATION
|
||||
|
||||
The right of modification includes the right to translate, adapt,
|
||||
arrange, or make any or all modifications to the Software, and the right
|
||||
to reproduce the resulting software. It includes, in particular, the
|
||||
right to create a Derivative Software.
|
||||
|
||||
The Licensee is authorized to make any or all modification to the
|
||||
Software provided that it includes an explicit notice that it is the
|
||||
author of said modification and indicates the date of the creation thereof.
|
||||
|
||||
|
||||
5.3 RIGHT OF DISTRIBUTION
|
||||
|
||||
In particular, the right of distribution includes the right to publish,
|
||||
transmit and communicate the Software to the general public on any or
|
||||
all medium, and by any or all means, and the right to market, either in
|
||||
consideration of a fee, or free of charge, one or more copies of the
|
||||
Software by any means.
|
||||
|
||||
The Licensee is further authorized to distribute copies of the modified
|
||||
or unmodified Software to third parties according to the terms and
|
||||
conditions set forth hereinafter.
|
||||
|
||||
|
||||
5.3.1 DISTRIBUTION OF SOFTWARE WITHOUT MODIFICATION
|
||||
|
||||
The Licensee is authorized to distribute true copies of the Software in
|
||||
Source Code or Object Code form, provided that said distribution
|
||||
complies with all the provisions of the Agreement and is accompanied by:
|
||||
|
||||
1. a copy of the Agreement,
|
||||
|
||||
2. a notice relating to the limitation of both the Licensor's
|
||||
warranty and liability as set forth in Articles 8 and 9,
|
||||
|
||||
and that, in the event that only the Object Code of the Software is
|
||||
redistributed, the Licensee allows effective access to the full Source
|
||||
Code of the Software at a minimum during the entire period of its
|
||||
distribution of the Software, it being understood that the additional
|
||||
cost of acquiring the Source Code shall not exceed the cost of
|
||||
transferring the data.
|
||||
|
||||
|
||||
5.3.2 DISTRIBUTION OF MODIFIED SOFTWARE
|
||||
|
||||
When the Licensee makes an Integrated Contribution to the Software, the
|
||||
terms and conditions for the distribution of the resulting Modified
|
||||
Software become subject to all the provisions of this Agreement.
|
||||
|
||||
The Licensee is authorized to distribute the Modified Software, in
|
||||
source code or object code form, provided that said distribution
|
||||
complies with all the provisions of the Agreement and is accompanied by:
|
||||
|
||||
1. a copy of the Agreement,
|
||||
|
||||
2. a notice relating to the limitation of both the Licensor's
|
||||
warranty and liability as set forth in Articles 8 and 9,
|
||||
|
||||
and that, in the event that only the object code of the Modified
|
||||
Software is redistributed, the Licensee allows effective access to the
|
||||
full source code of the Modified Software at a minimum during the entire
|
||||
period of its distribution of the Modified Software, it being understood
|
||||
that the additional cost of acquiring the source code shall not exceed
|
||||
the cost of transferring the data.
|
||||
|
||||
|
||||
5.3.3 DISTRIBUTION OF DERIVATIVE SOFTWARE
|
||||
|
||||
When the Licensee creates Derivative Software, this Derivative Software
|
||||
may be distributed under a license agreement other than this Agreement,
|
||||
subject to compliance with the requirement to include a notice
|
||||
concerning the rights over the Software as defined in Article 6.4.
|
||||
In the event the creation of the Derivative Software required modification
|
||||
of the Source Code, the Licensee undertakes that:
|
||||
|
||||
1. the resulting Modified Software will be governed by this Agreement,
|
||||
2. the Integrated Contributions in the resulting Modified Software
|
||||
will be clearly identified and documented,
|
||||
3. the Licensee will allow effective access to the source code of the
|
||||
Modified Software, at a minimum during the entire period of
|
||||
distribution of the Derivative Software, such that such
|
||||
modifications may be carried over in a subsequent version of the
|
||||
Software; it being understood that the additional cost of
|
||||
purchasing the source code of the Modified Software shall not
|
||||
exceed the cost of transferring the data.
|
||||
|
||||
|
||||
5.3.4 COMPATIBILITY WITH THE CeCILL LICENSE
|
||||
|
||||
When a Modified Software contains an Integrated Contribution subject to
|
||||
the CeCILL license agreement, or when a Derivative Software contains a
|
||||
Related Module subject to the CeCILL license agreement, the provisions
|
||||
set forth in the third item of Article 6.4 are optional.
|
||||
|
||||
|
||||
Article 6 - INTELLECTUAL PROPERTY
|
||||
|
||||
|
||||
6.1 OVER THE INITIAL SOFTWARE
|
||||
|
||||
The Holder owns the economic rights over the Initial Software. Any or
|
||||
all use of the Initial Software is subject to compliance with the terms
|
||||
and conditions under which the Holder has elected to distribute its work
|
||||
and no one shall be entitled to modify the terms and conditions for the
|
||||
distribution of said Initial Software.
|
||||
|
||||
The Holder undertakes that the Initial Software will remain ruled at
|
||||
least by this Agreement, for the duration set forth in Article 4.2.
|
||||
|
||||
|
||||
6.2 OVER THE INTEGRATED CONTRIBUTIONS
|
||||
|
||||
The Licensee who develops an Integrated Contribution is the owner of the
|
||||
intellectual property rights over this Contribution as defined by
|
||||
applicable law.
|
||||
|
||||
|
||||
6.3 OVER THE RELATED MODULES
|
||||
|
||||
The Licensee who develops a Related Module is the owner of the
|
||||
intellectual property rights over this Related Module as defined by
|
||||
applicable law and is free to choose the type of agreement that shall
|
||||
govern its distribution under the conditions defined in Article 5.3.3.
|
||||
|
||||
|
||||
6.4 NOTICE OF RIGHTS
|
||||
|
||||
The Licensee expressly undertakes:
|
||||
|
||||
1. not to remove, or modify, in any manner, the intellectual property
|
||||
notices attached to the Software;
|
||||
|
||||
2. to reproduce said notices, in an identical manner, in the copies
|
||||
of the Software modified or not;
|
||||
|
||||
3. to ensure that use of the Software, its intellectual property
|
||||
notices and the fact that it is governed by the Agreement is
|
||||
indicated in a text that is easily accessible, specifically from
|
||||
the interface of any Derivative Software.
|
||||
|
||||
The Licensee undertakes not to directly or indirectly infringe the
|
||||
intellectual property rights of the Holder and/or Contributors on the
|
||||
Software and to take, where applicable, vis-à-vis its staff, any and all
|
||||
measures required to ensure respect of said intellectual property rights
|
||||
of the Holder and/or Contributors.
|
||||
|
||||
|
||||
Article 7 - RELATED SERVICES
|
||||
|
||||
7.1 Under no circumstances shall the Agreement oblige the Licensor to
|
||||
provide technical assistance or maintenance services for the Software.
|
||||
|
||||
However, the Licensor is entitled to offer this type of services. The
|
||||
terms and conditions of such technical assistance, and/or such
|
||||
maintenance, shall be set forth in a separate instrument. Only the
|
||||
Licensor offering said maintenance and/or technical assistance services
|
||||
shall incur liability therefor.
|
||||
|
||||
7.2 Similarly, any Licensor is entitled to offer to its licensees, under
|
||||
its sole responsibility, a warranty, that shall only be binding upon
|
||||
itself, for the redistribution of the Software and/or the Modified
|
||||
Software, under terms and conditions that it is free to decide. Said
|
||||
warranty, and the financial terms and conditions of its application,
|
||||
shall be subject of a separate instrument executed between the Licensor
|
||||
and the Licensee.
|
||||
|
||||
|
||||
Article 8 - LIABILITY
|
||||
|
||||
8.1 Subject to the provisions of Article 8.2, the Licensee shall be
|
||||
entitled to claim compensation for any direct loss it may have suffered
|
||||
from the Software as a result of a fault on the part of the relevant
|
||||
Licensor, subject to providing evidence thereof.
|
||||
|
||||
8.2 The Licensor's liability is limited to the commitments made under
|
||||
this Agreement and shall not be incurred as a result of in particular:
|
||||
(i) loss due the Licensee's total or partial failure to fulfill its
|
||||
obligations, (ii) direct or consequential loss that is suffered by the
|
||||
Licensee due to the use or performance of the Software, and (iii) more
|
||||
generally, any consequential loss. In particular the Parties expressly
|
||||
agree that any or all pecuniary or business loss (i.e. loss of data,
|
||||
loss of profits, operating loss, loss of customers or orders,
|
||||
opportunity cost, any disturbance to business activities) or any or all
|
||||
legal proceedings instituted against the Licensee by a third party,
|
||||
shall constitute consequential loss and shall not provide entitlement to
|
||||
any or all compensation from the Licensor.
|
||||
|
||||
|
||||
Article 9 - WARRANTY
|
||||
|
||||
9.1 The Licensee acknowledges that the scientific and technical
|
||||
state-of-the-art when the Software was distributed did not enable all
|
||||
possible uses to be tested and verified, nor for the presence of
|
||||
possible defects to be detected. In this respect, the Licensee's
|
||||
attention has been drawn to the risks associated with loading, using,
|
||||
modifying and/or developing and reproducing the Software which are
|
||||
reserved for experienced users.
|
||||
|
||||
The Licensee shall be responsible for verifying, by any or all means,
|
||||
the suitability of the product for its requirements, its good working
|
||||
order, and for ensuring that it shall not cause damage to either persons
|
||||
or properties.
|
||||
|
||||
9.2 The Licensor hereby represents, in good faith, that it is entitled
|
||||
to grant all the rights over the Software (including in particular the
|
||||
rights set forth in Article 5).
|
||||
|
||||
9.3 The Licensee acknowledges that the Software is supplied "as is" by
|
||||
the Licensor without any other express or tacit warranty, other than
|
||||
that provided for in Article 9.2 and, in particular, without any warranty
|
||||
as to its commercial value, its secured, safe, innovative or relevant
|
||||
nature.
|
||||
|
||||
Specifically, the Licensor does not warrant that the Software is free
|
||||
from any error, that it will operate without interruption, that it will
|
||||
be compatible with the Licensee's own equipment and software
|
||||
configuration, nor that it will meet the Licensee's requirements.
|
||||
|
||||
9.4 The Licensor does not either expressly or tacitly warrant that the
|
||||
Software does not infringe any third party intellectual property right
|
||||
relating to a patent, software or any other property right. Therefore,
|
||||
the Licensor disclaims any and all liability towards the Licensee
|
||||
arising out of any or all proceedings for infringement that may be
|
||||
instituted in respect of the use, modification and redistribution of the
|
||||
Software. Nevertheless, should such proceedings be instituted against
|
||||
the Licensee, the Licensor shall provide it with technical and legal
|
||||
assistance for its defense. Such technical and legal assistance shall be
|
||||
decided on a case-by-case basis between the relevant Licensor and the
|
||||
Licensee pursuant to a memorandum of understanding. The Licensor
|
||||
disclaims any and all liability as regards the Licensee's use of the
|
||||
name of the Software. No warranty is given as regards the existence of
|
||||
prior rights over the name of the Software or as regards the existence
|
||||
of a trademark.
|
||||
|
||||
|
||||
Article 10 - TERMINATION
|
||||
|
||||
10.1 In the event of a breach by the Licensee of its obligations
|
||||
hereunder, the Licensor may automatically terminate this Agreement
|
||||
thirty (30) days after notice has been sent to the Licensee and has
|
||||
remained ineffective.
|
||||
|
||||
10.2 A Licensee whose Agreement is terminated shall no longer be
|
||||
authorized to use, modify or distribute the Software. However, any
|
||||
licenses that it may have granted prior to termination of the Agreement
|
||||
shall remain valid subject to their having been granted in compliance
|
||||
with the terms and conditions hereof.
|
||||
|
||||
|
||||
Article 11 - MISCELLANEOUS
|
||||
|
||||
|
||||
11.1 EXCUSABLE EVENTS
|
||||
|
||||
Neither Party shall be liable for any or all delay, or failure to
|
||||
perform the Agreement, that may be attributable to an event of force
|
||||
majeure, an act of God or an outside cause, such as defective
|
||||
functioning or interruptions of the electricity or telecommunications
|
||||
networks, network paralysis following a virus attack, intervention by
|
||||
government authorities, natural disasters, water damage, earthquakes,
|
||||
fire, explosions, strikes and labor unrest, war, etc.
|
||||
|
||||
11.2 Any failure by either Party, on one or more occasions, to invoke
|
||||
one or more of the provisions hereof, shall under no circumstances be
|
||||
interpreted as being a waiver by the interested Party of its right to
|
||||
invoke said provision(s) subsequently.
|
||||
|
||||
11.3 The Agreement cancels and replaces any or all previous agreements,
|
||||
whether written or oral, between the Parties and having the same
|
||||
purpose, and constitutes the entirety of the agreement between said
|
||||
Parties concerning said purpose. No supplement or modification to the
|
||||
terms and conditions hereof shall be effective as between the Parties
|
||||
unless it is made in writing and signed by their duly authorized
|
||||
representatives.
|
||||
|
||||
11.4 In the event that one or more of the provisions hereof were to
|
||||
conflict with a current or future applicable act or legislative text,
|
||||
said act or legislative text shall prevail, and the Parties shall make
|
||||
the necessary amendments so as to comply with said act or legislative
|
||||
text. All other provisions shall remain effective. Similarly, invalidity
|
||||
of a provision of the Agreement, for any reason whatsoever, shall not
|
||||
cause the Agreement as a whole to be invalid.
|
||||
|
||||
|
||||
11.5 LANGUAGE
|
||||
|
||||
The Agreement is drafted in both French and English and both versions
|
||||
are deemed authentic.
|
||||
|
||||
|
||||
Article 12 - NEW VERSIONS OF THE AGREEMENT
|
||||
|
||||
12.1 Any person is authorized to duplicate and distribute copies of this
|
||||
Agreement.
|
||||
|
||||
12.2 So as to ensure coherence, the wording of this Agreement is
|
||||
protected and may only be modified by the authors of the License, who
|
||||
reserve the right to periodically publish updates or new versions of the
|
||||
Agreement, each with a separate number. These subsequent versions may
|
||||
address new issues encountered by Free Software.
|
||||
|
||||
12.3 Any Software distributed under a given version of the Agreement may
|
||||
only be subsequently distributed under the same version of the Agreement
|
||||
or a subsequent version.
|
||||
|
||||
|
||||
Article 13 - GOVERNING LAW AND JURISDICTION
|
||||
|
||||
13.1 The Agreement is governed by French law. The Parties agree to
|
||||
endeavor to seek an amicable solution to any disagreements or disputes
|
||||
that may arise during the performance of the Agreement.
|
||||
|
||||
13.2 Failing an amicable solution within two (2) months as from their
|
||||
occurrence, and unless emergency proceedings are necessary, the
|
||||
disagreements or disputes shall be referred to the Paris Courts having
|
||||
jurisdiction, by the more diligent Party.
|
||||
|
||||
|
||||
Version 1.0 dated 2006-09-05.
|
||||
519
Resources/CeCILL_V2.1-en.txt
Normal file
519
Resources/CeCILL_V2.1-en.txt
Normal file
@@ -0,0 +1,519 @@
|
||||
|
||||
CeCILL FREE SOFTWARE LICENSE AGREEMENT
|
||||
|
||||
Version 2.1 dated 2013-06-21
|
||||
|
||||
|
||||
Notice
|
||||
|
||||
This Agreement is a Free Software license agreement that is the result
|
||||
of discussions between its authors in order to ensure compliance with
|
||||
the two main principles guiding its drafting:
|
||||
|
||||
* firstly, compliance with the principles governing the distribution
|
||||
of Free Software: access to source code, broad rights granted to users,
|
||||
* secondly, the election of a governing law, French law, with which it
|
||||
is conformant, both as regards the law of torts and intellectual
|
||||
property law, and the protection that it offers to both authors and
|
||||
holders of the economic rights over software.
|
||||
|
||||
The authors of the CeCILL (for Ce[a] C[nrs] I[nria] L[ogiciel] L[ibre])
|
||||
license are:
|
||||
|
||||
Commissariat à l'énergie atomique et aux énergies alternatives - CEA, a
|
||||
public scientific, technical and industrial research establishment,
|
||||
having its principal place of business at 25 rue Leblanc, immeuble Le
|
||||
Ponant D, 75015 Paris, France.
|
||||
|
||||
Centre National de la Recherche Scientifique - CNRS, a public scientific
|
||||
and technological establishment, having its principal place of business
|
||||
at 3 rue Michel-Ange, 75794 Paris cedex 16, France.
|
||||
|
||||
Institut National de Recherche en Informatique et en Automatique -
|
||||
Inria, a public scientific and technological establishment, having its
|
||||
principal place of business at Domaine de Voluceau, Rocquencourt, BP
|
||||
105, 78153 Le Chesnay cedex, France.
|
||||
|
||||
|
||||
Preamble
|
||||
|
||||
The purpose of this Free Software license agreement is to grant users
|
||||
the right to modify and redistribute the software governed by this
|
||||
license within the framework of an open source distribution model.
|
||||
|
||||
The exercising of this right is conditional upon certain obligations for
|
||||
users so as to preserve this status for all subsequent redistributions.
|
||||
|
||||
In consideration of access to the source code and the rights to copy,
|
||||
modify and redistribute granted by the license, users are provided only
|
||||
with a limited warranty and the software's author, the holder of the
|
||||
economic rights, and the successive licensors only have limited liability.
|
||||
|
||||
In this respect, the risks associated with loading, using, modifying
|
||||
and/or developing or reproducing the software by the user are brought to
|
||||
the user's attention, given its Free Software status, which may make it
|
||||
complicated to use, with the result that its use is reserved for
|
||||
developers and experienced professionals having in-depth computer
|
||||
knowledge. Users are therefore encouraged to load and test the
|
||||
suitability of the software as regards their requirements in conditions
|
||||
enabling the security of their systems and/or data to be ensured and,
|
||||
more generally, to use and operate it in the same conditions of
|
||||
security. This Agreement may be freely reproduced and published,
|
||||
provided it is not altered, and that no provisions are either added or
|
||||
removed herefrom.
|
||||
|
||||
This Agreement may apply to any or all software for which the holder of
|
||||
the economic rights decides to submit the use thereof to its provisions.
|
||||
|
||||
Frequently asked questions can be found on the official website of the
|
||||
CeCILL licenses family (http://www.cecill.info/index.en.html) for any
|
||||
necessary clarification.
|
||||
|
||||
|
||||
Article 1 - DEFINITIONS
|
||||
|
||||
For the purpose of this Agreement, when the following expressions
|
||||
commence with a capital letter, they shall have the following meaning:
|
||||
|
||||
Agreement: means this license agreement, and its possible subsequent
|
||||
versions and annexes.
|
||||
|
||||
Software: means the software in its Object Code and/or Source Code form
|
||||
and, where applicable, its documentation, "as is" when the Licensee
|
||||
accepts the Agreement.
|
||||
|
||||
Initial Software: means the Software in its Source Code and possibly its
|
||||
Object Code form and, where applicable, its documentation, "as is" when
|
||||
it is first distributed under the terms and conditions of the Agreement.
|
||||
|
||||
Modified Software: means the Software modified by at least one
|
||||
Contribution.
|
||||
|
||||
Source Code: means all the Software's instructions and program lines to
|
||||
which access is required so as to modify the Software.
|
||||
|
||||
Object Code: means the binary files originating from the compilation of
|
||||
the Source Code.
|
||||
|
||||
Holder: means the holder(s) of the economic rights over the Initial
|
||||
Software.
|
||||
|
||||
Licensee: means the Software user(s) having accepted the Agreement.
|
||||
|
||||
Contributor: means a Licensee having made at least one Contribution.
|
||||
|
||||
Licensor: means the Holder, or any other individual or legal entity, who
|
||||
distributes the Software under the Agreement.
|
||||
|
||||
Contribution: means any or all modifications, corrections, translations,
|
||||
adaptations and/or new functions integrated into the Software by any or
|
||||
all Contributors, as well as any or all Internal Modules.
|
||||
|
||||
Module: means a set of sources files including their documentation that
|
||||
enables supplementary functions or services in addition to those offered
|
||||
by the Software.
|
||||
|
||||
External Module: means any or all Modules, not derived from the
|
||||
Software, so that this Module and the Software run in separate address
|
||||
spaces, with one calling the other when they are run.
|
||||
|
||||
Internal Module: means any or all Module, connected to the Software so
|
||||
that they both execute in the same address space.
|
||||
|
||||
GNU GPL: means the GNU General Public License version 2 or any
|
||||
subsequent version, as published by the Free Software Foundation Inc.
|
||||
|
||||
GNU Affero GPL: means the GNU Affero General Public License version 3 or
|
||||
any subsequent version, as published by the Free Software Foundation Inc.
|
||||
|
||||
EUPL: means the European Union Public License version 1.1 or any
|
||||
subsequent version, as published by the European Commission.
|
||||
|
||||
Parties: mean both the Licensee and the Licensor.
|
||||
|
||||
These expressions may be used both in singular and plural form.
|
||||
|
||||
|
||||
Article 2 - PURPOSE
|
||||
|
||||
The purpose of the Agreement is the grant by the Licensor to the
|
||||
Licensee of a non-exclusive, transferable and worldwide license for the
|
||||
Software as set forth in Article 5 <#scope> hereinafter for the whole
|
||||
term of the protection granted by the rights over said Software.
|
||||
|
||||
|
||||
Article 3 - ACCEPTANCE
|
||||
|
||||
3.1 The Licensee shall be deemed as having accepted the terms and
|
||||
conditions of this Agreement upon the occurrence of the first of the
|
||||
following events:
|
||||
|
||||
* (i) loading the Software by any or all means, notably, by
|
||||
downloading from a remote server, or by loading from a physical medium;
|
||||
* (ii) the first time the Licensee exercises any of the rights granted
|
||||
hereunder.
|
||||
|
||||
3.2 One copy of the Agreement, containing a notice relating to the
|
||||
characteristics of the Software, to the limited warranty, and to the
|
||||
fact that its use is restricted to experienced users has been provided
|
||||
to the Licensee prior to its acceptance as set forth in Article 3.1
|
||||
<#accepting> hereinabove, and the Licensee hereby acknowledges that it
|
||||
has read and understood it.
|
||||
|
||||
|
||||
Article 4 - EFFECTIVE DATE AND TERM
|
||||
|
||||
|
||||
4.1 EFFECTIVE DATE
|
||||
|
||||
The Agreement shall become effective on the date when it is accepted by
|
||||
the Licensee as set forth in Article 3.1 <#accepting>.
|
||||
|
||||
|
||||
4.2 TERM
|
||||
|
||||
The Agreement shall remain in force for the entire legal term of
|
||||
protection of the economic rights over the Software.
|
||||
|
||||
|
||||
Article 5 - SCOPE OF RIGHTS GRANTED
|
||||
|
||||
The Licensor hereby grants to the Licensee, who accepts, the following
|
||||
rights over the Software for any or all use, and for the term of the
|
||||
Agreement, on the basis of the terms and conditions set forth hereinafter.
|
||||
|
||||
Besides, if the Licensor owns or comes to own one or more patents
|
||||
protecting all or part of the functions of the Software or of its
|
||||
components, the Licensor undertakes not to enforce the rights granted by
|
||||
these patents against successive Licensees using, exploiting or
|
||||
modifying the Software. If these patents are transferred, the Licensor
|
||||
undertakes to have the transferees subscribe to the obligations set
|
||||
forth in this paragraph.
|
||||
|
||||
|
||||
5.1 RIGHT OF USE
|
||||
|
||||
The Licensee is authorized to use the Software, without any limitation
|
||||
as to its fields of application, with it being hereinafter specified
|
||||
that this comprises:
|
||||
|
||||
1. permanent or temporary reproduction of all or part of the Software
|
||||
by any or all means and in any or all form.
|
||||
|
||||
2. loading, displaying, running, or storing the Software on any or all
|
||||
medium.
|
||||
|
||||
3. entitlement to observe, study or test its operation so as to
|
||||
determine the ideas and principles behind any or all constituent
|
||||
elements of said Software. This shall apply when the Licensee
|
||||
carries out any or all loading, displaying, running, transmission or
|
||||
storage operation as regards the Software, that it is entitled to
|
||||
carry out hereunder.
|
||||
|
||||
|
||||
5.2 ENTITLEMENT TO MAKE CONTRIBUTIONS
|
||||
|
||||
The right to make Contributions includes the right to translate, adapt,
|
||||
arrange, or make any or all modifications to the Software, and the right
|
||||
to reproduce the resulting software.
|
||||
|
||||
The Licensee is authorized to make any or all Contributions to the
|
||||
Software provided that it includes an explicit notice that it is the
|
||||
author of said Contribution and indicates the date of the creation thereof.
|
||||
|
||||
|
||||
5.3 RIGHT OF DISTRIBUTION
|
||||
|
||||
In particular, the right of distribution includes the right to publish,
|
||||
transmit and communicate the Software to the general public on any or
|
||||
all medium, and by any or all means, and the right to market, either in
|
||||
consideration of a fee, or free of charge, one or more copies of the
|
||||
Software by any means.
|
||||
|
||||
The Licensee is further authorized to distribute copies of the modified
|
||||
or unmodified Software to third parties according to the terms and
|
||||
conditions set forth hereinafter.
|
||||
|
||||
|
||||
5.3.1 DISTRIBUTION OF SOFTWARE WITHOUT MODIFICATION
|
||||
|
||||
The Licensee is authorized to distribute true copies of the Software in
|
||||
Source Code or Object Code form, provided that said distribution
|
||||
complies with all the provisions of the Agreement and is accompanied by:
|
||||
|
||||
1. a copy of the Agreement,
|
||||
|
||||
2. a notice relating to the limitation of both the Licensor's warranty
|
||||
and liability as set forth in Articles 8 and 9,
|
||||
|
||||
and that, in the event that only the Object Code of the Software is
|
||||
redistributed, the Licensee allows effective access to the full Source
|
||||
Code of the Software for a period of at least three years from the
|
||||
distribution of the Software, it being understood that the additional
|
||||
acquisition cost of the Source Code shall not exceed the cost of the
|
||||
data transfer.
|
||||
|
||||
|
||||
5.3.2 DISTRIBUTION OF MODIFIED SOFTWARE
|
||||
|
||||
When the Licensee makes a Contribution to the Software, the terms and
|
||||
conditions for the distribution of the resulting Modified Software
|
||||
become subject to all the provisions of this Agreement.
|
||||
|
||||
The Licensee is authorized to distribute the Modified Software, in
|
||||
source code or object code form, provided that said distribution
|
||||
complies with all the provisions of the Agreement and is accompanied by:
|
||||
|
||||
1. a copy of the Agreement,
|
||||
|
||||
2. a notice relating to the limitation of both the Licensor's warranty
|
||||
and liability as set forth in Articles 8 and 9,
|
||||
|
||||
and, in the event that only the object code of the Modified Software is
|
||||
redistributed,
|
||||
|
||||
3. a note stating the conditions of effective access to the full source
|
||||
code of the Modified Software for a period of at least three years
|
||||
from the distribution of the Modified Software, it being understood
|
||||
that the additional acquisition cost of the source code shall not
|
||||
exceed the cost of the data transfer.
|
||||
|
||||
|
||||
5.3.3 DISTRIBUTION OF EXTERNAL MODULES
|
||||
|
||||
When the Licensee has developed an External Module, the terms and
|
||||
conditions of this Agreement do not apply to said External Module, that
|
||||
may be distributed under a separate license agreement.
|
||||
|
||||
|
||||
5.3.4 COMPATIBILITY WITH OTHER LICENSES
|
||||
|
||||
The Licensee can include a code that is subject to the provisions of one
|
||||
of the versions of the GNU GPL, GNU Affero GPL and/or EUPL in the
|
||||
Modified or unmodified Software, and distribute that entire code under
|
||||
the terms of the same version of the GNU GPL, GNU Affero GPL and/or EUPL.
|
||||
|
||||
The Licensee can include the Modified or unmodified Software in a code
|
||||
that is subject to the provisions of one of the versions of the GNU GPL,
|
||||
GNU Affero GPL and/or EUPL and distribute that entire code under the
|
||||
terms of the same version of the GNU GPL, GNU Affero GPL and/or EUPL.
|
||||
|
||||
|
||||
Article 6 - INTELLECTUAL PROPERTY
|
||||
|
||||
|
||||
6.1 OVER THE INITIAL SOFTWARE
|
||||
|
||||
The Holder owns the economic rights over the Initial Software. Any or
|
||||
all use of the Initial Software is subject to compliance with the terms
|
||||
and conditions under which the Holder has elected to distribute its work
|
||||
and no one shall be entitled to modify the terms and conditions for the
|
||||
distribution of said Initial Software.
|
||||
|
||||
The Holder undertakes that the Initial Software will remain ruled at
|
||||
least by this Agreement, for the duration set forth in Article 4.2 <#term>.
|
||||
|
||||
|
||||
6.2 OVER THE CONTRIBUTIONS
|
||||
|
||||
The Licensee who develops a Contribution is the owner of the
|
||||
intellectual property rights over this Contribution as defined by
|
||||
applicable law.
|
||||
|
||||
|
||||
6.3 OVER THE EXTERNAL MODULES
|
||||
|
||||
The Licensee who develops an External Module is the owner of the
|
||||
intellectual property rights over this External Module as defined by
|
||||
applicable law and is free to choose the type of agreement that shall
|
||||
govern its distribution.
|
||||
|
||||
|
||||
6.4 JOINT PROVISIONS
|
||||
|
||||
The Licensee expressly undertakes:
|
||||
|
||||
1. not to remove, or modify, in any manner, the intellectual property
|
||||
notices attached to the Software;
|
||||
|
||||
2. to reproduce said notices, in an identical manner, in the copies of
|
||||
the Software modified or not.
|
||||
|
||||
The Licensee undertakes not to directly or indirectly infringe the
|
||||
intellectual property rights on the Software of the Holder and/or
|
||||
Contributors, and to take, where applicable, vis-à-vis its staff, any
|
||||
and all measures required to ensure respect of said intellectual
|
||||
property rights of the Holder and/or Contributors.
|
||||
|
||||
|
||||
Article 7 - RELATED SERVICES
|
||||
|
||||
7.1 Under no circumstances shall the Agreement oblige the Licensor to
|
||||
provide technical assistance or maintenance services for the Software.
|
||||
|
||||
However, the Licensor is entitled to offer this type of services. The
|
||||
terms and conditions of such technical assistance, and/or such
|
||||
maintenance, shall be set forth in a separate instrument. Only the
|
||||
Licensor offering said maintenance and/or technical assistance services
|
||||
shall incur liability therefor.
|
||||
|
||||
7.2 Similarly, any Licensor is entitled to offer to its licensees, under
|
||||
its sole responsibility, a warranty, that shall only be binding upon
|
||||
itself, for the redistribution of the Software and/or the Modified
|
||||
Software, under terms and conditions that it is free to decide. Said
|
||||
warranty, and the financial terms and conditions of its application,
|
||||
shall be subject of a separate instrument executed between the Licensor
|
||||
and the Licensee.
|
||||
|
||||
|
||||
Article 8 - LIABILITY
|
||||
|
||||
8.1 Subject to the provisions of Article 8.2, the Licensee shall be
|
||||
entitled to claim compensation for any direct loss it may have suffered
|
||||
from the Software as a result of a fault on the part of the relevant
|
||||
Licensor, subject to providing evidence thereof.
|
||||
|
||||
8.2 The Licensor's liability is limited to the commitments made under
|
||||
this Agreement and shall not be incurred as a result of in particular:
|
||||
(i) loss due the Licensee's total or partial failure to fulfill its
|
||||
obligations, (ii) direct or consequential loss that is suffered by the
|
||||
Licensee due to the use or performance of the Software, and (iii) more
|
||||
generally, any consequential loss. In particular the Parties expressly
|
||||
agree that any or all pecuniary or business loss (i.e. loss of data,
|
||||
loss of profits, operating loss, loss of customers or orders,
|
||||
opportunity cost, any disturbance to business activities) or any or all
|
||||
legal proceedings instituted against the Licensee by a third party,
|
||||
shall constitute consequential loss and shall not provide entitlement to
|
||||
any or all compensation from the Licensor.
|
||||
|
||||
|
||||
Article 9 - WARRANTY
|
||||
|
||||
9.1 The Licensee acknowledges that the scientific and technical
|
||||
state-of-the-art when the Software was distributed did not enable all
|
||||
possible uses to be tested and verified, nor for the presence of
|
||||
possible defects to be detected. In this respect, the Licensee's
|
||||
attention has been drawn to the risks associated with loading, using,
|
||||
modifying and/or developing and reproducing the Software which are
|
||||
reserved for experienced users.
|
||||
|
||||
The Licensee shall be responsible for verifying, by any or all means,
|
||||
the suitability of the product for its requirements, its good working
|
||||
order, and for ensuring that it shall not cause damage to either persons
|
||||
or properties.
|
||||
|
||||
9.2 The Licensor hereby represents, in good faith, that it is entitled
|
||||
to grant all the rights over the Software (including in particular the
|
||||
rights set forth in Article 5 <#scope>).
|
||||
|
||||
9.3 The Licensee acknowledges that the Software is supplied "as is" by
|
||||
the Licensor without any other express or tacit warranty, other than
|
||||
that provided for in Article 9.2 <#good-faith> and, in particular,
|
||||
without any warranty as to its commercial value, its secured, safe,
|
||||
innovative or relevant nature.
|
||||
|
||||
Specifically, the Licensor does not warrant that the Software is free
|
||||
from any error, that it will operate without interruption, that it will
|
||||
be compatible with the Licensee's own equipment and software
|
||||
configuration, nor that it will meet the Licensee's requirements.
|
||||
|
||||
9.4 The Licensor does not either expressly or tacitly warrant that the
|
||||
Software does not infringe any third party intellectual property right
|
||||
relating to a patent, software or any other property right. Therefore,
|
||||
the Licensor disclaims any and all liability towards the Licensee
|
||||
arising out of any or all proceedings for infringement that may be
|
||||
instituted in respect of the use, modification and redistribution of the
|
||||
Software. Nevertheless, should such proceedings be instituted against
|
||||
the Licensee, the Licensor shall provide it with technical and legal
|
||||
expertise for its defense. Such technical and legal expertise shall be
|
||||
decided on a case-by-case basis between the relevant Licensor and the
|
||||
Licensee pursuant to a memorandum of understanding. The Licensor
|
||||
disclaims any and all liability as regards the Licensee's use of the
|
||||
name of the Software. No warranty is given as regards the existence of
|
||||
prior rights over the name of the Software or as regards the existence
|
||||
of a trademark.
|
||||
|
||||
|
||||
Article 10 - TERMINATION
|
||||
|
||||
10.1 In the event of a breach by the Licensee of its obligations
|
||||
hereunder, the Licensor may automatically terminate this Agreement
|
||||
thirty (30) days after notice has been sent to the Licensee and has
|
||||
remained ineffective.
|
||||
|
||||
10.2 A Licensee whose Agreement is terminated shall no longer be
|
||||
authorized to use, modify or distribute the Software. However, any
|
||||
licenses that it may have granted prior to termination of the Agreement
|
||||
shall remain valid subject to their having been granted in compliance
|
||||
with the terms and conditions hereof.
|
||||
|
||||
|
||||
Article 11 - MISCELLANEOUS
|
||||
|
||||
|
||||
11.1 EXCUSABLE EVENTS
|
||||
|
||||
Neither Party shall be liable for any or all delay, or failure to
|
||||
perform the Agreement, that may be attributable to an event of force
|
||||
majeure, an act of God or an outside cause, such as defective
|
||||
functioning or interruptions of the electricity or telecommunications
|
||||
networks, network paralysis following a virus attack, intervention by
|
||||
government authorities, natural disasters, water damage, earthquakes,
|
||||
fire, explosions, strikes and labor unrest, war, etc.
|
||||
|
||||
11.2 Any failure by either Party, on one or more occasions, to invoke
|
||||
one or more of the provisions hereof, shall under no circumstances be
|
||||
interpreted as being a waiver by the interested Party of its right to
|
||||
invoke said provision(s) subsequently.
|
||||
|
||||
11.3 The Agreement cancels and replaces any or all previous agreements,
|
||||
whether written or oral, between the Parties and having the same
|
||||
purpose, and constitutes the entirety of the agreement between said
|
||||
Parties concerning said purpose. No supplement or modification to the
|
||||
terms and conditions hereof shall be effective as between the Parties
|
||||
unless it is made in writing and signed by their duly authorized
|
||||
representatives.
|
||||
|
||||
11.4 In the event that one or more of the provisions hereof were to
|
||||
conflict with a current or future applicable act or legislative text,
|
||||
said act or legislative text shall prevail, and the Parties shall make
|
||||
the necessary amendments so as to comply with said act or legislative
|
||||
text. All other provisions shall remain effective. Similarly, invalidity
|
||||
of a provision of the Agreement, for any reason whatsoever, shall not
|
||||
cause the Agreement as a whole to be invalid.
|
||||
|
||||
|
||||
11.5 LANGUAGE
|
||||
|
||||
The Agreement is drafted in both French and English and both versions
|
||||
are deemed authentic.
|
||||
|
||||
|
||||
Article 12 - NEW VERSIONS OF THE AGREEMENT
|
||||
|
||||
12.1 Any person is authorized to duplicate and distribute copies of this
|
||||
Agreement.
|
||||
|
||||
12.2 So as to ensure coherence, the wording of this Agreement is
|
||||
protected and may only be modified by the authors of the License, who
|
||||
reserve the right to periodically publish updates or new versions of the
|
||||
Agreement, each with a separate number. These subsequent versions may
|
||||
address new issues encountered by Free Software.
|
||||
|
||||
12.3 Any Software distributed under a given version of the Agreement may
|
||||
only be subsequently distributed under the same version of the Agreement
|
||||
or a subsequent version, subject to the provisions of Article 5.3.4
|
||||
<#compatibility>.
|
||||
|
||||
|
||||
Article 13 - GOVERNING LAW AND JURISDICTION
|
||||
|
||||
13.1 The Agreement is governed by French law. The Parties agree to
|
||||
endeavor to seek an amicable solution to any disagreements or disputes
|
||||
that may arise during the performance of the Agreement.
|
||||
|
||||
13.2 Failing an amicable solution within two (2) months as from their
|
||||
occurrence, and unless emergency proceedings are necessary, the
|
||||
disagreements or disputes shall be referred to the Paris Courts having
|
||||
jurisdiction, by the more diligent Party.
|
||||
|
||||
29
Resources/InsaneWidget/CMake/FindLibInsane.cmake
Normal file
29
Resources/InsaneWidget/CMake/FindLibInsane.cmake
Normal file
@@ -0,0 +1,29 @@
|
||||
#
|
||||
|
||||
# - Try to find LibInsane
|
||||
# Once done this will define
|
||||
# LIBINSANE_FOUND - System has LibInsane
|
||||
# LIBINSANE_INCLUDE_DIRS - The LibInsane include directories
|
||||
# LIBINSANE_LIBRARIES - The libraries needed to use LibInsane
|
||||
# LIBINSANE_DEFINITIONS - Compiler switches required for using LibInsane
|
||||
|
||||
find_package(PkgConfig)
|
||||
pkg_check_modules(PC_LIBINSANE QUIET libinsane.pc)
|
||||
set(LIBINSANE_DEFINITIONS ${PC_LIBINSANE_CFLAGS_OTHER})
|
||||
|
||||
find_path(LIBINSANE_INCLUDE_DIR libinsane/sane.h
|
||||
HINTS ${PC_LIBINSANE_INCLUDEDIR} ${PC_LIBINSANE_INCLUDE_DIRS}
|
||||
PATH_SUFFIXES libinsane )
|
||||
|
||||
find_library(LIBINSANE_LIBRARY NAMES libinsane.so
|
||||
HINTS ${PC_LIBINSANE_LIBDIR} ${PC_LIBINSANE_LIBRARY_DIRS} )
|
||||
|
||||
set(LIBINSANE_LIBRARIES ${LIBINSANE_LIBRARY})
|
||||
set(LIBINSANE_INCLUDE_DIRS ${LIBINSANE_INCLUDE_DIR} )
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
# handle the QUIETLY and REQUIRED arguments and set LIBINSANE_FOUND to TRUE
|
||||
# if all listed variables are TRUE
|
||||
find_package_handle_standard_args(LibInsane DEFAULT_MSG
|
||||
LIBINSANE_LIBRARY LIBINSANE_INCLUDE_DIR)
|
||||
mark_as_advanced(LIBINSANE_INCLUDE_DIR LIBINSANE_LIBRARY )
|
||||
23
Resources/InsaneWidget/CMake/FindPaper.cmake
Normal file
23
Resources/InsaneWidget/CMake/FindPaper.cmake
Normal file
@@ -0,0 +1,23 @@
|
||||
# - Try to find Paper
|
||||
# Once done this will define
|
||||
# PAPER_FOUND - System has Paper
|
||||
# PAPER_INCLUDE_DIRS - The Paper include directories
|
||||
# PAPER_LIBRARIES - The libraries needed to use Paper
|
||||
# PAPER_DEFINITIONS - Compiler switches required for using Paper
|
||||
|
||||
find_path(PAPER_INCLUDE_DIR paper.h
|
||||
HINTS ${PC_PAPER_INCLUDEDIR} ${PC_PAPER_INCLUDE_DIRS}
|
||||
PATH_SUFFIXES paper )
|
||||
|
||||
find_library(PAPER_LIBRARY NAMES libpaper.so
|
||||
HINTS ${PC_PAPER_LIBDIR} ${PC_PAPER_LIBRARY_DIRS} )
|
||||
|
||||
set(PAPER_LIBRARIES ${PAPER_LIBRARY} )
|
||||
set(PAPER_INCLUDE_DIRS ${PAPER_INCLUDE_DIR} )
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
# handle the QUIETLY and REQUIRED arguments and set PAPER_FOUND to TRUE
|
||||
# if all listed variables are TRUE
|
||||
find_package_handle_standard_args(Paper DEFAULT_MSG
|
||||
PAPER_LIBRARY PAPER_INCLUDE_DIR)
|
||||
mark_as_advanced(PAPER_INCLUDE_DIR PAPER_LIBRARY )
|
||||
27
Resources/InsaneWidget/CMake/FindPoDoFo.cmake
Normal file
27
Resources/InsaneWidget/CMake/FindPoDoFo.cmake
Normal file
@@ -0,0 +1,27 @@
|
||||
# - Try to find PoDoFo
|
||||
# Once done this will define
|
||||
# PODOFO_FOUND - System has PoDoFo
|
||||
# PODOFO_INCLUDE_DIRS - The PoDoFo include directories
|
||||
# PODOFO_LIBRARIES - The libraries needed to use PoDoFo
|
||||
# PODOFO_DEFINITIONS - Compiler switches required for using PoDoFo
|
||||
|
||||
find_package(PkgConfig)
|
||||
pkg_check_modules(PC_PODOFO QUIET libpodofo.pc)
|
||||
set(PODOFO_DEFINITIONS ${PC_PODOFO_CFLAGS_OTHER})
|
||||
|
||||
find_path(PODOFO_INCLUDE_DIR podofo/podofo.h
|
||||
HINTS ${PC_PODOFO_INCLUDEDIR} ${PC_PODOFO_INCLUDE_DIRS}
|
||||
PATH_SUFFIXES podofo )
|
||||
|
||||
find_library(PODOFO_LIBRARY NAMES libpodofo.so
|
||||
HINTS ${PC_PODOFO_LIBDIR} ${PC_PODOFO_LIBRARY_DIRS} )
|
||||
|
||||
set(PODOFO_LIBRARIES ${PODOFO_LIBRARY} )
|
||||
set(PODOFO_INCLUDE_DIRS ${PODOFO_INCLUDE_DIR} )
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
# handle the QUIETLY and REQUIRED arguments and set PODOFO_FOUND to TRUE
|
||||
# if all listed variables are TRUE
|
||||
find_package_handle_standard_args(PoDoFo DEFAULT_MSG
|
||||
PODOFO_LIBRARY PODOFO_INCLUDE_DIR)
|
||||
mark_as_advanced(PODOFO_INCLUDE_DIR PODOFO_LIBRARY )
|
||||
33
Resources/InsaneWidget/CMakeLists.txt
Normal file
33
Resources/InsaneWidget/CMakeLists.txt
Normal file
@@ -0,0 +1,33 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
project(InsaneWidget)
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/CMake")
|
||||
|
||||
find_package(wxWidgets COMPONENTS base core CONFIG REQUIRED)
|
||||
find_package(LibInsane REQUIRED)
|
||||
find_package(PoDoFo REQUIRED)
|
||||
find_package(Paper REQUIRED)
|
||||
|
||||
|
||||
include_directories(${CMAKE_CURRENT_LIST_DIR}
|
||||
${CMAKE_CURRENT_LIST_DIR}/UI
|
||||
${CMAKE_CURRENT_LIST_DIR}/../Utilities)
|
||||
|
||||
add_library(insanewidget STATIC
|
||||
UI/InsaneWidget.cpp
|
||||
UI/ScannerWidget.cpp
|
||||
|
||||
Common.h
|
||||
XInsaneWidget.cpp
|
||||
XScannerWidget.cpp
|
||||
InsaneWorker.cpp
|
||||
PixelToImageWriter.cpp
|
||||
PixelToPdfWriter.cpp)
|
||||
|
||||
target_link_libraries(insanewidget minutils
|
||||
${wxWidgets_LIBRARIES}
|
||||
${LIBINSANE_LIBRARIES}
|
||||
${PODOFO_LIBRARIES}
|
||||
${NETPBM_LIBRARIES}
|
||||
${PAPER_LIBRARIES})
|
||||
30
Resources/InsaneWidget/Common.h
Normal file
30
Resources/InsaneWidget/Common.h
Normal file
@@ -0,0 +1,30 @@
|
||||
// /*
|
||||
// * File: Common.h
|
||||
// * Author: Saleem Edah-Tally - nmset@yandex.com
|
||||
// * License : CeCILL-C
|
||||
// * Copyright Saleem Edah-Tally - © 2025
|
||||
// *
|
||||
// * Created on 27 06 2025, 20:34
|
||||
// */
|
||||
|
||||
#ifndef COMMON_H
|
||||
#define COMMON_H
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
enum {PDF, PNG, JPEG, TIFF, PNM};
|
||||
typedef std::map <int, std::string> ExtensionsMap;
|
||||
|
||||
static ExtensionsMap Extensions;
|
||||
|
||||
static void UpdateExtensionsMap()
|
||||
{
|
||||
Extensions[PDF] = "pdf";
|
||||
Extensions[PNG] = "png";
|
||||
Extensions[JPEG] = "jpeg";
|
||||
Extensions[TIFF] = "tiff";
|
||||
Extensions[PNM] = "pnm";
|
||||
}
|
||||
|
||||
#endif // COMMON_H
|
||||
582
Resources/InsaneWidget/InsaneWorker.cpp
Normal file
582
Resources/InsaneWidget/InsaneWorker.cpp
Normal file
@@ -0,0 +1,582 @@
|
||||
/*
|
||||
* File: InsaneWorker.cpp
|
||||
* Author: Saleem Edah-Tally - nmset@yandex.com
|
||||
* License : CeCILL-C
|
||||
* Copyright Saleem Edah-Tally - © 2024
|
||||
*
|
||||
* Created on 14 02 2024, 13:00
|
||||
*/
|
||||
|
||||
#include "InsaneWorker.h"
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <paper.h>
|
||||
#include <libinsane/log.h>
|
||||
#include <libinsane/safebet.h>
|
||||
#include <libinsane/error.h>
|
||||
#include <libinsane/util.h>
|
||||
#include <libinsane/normalizers.h>
|
||||
#include <libinsane/constants.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
#define IERR(e) ("[" + to_string(e) + "] " + lis_strerror(e))
|
||||
static bool gs_cancelRequested = false;
|
||||
|
||||
InsaneWorker::InsaneWorker ( InsaneWorkerEvent * evh )
|
||||
{
|
||||
m_evh = evh;
|
||||
}
|
||||
|
||||
InsaneWorker::~InsaneWorker()
|
||||
{
|
||||
if (m_api)
|
||||
m_api->cleanup(m_api);
|
||||
}
|
||||
|
||||
bool InsaneWorker::Init()
|
||||
{
|
||||
// Terminate a previous one.
|
||||
if (m_api)
|
||||
{
|
||||
m_devices.clear();
|
||||
m_deviceId.clear();
|
||||
m_api->cleanup(m_api);
|
||||
m_sourceItem = nullptr;
|
||||
m_rootSourceItem = nullptr;
|
||||
}
|
||||
lis_error err;
|
||||
err = lis_safebet ( &m_api );
|
||||
if ( err )
|
||||
{
|
||||
if ( m_evh )
|
||||
{
|
||||
m_evh->OnInsaneError ( IERR(err) );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
lis_device_descriptor ** devices = nullptr; // nullptr terminated.
|
||||
err = m_api->list_devices ( m_api, LIS_DEVICE_LOCATIONS_LOCAL_ONLY, &devices ); // Gets network scanners though.
|
||||
if ( err )
|
||||
{
|
||||
m_evh->OnInsaneError ( IERR(err) );
|
||||
return false;
|
||||
}
|
||||
|
||||
uint numberOfDevices = 0;
|
||||
for ( uint i = 0; devices[i] != nullptr; i++ )
|
||||
{
|
||||
numberOfDevices++;
|
||||
}
|
||||
// Collect available descriptions for all devices.
|
||||
for ( uint i = 0; i < numberOfDevices; i++ )
|
||||
{
|
||||
DeviceDescriptor dd;
|
||||
lis_device_descriptor * descriptor = devices[i];
|
||||
dd.id = descriptor->dev_id;
|
||||
dd.model = descriptor->model;
|
||||
dd.type = descriptor->type;
|
||||
dd.vendor = descriptor->vendor;
|
||||
m_devices.push_back(dd);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Determine if a source item is a feeder.
|
||||
int InsaneWorker::IsADF(const std::string& deviceId, int sourceChildIndex)
|
||||
{
|
||||
if ( !m_api )
|
||||
{
|
||||
if ( m_evh )
|
||||
{
|
||||
m_evh->OnError ( "Insane api is NULL; has Init() been called?");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
lis_error err;
|
||||
lis_item * rootSourceItem = nullptr;
|
||||
err = m_api->get_device ( m_api, deviceId.c_str(), &rootSourceItem );
|
||||
if ( err )
|
||||
{
|
||||
if ( m_evh )
|
||||
m_evh->OnInsaneError ( IERR ( err ) );
|
||||
return false;
|
||||
}
|
||||
lis_item ** children = nullptr;
|
||||
err = rootSourceItem->get_children(rootSourceItem, &children);
|
||||
if ( err )
|
||||
{
|
||||
if ( m_evh )
|
||||
m_evh->OnInsaneError ( IERR ( err ) );
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool adf = (children[sourceChildIndex]->type == LIS_ITEM_ADF);
|
||||
rootSourceItem->close(rootSourceItem);
|
||||
return adf;
|
||||
}
|
||||
|
||||
// Ex: all supported resolutions.
|
||||
std::string InsaneWorker::GetOptionPossibleValues(const std::string& deviceId,
|
||||
const std::string& optionName, std::vector<std::string>& possible)
|
||||
{
|
||||
if ( !m_api )
|
||||
{
|
||||
if ( m_evh )
|
||||
{
|
||||
m_evh->OnError ( "Insane api is NULL; has Init() been called?");
|
||||
return "";
|
||||
}
|
||||
}
|
||||
lis_error err;
|
||||
lis_item * item = nullptr;
|
||||
err = m_api->get_device ( m_api, deviceId.c_str(), &item );
|
||||
if ( err )
|
||||
{
|
||||
if ( m_evh )
|
||||
m_evh->OnInsaneError ( IERR ( err ) );
|
||||
return "";
|
||||
}
|
||||
|
||||
lis_option_descriptor ** options = nullptr;
|
||||
err = item->get_options ( item, &options );
|
||||
if ( err )
|
||||
{
|
||||
if ( m_evh )
|
||||
m_evh->OnInsaneError ( IERR ( err ) );
|
||||
item->close(item);
|
||||
return "";
|
||||
}
|
||||
uint numberOfOptions = 0;
|
||||
for ( uint i = 0; options[i] != nullptr; i++ )
|
||||
{
|
||||
numberOfOptions++;
|
||||
}
|
||||
|
||||
std::string defaultValue;
|
||||
for ( uint i = 0; i < numberOfOptions; i++ )
|
||||
{
|
||||
lis_option_descriptor * optionDescriptor = options[i];
|
||||
const std::string name = optionDescriptor->name;
|
||||
if ( ToLower(name) != optionName )
|
||||
continue;
|
||||
union lis_value value;
|
||||
err = optionDescriptor->fn.get_value ( optionDescriptor, &value );
|
||||
if ( err )
|
||||
{
|
||||
if ( m_evh )
|
||||
m_evh->OnInsaneError ( IERR ( err ) );
|
||||
item->close(item);
|
||||
return "";
|
||||
}
|
||||
lis_value_type type = optionDescriptor->value.type;
|
||||
bool isString = false;
|
||||
switch ( type )
|
||||
{
|
||||
case LIS_TYPE_BOOL:
|
||||
defaultValue = std::to_string(( bool ) value.boolean);
|
||||
break;
|
||||
case LIS_TYPE_INTEGER:
|
||||
defaultValue = std::to_string(( long ) value.integer);
|
||||
break;
|
||||
case LIS_TYPE_DOUBLE:
|
||||
defaultValue = std::to_string(( double ) value.dbl);
|
||||
break;
|
||||
case LIS_TYPE_STRING:
|
||||
isString = true;
|
||||
defaultValue = value.string;
|
||||
break;
|
||||
case LIS_TYPE_IMAGE_FORMAT:
|
||||
defaultValue = "Unmanaged";
|
||||
break;
|
||||
default:
|
||||
defaultValue = "Unknown";
|
||||
break;
|
||||
}
|
||||
lis_value_list valueList = optionDescriptor->constraint.possible.list;
|
||||
int numberOfListItems = valueList.nb_values;
|
||||
if ( numberOfListItems )
|
||||
{
|
||||
for ( int j = 0; j < numberOfListItems; j++ )
|
||||
{
|
||||
if ( isString )
|
||||
possible.push_back( valueList.values[j].string );
|
||||
else
|
||||
possible.push_back( std::to_string ( valueList.values[j].integer ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
item->close(item);
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
// Open a source item and prepare for the next step, i.e, scanning.
|
||||
bool InsaneWorker::ConfigureDevice(const std::string& deviceId,
|
||||
const std::string& source, int sourceChildIndex,
|
||||
const std::string& mode, int resolution,
|
||||
const std::string& paperSize)
|
||||
{
|
||||
if ( !m_api )
|
||||
{
|
||||
if ( m_evh )
|
||||
{
|
||||
m_evh->OnError ( "Insane api is NULL; has Init() been called?");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
m_deviceId = deviceId;
|
||||
m_source = source;
|
||||
m_sourceChildIndex = (sourceChildIndex > -1) ? sourceChildIndex : 0;
|
||||
m_mode = mode;
|
||||
m_resolution = resolution;
|
||||
m_paperSize = paperSize;
|
||||
|
||||
lis_error err;
|
||||
|
||||
err = m_api->get_device ( m_api, m_deviceId.c_str(), &m_rootSourceItem );
|
||||
if ( err )
|
||||
{
|
||||
if ( m_evh )
|
||||
m_evh->OnInsaneError ( IERR ( err ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
lis_item ** children = nullptr;
|
||||
err = m_rootSourceItem->get_children(m_rootSourceItem, &children);
|
||||
if ( err )
|
||||
{
|
||||
if ( m_evh )
|
||||
m_evh->OnInsaneError ( IERR ( err ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
// Selecting a lis_item by the source index.
|
||||
// One child item is created by libinsane if there is no source: v4l.
|
||||
m_sourceItem = children[m_sourceChildIndex];
|
||||
if (!m_sourceItem)
|
||||
{
|
||||
if (m_evh)
|
||||
m_evh->OnError("Could not determine a device item");
|
||||
m_rootSourceItem->close(m_rootSourceItem);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Error status not checked; use defaults if failure.
|
||||
lis_set_option(m_sourceItem, OPT_NAME_MODE, mode.c_str());
|
||||
/*
|
||||
* Selecting a source on a child item that has been selected by a source index.
|
||||
* Sounds weird but needed.
|
||||
*/
|
||||
lis_set_option(m_sourceItem, OPT_NAME_SOURCE, source.c_str());
|
||||
lis_set_option(m_sourceItem, OPT_NAME_RESOLUTION, to_string(resolution).c_str());
|
||||
pair<double, double> br;
|
||||
if (GetBottomRight(br))
|
||||
{
|
||||
// For v4l, these do not get applied.
|
||||
lis_set_option(m_sourceItem, "br-x", to_string(br.first).c_str());
|
||||
lis_set_option(m_sourceItem, "br-y", to_string(br.second).c_str());
|
||||
}
|
||||
|
||||
// Don't close m_rootDeviceItem, it is prepared for ::Scan().
|
||||
return true;
|
||||
}
|
||||
|
||||
// Perform scanning: create raw data files.
|
||||
bool InsaneWorker::Scan(const std::string& dir, const std::string& basename,
|
||||
int startIndex, int padwidth, int increment)
|
||||
{
|
||||
if ( !m_api || !m_sourceItem )
|
||||
{
|
||||
if ( m_evh )
|
||||
{
|
||||
m_evh->OnError ( "Insane api or device item is NULL, cannot scan.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (dir.empty() || basename.empty() || startIndex < 0 || padwidth < 0 || (increment == 0))
|
||||
{
|
||||
if ( m_evh )
|
||||
{
|
||||
m_evh->OnError ( "Invalid input, cannot scan.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
auto makeFileName = [&] (int index)
|
||||
{
|
||||
// std:format is not friendly with a variable padwidth; requires a literal format.
|
||||
stringstream ss;
|
||||
ss << setfill('0') << setw(padwidth) << index;
|
||||
return (dir + "/" + basename + "-" + ss.str());
|
||||
};
|
||||
|
||||
lis_error err;
|
||||
|
||||
lis_scan_session * session;
|
||||
// Scanning starts here on device.
|
||||
err = m_sourceItem->scan_start(m_sourceItem, &session);
|
||||
if (err || !session)
|
||||
{
|
||||
if ( m_evh )
|
||||
m_evh->OnInsaneError ( IERR ( err ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
lis_scan_parameters parameters; // DO NOT use a POINTER here.
|
||||
err = session->get_scan_parameters(session, ¶meters);
|
||||
if (err)
|
||||
{
|
||||
if ( m_evh )
|
||||
m_evh->OnInsaneError ( IERR ( err ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* format is troublesome: always 0.
|
||||
* But for LineArt, in the logs, sane_get_parameters() returns format=1 (v4l)
|
||||
* or format=2 (remote).
|
||||
*/
|
||||
// lis_img_format format = parameters.format; // guaranteed, but always 0, even for LineArt.
|
||||
const int lineArtFactor = (m_mode == string("LineArt") ? 3 : 1); // insane always outputs RGB.
|
||||
int imageWidth = parameters.width; // pixels, guaranteed.
|
||||
int imageHeight = parameters.height; // pixels, not guaranteed.
|
||||
size_t imageSize = parameters.image_size * lineArtFactor; // bytes, not guaranteed.
|
||||
InsaneWorkerEvent::ImageAttributes imageAttributes;
|
||||
imageAttributes.size = imageSize;
|
||||
imageAttributes.width = imageWidth;
|
||||
imageAttributes.height = imageHeight;
|
||||
|
||||
// This file is valid raw pixels. It can be converted with rawtoppm and rawtopgm.
|
||||
uint pageIndex = startIndex;
|
||||
string filePath = makeFileName(pageIndex);
|
||||
const int bytesPerRow = imageSize / imageHeight;
|
||||
/*
|
||||
* Needs confirmation.
|
||||
* LineArt : 1 pixel = 1 bit - maximum resolution = 9600
|
||||
* Gray : 1 pixel = 1 byte - maximum resolution = 2400
|
||||
* Color : 1 pixel = 3 bytes - maximum resolution = 600
|
||||
*
|
||||
* A4, LineArt, 4800: 1690000620 bytes file OK (1.6 GiB).
|
||||
* Above that resolution:
|
||||
* std::bad_alloc - 1993034797 bytes (1.856 GiB) cannot be allocated
|
||||
* for one row. System with 64 GB RAM.
|
||||
*/
|
||||
|
||||
if (m_evh)
|
||||
m_evh->OnStartScanSession(startIndex, imageAttributes);
|
||||
do
|
||||
{
|
||||
ofstream outFile;
|
||||
if (m_evh)
|
||||
m_evh->OnPageStartScan(filePath, pageIndex, imageAttributes);
|
||||
do
|
||||
{
|
||||
if (gs_cancelRequested)
|
||||
{
|
||||
session->cancel(session);
|
||||
if (m_evh)
|
||||
m_evh->OnSessionCancelled(filePath);
|
||||
gs_cancelRequested = false;
|
||||
return false;
|
||||
}
|
||||
try
|
||||
{
|
||||
char * readBytes = new char[bytesPerRow];
|
||||
size_t bufferSize = bytesPerRow;
|
||||
err = session->scan_read(session, readBytes, &bufferSize); // bufferSize is in/out.
|
||||
if (LIS_IS_ERROR(err))
|
||||
{
|
||||
delete[] readBytes;
|
||||
if (m_evh)
|
||||
m_evh->OnSessionReadError(filePath);
|
||||
return false;
|
||||
}
|
||||
/*
|
||||
* bufferSize == 0 does not mean end_of_page or end of file.
|
||||
* But we get here when end_of_feed is false while there's nothing more to read.
|
||||
*/
|
||||
if (bufferSize)
|
||||
{
|
||||
if (!outFile.is_open())
|
||||
outFile.open(filePath, ios::binary | ios::trunc);
|
||||
outFile.write((const char*) readBytes, bufferSize);
|
||||
}
|
||||
delete[] readBytes;
|
||||
}
|
||||
catch (std::bad_alloc& e)
|
||||
{
|
||||
m_rootSourceItem->close(m_rootSourceItem);
|
||||
cout << "ABORT: " << e.what() << " - could not allocate " << bytesPerRow << " bytes." << endl;
|
||||
if (m_evh)
|
||||
m_evh->OnError("Insufficient system RAM.");
|
||||
return false;
|
||||
}
|
||||
} while (!session->end_of_page(session));
|
||||
/*
|
||||
* end_of_feed may return false though there is no more to read.
|
||||
* If outFile is not open, nothing was read; don't call OnPageEndScan.
|
||||
*/
|
||||
bool outFileWasOpen = outFile.is_open();
|
||||
// It may not have been opened.
|
||||
outFile.flush();
|
||||
outFile.close();
|
||||
if (m_evh && outFileWasOpen)
|
||||
m_evh->OnPageEndScan(filePath, pageIndex, imageAttributes);
|
||||
pageIndex += increment;
|
||||
if (m_sourceItem->type != LIS_ITEM_ADF) // v4l also
|
||||
break;
|
||||
filePath = makeFileName(pageIndex);
|
||||
} while( !session->end_of_feed(session));
|
||||
if (m_evh)
|
||||
m_evh->OnEndScanSession(pageIndex - increment, imageAttributes);
|
||||
|
||||
m_rootSourceItem->close(m_sourceItem); // Child.
|
||||
m_rootSourceItem->close(m_rootSourceItem); // Root.
|
||||
return true;
|
||||
}
|
||||
|
||||
// Determine the page extent.
|
||||
bool InsaneWorker::GetBottomRight(std::pair<double, double>& br)
|
||||
{
|
||||
int res = paperinit();
|
||||
if (res != PAPER_OK)
|
||||
{
|
||||
const string msg = "Could not initialise the paper library.";
|
||||
cerr << msg << endl;
|
||||
if (m_evh)
|
||||
m_evh->OnError(msg);
|
||||
return false;
|
||||
}
|
||||
|
||||
const paper * p = paperinfo(m_paperSize.c_str());
|
||||
if (!p)
|
||||
{
|
||||
string msg = "Failed to find the requested paper; attempt to use a default paper size.";
|
||||
cerr << msg << endl;
|
||||
if (m_evh)
|
||||
m_evh->OnError(msg);
|
||||
p = defaultpaper();
|
||||
if (!p)
|
||||
{
|
||||
msg = "Failed to find a default paper size; using the default scanner sizes.";
|
||||
cerr << msg << endl;
|
||||
if (m_evh)
|
||||
m_evh->OnError(msg);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int unit = paperunit(p);
|
||||
double conversionFactor = 1.0;
|
||||
if (unit == PAPER_UNIT_MM)
|
||||
conversionFactor = 1.0;
|
||||
else if (unit == PAPER_UNIT_IN)
|
||||
conversionFactor = 25.4;
|
||||
else
|
||||
{
|
||||
const string msg = "The measurement unit of the paper size is not handled; using the default scanner sizes.";
|
||||
cerr << msg << endl;
|
||||
if (m_evh)
|
||||
m_evh->OnError(msg);
|
||||
return false;
|
||||
}
|
||||
|
||||
br.first = paperwidth(p) * conversionFactor;
|
||||
br.second = paperheight(p) * conversionFactor;
|
||||
|
||||
res = paperdone();
|
||||
if (res != PAPER_OK)
|
||||
{
|
||||
const string msg = "Could not cleanly end the paper library.";
|
||||
cerr << msg << endl;
|
||||
if (m_evh)
|
||||
m_evh->OnError(msg);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
std::string InsaneWorker::ToLower(const std::string& input)
|
||||
{
|
||||
// We are dealing with single byte characters.
|
||||
string output;
|
||||
for ( char c : input )
|
||||
output.append ( 1, std::tolower ( c ) );
|
||||
return output;
|
||||
}
|
||||
|
||||
void InsaneWorker::Cancel()
|
||||
{
|
||||
gs_cancelRequested = true;
|
||||
}
|
||||
|
||||
std::pair<int, int> InsaneWorker::UpdateStartAndIncrement(const int startPageIndex, const int increment,
|
||||
const bool adf, const bool doubleSided, const int total)
|
||||
{
|
||||
int newStartPageIndex = startPageIndex;
|
||||
int newIncrement = increment;
|
||||
int totalEven = total;
|
||||
if (total % 2)
|
||||
totalEven++;
|
||||
// Scanning forward before max.
|
||||
if ((increment > 0) && adf && doubleSided && (startPageIndex < (totalEven - 2)))
|
||||
{
|
||||
newIncrement = 2;
|
||||
newStartPageIndex += newIncrement;
|
||||
}
|
||||
// Scanning forward at max.
|
||||
else if ((increment > 0) && adf && doubleSided && (startPageIndex == (totalEven - 2)))
|
||||
{
|
||||
newIncrement = -2;
|
||||
newStartPageIndex++;
|
||||
}
|
||||
// Scanning backward.
|
||||
else if ((increment < 0) && adf && doubleSided && (startPageIndex <= (totalEven - 1)))
|
||||
{
|
||||
newIncrement = -2;
|
||||
newStartPageIndex += newIncrement;
|
||||
}
|
||||
else
|
||||
{
|
||||
newIncrement = 1;
|
||||
newStartPageIndex++;
|
||||
}
|
||||
|
||||
std::pair<int, int> result = {newStartPageIndex, newIncrement};
|
||||
return result;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
InsaneWorkerEvent::InsaneWorkerEvent()
|
||||
{}
|
||||
|
||||
InsaneWorkerEvent::~InsaneWorkerEvent()
|
||||
{}
|
||||
|
||||
void InsaneWorkerEvent::OnInsaneError ( const std::string& message )
|
||||
{}
|
||||
|
||||
void InsaneWorkerEvent::OnError ( const std::string& message )
|
||||
{}
|
||||
|
||||
void InsaneWorkerEvent::OnSessionCancelled(const std::string& filePath)
|
||||
{}
|
||||
|
||||
void InsaneWorkerEvent::OnSessionReadError(const std::string& filePath)
|
||||
{}
|
||||
|
||||
void InsaneWorkerEvent::OnPageStartScan(const std::string& filePath,uint pageIndex, const ImageAttributes& imageAttributes)
|
||||
{}
|
||||
|
||||
void InsaneWorkerEvent::OnPageEndScan(const std::string& filePath, uint pageIndex, const ImageAttributes& imageAttributes)
|
||||
{}
|
||||
|
||||
void InsaneWorkerEvent::OnStartScanSession(uint pageIndex, const ImageAttributes& imageAttributes)
|
||||
{}
|
||||
|
||||
void InsaneWorkerEvent::OnEndScanSession(uint pageIndex, const ImageAttributes& imageAttributes)
|
||||
{}
|
||||
128
Resources/InsaneWidget/InsaneWorker.h
Normal file
128
Resources/InsaneWidget/InsaneWorker.h
Normal file
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* File: InsaneWorker.h
|
||||
* Author: Saleem Edah-Tally - nmset@yandex.com
|
||||
* License : CeCILL-C
|
||||
* Copyright Saleem Edah-Tally - © 2024
|
||||
*
|
||||
* Created on 14 02 2024, 13:00
|
||||
*/
|
||||
|
||||
#ifndef INSANEWORKER_H
|
||||
#define INSANEWORKER_H
|
||||
|
||||
#include <libinsane/capi.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class InsaneWorkerEvent;
|
||||
|
||||
/**
|
||||
* Performs scanning to raw data as files.\n
|
||||
* Input values are as obtained from the scanner widget:
|
||||
*
|
||||
* - device identifier - ex: sane:brother5:net1;dev0
|
||||
* - source - ex: Automatic Document Feeder(centrally aligned)
|
||||
* - source index - important for an ADF source
|
||||
* - mode - Color, LineArt, anything else is Gray
|
||||
* - resolution
|
||||
* - paper size - only those handled by PoDoFo
|
||||
*
|
||||
* Output files are numbered with a padded suffix according to an increment that
|
||||
* can be negative.
|
||||
*/
|
||||
|
||||
/*
|
||||
* All C objects must be initialised.
|
||||
* Initialise to nullptr and not to NULL.
|
||||
* Otherwise, unhealthy things are observed,
|
||||
* like 'if (err)' always evaluated to true.
|
||||
*/
|
||||
|
||||
class InsaneWorker
|
||||
{
|
||||
public:
|
||||
|
||||
InsaneWorker ( InsaneWorkerEvent* evh = nullptr );
|
||||
~InsaneWorker();
|
||||
struct DeviceDescriptor
|
||||
{
|
||||
std::string id;
|
||||
std::string model;
|
||||
std::string type;
|
||||
std::string vendor;
|
||||
std::string GetLabel()
|
||||
{
|
||||
return model + "-" + type + " [" + vendor + "]";
|
||||
}
|
||||
};
|
||||
|
||||
bool Init(); // Must be explicitly called, once only.
|
||||
std::vector<DeviceDescriptor> GetDeviceDescriptors()
|
||||
{
|
||||
return m_devices;
|
||||
}
|
||||
int IsADF(const std::string& deviceId, int sourceChildIndex);;
|
||||
std::string GetOptionPossibleValues(const std::string& deviceId,
|
||||
const std::string& optionName, std::vector<std::string>& possible);
|
||||
bool ConfigureDevice(const std::string& deviceId,
|
||||
const std::string& source = "FlatBed", int sourceChildIndex = 0,
|
||||
const std::string& mode = "Color", int resolution = 300,
|
||||
const std::string& paperSize = "A4");
|
||||
bool Scan(const std::string& dir, const std::string& basename,
|
||||
int startIndex = 0, int padwidth = 2, int increment = 1); // increment can be negative
|
||||
void Cancel();
|
||||
InsaneWorkerEvent * GetEventHandler() const
|
||||
{
|
||||
return m_evh;
|
||||
}
|
||||
/**
|
||||
* Update the start page index and increment to pass to ::Scan(), accounting
|
||||
* for ADF and double sided scanning.
|
||||
*/
|
||||
std::pair<int, int> UpdateStartAndIncrement(const int startPageIndex, const int increment,
|
||||
const bool adf, const bool doubleSided, const int total);
|
||||
|
||||
private:
|
||||
lis_api * m_api = nullptr;
|
||||
lis_item * m_rootSourceItem = nullptr; // May have child items.
|
||||
lis_item * m_sourceItem = nullptr;
|
||||
InsaneWorkerEvent * m_evh = nullptr;
|
||||
|
||||
std::vector<DeviceDescriptor> m_devices;
|
||||
std::string m_deviceId;
|
||||
std::string m_source = "FlatBed";
|
||||
int m_sourceChildIndex = 0;
|
||||
std::string m_mode = "Color";
|
||||
int m_resolution = 300;
|
||||
std::string m_paperSize = "A4";
|
||||
|
||||
bool GetBottomRight(std::pair<double, double>& br);
|
||||
std::string ToLower(const std::string& input);
|
||||
};
|
||||
|
||||
class InsaneWorkerEvent
|
||||
{
|
||||
public:
|
||||
InsaneWorkerEvent();
|
||||
virtual ~InsaneWorkerEvent();
|
||||
|
||||
struct ImageAttributes
|
||||
{
|
||||
size_t size = 0; // bytes
|
||||
uint width = 0; // pixels
|
||||
uint height = 0; // pixels
|
||||
};
|
||||
|
||||
virtual void OnInsaneError ( const std::string& message );
|
||||
virtual void OnError ( const std::string& message );
|
||||
virtual void OnSessionCancelled(const std::string& filePath);
|
||||
virtual void OnSessionReadError(const std::string& filePath);
|
||||
virtual void OnPageStartScan(const std::string& filePath, uint pageIndex,
|
||||
const ImageAttributes& imageAttributes);
|
||||
virtual void OnPageEndScan(const std::string& filePath, uint pageIndex,
|
||||
const ImageAttributes& imageAttributes);
|
||||
virtual void OnStartScanSession(uint pageIndex, const ImageAttributes& imageAttributes);
|
||||
virtual void OnEndScanSession(uint pageIndex, const ImageAttributes& imageAttributes);
|
||||
};
|
||||
|
||||
#endif // INSANEWORKER_H
|
||||
61
Resources/InsaneWidget/PixelToImageWriter.cpp
Normal file
61
Resources/InsaneWidget/PixelToImageWriter.cpp
Normal file
@@ -0,0 +1,61 @@
|
||||
// /*
|
||||
// * File: PixelToImageWriter.cpp
|
||||
// * Author: Saleem Edah-Tally - nmset@yandex.com
|
||||
// * License : CeCILL-C
|
||||
// * Copyright Saleem Edah-Tally - © 2025
|
||||
// *
|
||||
// * Created on 27 06 2025, 20:28
|
||||
// */
|
||||
|
||||
#include "PixelToImageWriter.h"
|
||||
#include <Common.h>
|
||||
#include <fstream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
bool PixelToImageWriter::Convert(const std::string& pixelFilePath,
|
||||
int imageWidth, int imageHeight,
|
||||
int outputFormat, wxImage * image)
|
||||
{
|
||||
UpdateExtensionsMap();
|
||||
wxImage * outImage = image;
|
||||
unique_ptr<wxImage> tmpImage;
|
||||
if (!image)
|
||||
{
|
||||
tmpImage = make_unique<wxImage>();
|
||||
outImage = tmpImage.get();
|
||||
}
|
||||
string raw;
|
||||
ifstream ifs(pixelFilePath, ios::binary);
|
||||
if (!ifs.good())
|
||||
{
|
||||
cerr << _("Failed to read raw file.") << endl;
|
||||
return false;
|
||||
}
|
||||
raw.assign(istreambuf_iterator<char>(ifs), istreambuf_iterator<char>());
|
||||
|
||||
outImage->SetData((unsigned char*) raw.data(), imageWidth, imageHeight, true); // true +++
|
||||
|
||||
switch (outputFormat)
|
||||
{
|
||||
case PNG:
|
||||
outImage->SaveFile(pixelFilePath + "." + Extensions[PNG], wxBITMAP_TYPE_PNG);
|
||||
break;
|
||||
case JPEG:
|
||||
outImage->SaveFile(pixelFilePath + "." + Extensions[JPEG], wxBITMAP_TYPE_JPEG);
|
||||
break;
|
||||
case TIFF:
|
||||
outImage->SaveFile(pixelFilePath + "." + Extensions[TIFF], wxBITMAP_TYPE_TIFF);
|
||||
break;
|
||||
case PNM:
|
||||
outImage->SaveFile(pixelFilePath + "." + Extensions[PNM], wxBITMAP_TYPE_PNM);
|
||||
break;
|
||||
case PDF:
|
||||
break;
|
||||
default:
|
||||
cerr << _("Unhandled output image format.") << endl;
|
||||
return false;
|
||||
};
|
||||
|
||||
return true;
|
||||
}
|
||||
28
Resources/InsaneWidget/PixelToImageWriter.h
Normal file
28
Resources/InsaneWidget/PixelToImageWriter.h
Normal file
@@ -0,0 +1,28 @@
|
||||
// /*
|
||||
// * File: PixelToImageWriter.h
|
||||
// * Author: Saleem Edah-Tally - nmset@yandex.com
|
||||
// * License : CeCILL-C
|
||||
// * Copyright Saleem Edah-Tally - © 2025
|
||||
// *
|
||||
// * Created on 27 06 2025, 20:28
|
||||
// */
|
||||
|
||||
#ifndef PIXELTOIMAGEWRITER_H
|
||||
#define PIXELTOIMAGEWRITER_H
|
||||
|
||||
#include "Common.h"
|
||||
#include <string>
|
||||
#include <wx/wx.h>
|
||||
|
||||
/**
|
||||
* Create an image file from a raw scanned file.\n
|
||||
*/
|
||||
class PixelToImageWriter
|
||||
{
|
||||
public:
|
||||
static bool Convert(const std::string& pixelFilePath,
|
||||
int imageWidth, int imageHeight, int outputFormat = PNG,
|
||||
wxImage * image = nullptr);
|
||||
};
|
||||
|
||||
#endif // PIXELTOIMAGEWRITER_H
|
||||
83
Resources/InsaneWidget/PixelToPdfWriter.cpp
Normal file
83
Resources/InsaneWidget/PixelToPdfWriter.cpp
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* File: PixelToPdfWriter.cpp
|
||||
* Author: Saleem Edah-Tally - nmset@yandex.com
|
||||
* License : CeCILL-C
|
||||
* Copyright Saleem Edah-Tally - © 2025
|
||||
*
|
||||
* Created on 14 06 2025, 17:15
|
||||
*/
|
||||
|
||||
#include "PixelToPdfWriter.h"
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
|
||||
using namespace std;
|
||||
using namespace PoDoFo;
|
||||
|
||||
PixelToPdfWriter::PixelToPdfWriter()
|
||||
{
|
||||
m_pageSizes["A0"] = PoDoFo::PdfPageSize::A0;
|
||||
m_pageSizes["A1"] = PoDoFo::PdfPageSize::A1;
|
||||
m_pageSizes["A2"] = PoDoFo::PdfPageSize::A2;
|
||||
m_pageSizes["A3"] = PoDoFo::PdfPageSize::A3;
|
||||
m_pageSizes["A4"] = PoDoFo::PdfPageSize::A4;
|
||||
m_pageSizes["A5"] = PoDoFo::PdfPageSize::A5;
|
||||
m_pageSizes["A6"] = PoDoFo::PdfPageSize::A6;
|
||||
m_pageSizes["Letter"] = PoDoFo::PdfPageSize::Letter;
|
||||
m_pageSizes["Legal"] = PoDoFo::PdfPageSize::Legal;
|
||||
m_pageSizes["Tabloid"] = PoDoFo::PdfPageSize::Tabloid;
|
||||
}
|
||||
|
||||
|
||||
bool PixelToPdfWriter::AddPageAt(const std::string& pixelFile, uint width, uint height, uint index,
|
||||
PoDoFo::PdfPageSize pageSize, PoDoFo::PdfColorSpace)
|
||||
{
|
||||
try
|
||||
{
|
||||
Rect pageRect = PdfPage::CreateStandardPageSize(pageSize);
|
||||
PdfPage& page = m_doc.GetPages().CreatePageAt(index, pageRect);
|
||||
|
||||
PdfImageInfo info;
|
||||
info.Width = width; // Must be known beforehand and must be exact.
|
||||
info.Height = height;
|
||||
info.BitsPerComponent = 8;
|
||||
info.ColorSpace = PdfColorSpace::DeviceRGB; // Is always RGB from libinsane.
|
||||
|
||||
ifstream ifs(pixelFile, ios::binary);
|
||||
string content;
|
||||
content.assign(istreambuf_iterator<char>(ifs), istreambuf_iterator<char>());
|
||||
bufferview bv(content);
|
||||
|
||||
const uint pageNumber = m_doc.GetPages().GetCount();
|
||||
std::unique_ptr<PdfImage> image = m_doc.CreateImage("Page_" + to_string(pageNumber)); // No space.
|
||||
image->SetDataRaw(bv, info); // OK for pixel file, including LineArt
|
||||
double scale = std::min(pageRect.Width / image->GetWidth(), pageRect.Height / image->GetHeight());
|
||||
|
||||
PdfPainter painter;
|
||||
painter.SetCanvas(page);
|
||||
painter.DrawImage(*(image), 0.0, 0.0, scale, scale);
|
||||
painter.FinishDrawing();
|
||||
}
|
||||
catch (PdfError& e)
|
||||
{
|
||||
cerr << e.ErrorMessage(e.GetCode()) << endl << e.what() << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PixelToPdfWriter::Save(const std::string& pdfFile)
|
||||
{
|
||||
m_doc.Save(pdfFile);
|
||||
}
|
||||
|
||||
uint PixelToPdfWriter::GetNumberOfPages() const
|
||||
{
|
||||
return m_doc.GetPages().GetCount();
|
||||
}
|
||||
|
||||
void PixelToPdfWriter::RemovePageAt(uint index)
|
||||
{
|
||||
m_doc.GetPages().RemovePageAt(index);
|
||||
}
|
||||
49
Resources/InsaneWidget/PixelToPdfWriter.h
Normal file
49
Resources/InsaneWidget/PixelToPdfWriter.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* File: PixelToPdfWriter.h
|
||||
* Author: Saleem Edah-Tally - nmset@yandex.com
|
||||
* License : CeCILL-C
|
||||
* Copyright Saleem Edah-Tally - © 2025
|
||||
*
|
||||
* Created on 14 06 2025, 17:15
|
||||
*/
|
||||
|
||||
#ifndef PIXELTOPDFWRITER_H
|
||||
#define PIXELTOPDFWRITER_H
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <podofo/podofo.h>
|
||||
|
||||
/**
|
||||
* Create a PDF document, append or insert pages from raw scanned files.\n
|
||||
* Each image is a full page scan; it is scaled in the PDF document to the full
|
||||
* page dimensions.\n
|
||||
* Account for page size.
|
||||
*/
|
||||
class PixelToPdfWriter
|
||||
{
|
||||
public:
|
||||
typedef std::map<std::string, PoDoFo::PdfPageSize> PageSizeMap;
|
||||
|
||||
PixelToPdfWriter();
|
||||
bool AddPageAt(const std::string& pixelFile, uint width, uint height, uint index,
|
||||
PoDoFo::PdfPageSize pageSize = PoDoFo::PdfPageSize::A4,
|
||||
PoDoFo::PdfColorSpace = PoDoFo::PdfColorSpace::DeviceRGB /*Unused*/);
|
||||
void Save(const std::string& pdfFile);
|
||||
uint GetNumberOfPages() const;
|
||||
void RemovePageAt(uint index);
|
||||
PoDoFo::PdfPageSize GetPageSize(const std::string& literal)
|
||||
{
|
||||
return m_pageSizes[literal]; // 0 if not found, PdfPageSize::Unknown.
|
||||
}
|
||||
PageSizeMap GetPageSizes() const
|
||||
{
|
||||
return m_pageSizes;
|
||||
}
|
||||
private:
|
||||
PoDoFo::PdfMemDocument m_doc;
|
||||
|
||||
PageSizeMap m_pageSizes;
|
||||
};
|
||||
|
||||
#endif // PIXELTOPDFWRITER_H
|
||||
180
Resources/InsaneWidget/UI/InsaneWidget.cpp
Normal file
180
Resources/InsaneWidget/UI/InsaneWidget.cpp
Normal file
@@ -0,0 +1,180 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: InsaneWidgetcpp.cpp
|
||||
// Purpose:
|
||||
// Author: Saleem EDAH-TALLY
|
||||
// Modified by:
|
||||
// Created: dim. 15 juin 2025 19:37:17
|
||||
// RCS-ID:
|
||||
// Copyright: Copyright Saleem EDAH-TALLY. All rights reserved.
|
||||
// Licence: CeCILL-C
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// For compilers that support precompilation, includes "wx/wx.h".
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/wx.h"
|
||||
#endif
|
||||
|
||||
////@begin includes
|
||||
////@end includes
|
||||
|
||||
#include "InsaneWidget.h"
|
||||
|
||||
////@begin XPM images
|
||||
////@end XPM images
|
||||
|
||||
|
||||
/*
|
||||
* InsaneWidget type definition
|
||||
*/
|
||||
|
||||
IMPLEMENT_DYNAMIC_CLASS( InsaneWidget, wxPanel )
|
||||
|
||||
|
||||
/*
|
||||
* InsaneWidget event table definition
|
||||
*/
|
||||
|
||||
BEGIN_EVENT_TABLE( InsaneWidget, wxPanel )
|
||||
|
||||
////@begin InsaneWidget event table entries
|
||||
////@end InsaneWidget event table entries
|
||||
|
||||
END_EVENT_TABLE()
|
||||
|
||||
|
||||
/*
|
||||
* InsaneWidget constructors
|
||||
*/
|
||||
|
||||
InsaneWidget::InsaneWidget()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
InsaneWidget::InsaneWidget( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style )
|
||||
{
|
||||
Init();
|
||||
Create(parent, id, pos, size, style);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* InsaneWidget creator
|
||||
*/
|
||||
|
||||
bool InsaneWidget::Create( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style )
|
||||
{
|
||||
////@begin InsaneWidget creation
|
||||
SetExtraStyle(wxWS_EX_VALIDATE_RECURSIVELY);
|
||||
wxPanel::Create( parent, id, pos, size, style );
|
||||
|
||||
CreateControls();
|
||||
if (GetSizer())
|
||||
{
|
||||
GetSizer()->SetSizeHints(this);
|
||||
}
|
||||
Centre();
|
||||
////@end InsaneWidget creation
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* InsaneWidget destructor
|
||||
*/
|
||||
|
||||
InsaneWidget::~InsaneWidget()
|
||||
{
|
||||
////@begin InsaneWidget destruction
|
||||
////@end InsaneWidget destruction
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Member initialisation
|
||||
*/
|
||||
|
||||
void InsaneWidget::Init()
|
||||
{
|
||||
////@begin InsaneWidget member initialisation
|
||||
lblNewDoc = NULL;
|
||||
txtNewDoc = NULL;
|
||||
btnScan = NULL;
|
||||
////@end InsaneWidget member initialisation
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Control creation for InsaneWidget
|
||||
*/
|
||||
|
||||
void InsaneWidget::CreateControls()
|
||||
{
|
||||
////@begin InsaneWidget content construction
|
||||
InsaneWidget* itemPanel1 = this;
|
||||
|
||||
wxBoxSizer* itemBoxSizer2 = new wxBoxSizer(wxVERTICAL);
|
||||
itemPanel1->SetSizer(itemBoxSizer2);
|
||||
|
||||
wxBoxSizer* itemBoxSizer1 = new wxBoxSizer(wxHORIZONTAL);
|
||||
itemBoxSizer2->Add(itemBoxSizer1, 0, wxGROW|wxALL, 5);
|
||||
|
||||
lblNewDoc = new wxStaticText( itemPanel1, ID_NewDoc_LBL, _("New"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
if (InsaneWidget::ShowToolTips())
|
||||
lblNewDoc->SetToolTip(_("'Right' click to define a scan project."));
|
||||
itemBoxSizer1->Add(lblNewDoc, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
|
||||
|
||||
txtNewDoc = new wxTextCtrl( itemPanel1, ID_NewDoc_TXT, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE|wxTE_READONLY );
|
||||
if (InsaneWidget::ShowToolTips())
|
||||
txtNewDoc->SetToolTip(_("Full path to destination file without the extension; it is determined by the output type."));
|
||||
itemBoxSizer1->Add(txtNewDoc, 1, wxGROW|wxALL, 5);
|
||||
|
||||
btnScan = new wxButton( itemPanel1, ID_Scan_BTN, _("Scan"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
if (InsaneWidget::ShowToolTips())
|
||||
btnScan->SetToolTip(_("'Left click' to start the scan project.\n'Right click' to show the scanner widget."));
|
||||
itemBoxSizer1->Add(btnScan, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
|
||||
|
||||
////@end InsaneWidget content construction
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Should we show tooltips?
|
||||
*/
|
||||
|
||||
bool InsaneWidget::ShowToolTips()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get bitmap resources
|
||||
*/
|
||||
|
||||
wxBitmap InsaneWidget::GetBitmapResource( const wxString& name )
|
||||
{
|
||||
// Bitmap retrieval
|
||||
////@begin InsaneWidget bitmap retrieval
|
||||
wxUnusedVar(name);
|
||||
return wxNullBitmap;
|
||||
////@end InsaneWidget bitmap retrieval
|
||||
}
|
||||
|
||||
/*
|
||||
* Get icon resources
|
||||
*/
|
||||
|
||||
wxIcon InsaneWidget::GetIconResource( const wxString& name )
|
||||
{
|
||||
// Icon retrieval
|
||||
////@begin InsaneWidget icon retrieval
|
||||
wxUnusedVar(name);
|
||||
return wxNullIcon;
|
||||
////@end InsaneWidget icon retrieval
|
||||
}
|
||||
97
Resources/InsaneWidget/UI/InsaneWidget.h
Normal file
97
Resources/InsaneWidget/UI/InsaneWidget.h
Normal file
@@ -0,0 +1,97 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: InsaneWidget.h
|
||||
// Purpose:
|
||||
// Author: Saleem EDAH-TALLY
|
||||
// Modified by:
|
||||
// Created: dim. 15 juin 2025 19:37:17
|
||||
// RCS-ID:
|
||||
// Copyright: Copyright Saleem EDAH-TALLY. All rights reserved.
|
||||
// Licence: CeCILL-C
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _INSANEWIDGET_H_
|
||||
#define _INSANEWIDGET_H_
|
||||
|
||||
|
||||
/*!
|
||||
* Includes
|
||||
*/
|
||||
|
||||
////@begin includes
|
||||
////@end includes
|
||||
|
||||
/*!
|
||||
* Forward declarations
|
||||
*/
|
||||
|
||||
////@begin forward declarations
|
||||
////@end forward declarations
|
||||
|
||||
/*!
|
||||
* Control identifiers
|
||||
*/
|
||||
|
||||
////@begin control identifiers
|
||||
#define ID_INSANEWIDGET 10000
|
||||
#define ID_NewDoc_LBL 10014
|
||||
#define ID_NewDoc_TXT 10005
|
||||
#define ID_Scan_BTN 10006
|
||||
#define SYMBOL_INSANEWIDGET_STYLE wxTAB_TRAVERSAL
|
||||
#define SYMBOL_INSANEWIDGET_TITLE _("InsaneWidget")
|
||||
#define SYMBOL_INSANEWIDGET_IDNAME ID_INSANEWIDGET
|
||||
#define SYMBOL_INSANEWIDGET_SIZE wxSize(400, 300)
|
||||
#define SYMBOL_INSANEWIDGET_POSITION wxDefaultPosition
|
||||
////@end control identifiers
|
||||
|
||||
|
||||
/*!
|
||||
* InsaneWidget class declaration
|
||||
*/
|
||||
|
||||
class InsaneWidget: public wxPanel
|
||||
{
|
||||
DECLARE_DYNAMIC_CLASS( InsaneWidget )
|
||||
DECLARE_EVENT_TABLE()
|
||||
|
||||
public:
|
||||
/// Constructors
|
||||
InsaneWidget();
|
||||
InsaneWidget( wxWindow* parent, wxWindowID id = SYMBOL_INSANEWIDGET_IDNAME, const wxPoint& pos = SYMBOL_INSANEWIDGET_POSITION, const wxSize& size = SYMBOL_INSANEWIDGET_SIZE, long style = SYMBOL_INSANEWIDGET_STYLE );
|
||||
|
||||
/// Creation
|
||||
bool Create( wxWindow* parent, wxWindowID id = SYMBOL_INSANEWIDGET_IDNAME, const wxPoint& pos = SYMBOL_INSANEWIDGET_POSITION, const wxSize& size = SYMBOL_INSANEWIDGET_SIZE, long style = SYMBOL_INSANEWIDGET_STYLE );
|
||||
|
||||
/// Destructor
|
||||
~InsaneWidget();
|
||||
|
||||
/// Initialises member variables
|
||||
void Init();
|
||||
|
||||
/// Creates the controls and sizers
|
||||
void CreateControls();
|
||||
|
||||
////@begin InsaneWidget event handler declarations
|
||||
|
||||
////@end InsaneWidget event handler declarations
|
||||
|
||||
////@begin InsaneWidget member function declarations
|
||||
|
||||
/// Retrieves bitmap resources
|
||||
wxBitmap GetBitmapResource( const wxString& name );
|
||||
|
||||
/// Retrieves icon resources
|
||||
wxIcon GetIconResource( const wxString& name );
|
||||
////@end InsaneWidget member function declarations
|
||||
|
||||
/// Should we show tooltips?
|
||||
static bool ShowToolTips();
|
||||
|
||||
////@begin InsaneWidget member variables
|
||||
wxStaticText* lblNewDoc;
|
||||
wxTextCtrl* txtNewDoc;
|
||||
wxButton* btnScan;
|
||||
////@end InsaneWidget member variables
|
||||
};
|
||||
|
||||
#endif
|
||||
// _INSANEWIDGET_H_
|
||||
1659
Resources/InsaneWidget/UI/InsaneWidget.pjd
Normal file
1659
Resources/InsaneWidget/UI/InsaneWidget.pjd
Normal file
File diff suppressed because it is too large
Load Diff
1
Resources/InsaneWidget/UI/InsaneWidget.rc
Normal file
1
Resources/InsaneWidget/UI/InsaneWidget.rc
Normal file
@@ -0,0 +1 @@
|
||||
#include "wx/msw/wx.rc"
|
||||
237
Resources/InsaneWidget/UI/ScannerWidget.cpp
Normal file
237
Resources/InsaneWidget/UI/ScannerWidget.cpp
Normal file
@@ -0,0 +1,237 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: ScannerWidget.cpp
|
||||
// Purpose:
|
||||
// Author: Saleem EDAH-TALLY
|
||||
// Modified by:
|
||||
// Created: dim. 15 juin 2025 19:39:52
|
||||
// RCS-ID:
|
||||
// Copyright: Copyright Saleem EDAH-TALLY. All rights reserved.
|
||||
// Licence: CeCILL-C
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// For compilers that support precompilation, includes "wx/wx.h".
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/wx.h"
|
||||
#endif
|
||||
|
||||
////@begin includes
|
||||
////@end includes
|
||||
|
||||
#include "ScannerWidget.h"
|
||||
|
||||
////@begin XPM images
|
||||
////@end XPM images
|
||||
|
||||
|
||||
/*
|
||||
* ScannerWidget type definition
|
||||
*/
|
||||
|
||||
IMPLEMENT_DYNAMIC_CLASS( ScannerWidget, wxPanel )
|
||||
|
||||
|
||||
/*
|
||||
* ScannerWidget event table definition
|
||||
*/
|
||||
|
||||
BEGIN_EVENT_TABLE( ScannerWidget, wxPanel )
|
||||
|
||||
////@begin ScannerWidget event table entries
|
||||
////@end ScannerWidget event table entries
|
||||
|
||||
END_EVENT_TABLE()
|
||||
|
||||
|
||||
/*
|
||||
* ScannerWidget constructors
|
||||
*/
|
||||
|
||||
ScannerWidget::ScannerWidget()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
ScannerWidget::ScannerWidget( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style )
|
||||
{
|
||||
Init();
|
||||
Create(parent, id, pos, size, style);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ScannerWidget creator
|
||||
*/
|
||||
|
||||
bool ScannerWidget::Create( wxWindow* parent, wxWindowID id, const wxPoint& pos, const wxSize& size, long style )
|
||||
{
|
||||
////@begin ScannerWidget creation
|
||||
SetExtraStyle(wxWS_EX_VALIDATE_RECURSIVELY);
|
||||
wxPanel::Create( parent, id, pos, size, style );
|
||||
|
||||
CreateControls();
|
||||
if (GetSizer())
|
||||
{
|
||||
GetSizer()->SetSizeHints(this);
|
||||
}
|
||||
Centre();
|
||||
////@end ScannerWidget creation
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ScannerWidget destructor
|
||||
*/
|
||||
|
||||
ScannerWidget::~ScannerWidget()
|
||||
{
|
||||
////@begin ScannerWidget destruction
|
||||
////@end ScannerWidget destruction
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Member initialisation
|
||||
*/
|
||||
|
||||
void ScannerWidget::Init()
|
||||
{
|
||||
////@begin ScannerWidget member initialisation
|
||||
lblImageType = NULL;
|
||||
cmbOutputType = NULL;
|
||||
btnRefreshDevices = NULL;
|
||||
lblDevices = NULL;
|
||||
cmbDevices = NULL;
|
||||
lblSource = NULL;
|
||||
cmbSource = NULL;
|
||||
lblMode = NULL;
|
||||
cmbMode = NULL;
|
||||
lblResolution = NULL;
|
||||
cmbResolution = NULL;
|
||||
lblPaperSize = NULL;
|
||||
cmbPaperSize = NULL;
|
||||
////@end ScannerWidget member initialisation
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Control creation for ScannerWidget
|
||||
*/
|
||||
|
||||
void ScannerWidget::CreateControls()
|
||||
{
|
||||
////@begin ScannerWidget content construction
|
||||
ScannerWidget* itemPanel1 = this;
|
||||
|
||||
wxBoxSizer* itemBoxSizer1 = new wxBoxSizer(wxVERTICAL);
|
||||
itemPanel1->SetSizer(itemBoxSizer1);
|
||||
|
||||
wxFlexGridSizer* itemFlexGridSizer2 = new wxFlexGridSizer(0, 2, 0, 0);
|
||||
itemBoxSizer1->Add(itemFlexGridSizer2, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
|
||||
|
||||
lblImageType = new wxStaticText( itemPanel1, wxID_STATIC_IMAGE_TYPE, _("Format:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
itemFlexGridSizer2->Add(lblImageType, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL, 5);
|
||||
|
||||
wxArrayString cmbOutputTypeStrings;
|
||||
cmbOutputType = new wxComboBox( itemPanel1, ID_COMBOBOX_IMAGE_TYPE, wxEmptyString, wxDefaultPosition, wxDefaultSize, cmbOutputTypeStrings, wxCB_READONLY );
|
||||
if (ScannerWidget::ShowToolTips())
|
||||
cmbOutputType->SetToolTip(_("Output document format"));
|
||||
itemFlexGridSizer2->Add(cmbOutputType, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxALL, 5);
|
||||
|
||||
wxBoxSizer* itemBoxSizer5 = new wxBoxSizer(wxHORIZONTAL);
|
||||
itemFlexGridSizer2->Add(itemBoxSizer5, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5);
|
||||
|
||||
btnRefreshDevices = new wxButton( itemPanel1, ID_BUTTON_REFRESH_DEVICES, wxGetTranslation(wxString() + (wxChar) 0x21BB), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT );
|
||||
if (ScannerWidget::ShowToolTips())
|
||||
btnRefreshDevices->SetToolTip(_("Refresh available devices"));
|
||||
itemBoxSizer5->Add(btnRefreshDevices, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
|
||||
|
||||
lblDevices = new wxStaticText( itemPanel1, wxID_STATIC_DEVICES, _("Devices:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
itemBoxSizer5->Add(lblDevices, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
|
||||
|
||||
wxArrayString cmbDevicesStrings;
|
||||
cmbDevices = new wxComboBox( itemPanel1, ID_COMBOBOX_Devices, wxEmptyString, wxDefaultPosition, wxDefaultSize, cmbDevicesStrings, wxCB_READONLY );
|
||||
if (ScannerWidget::ShowToolTips())
|
||||
cmbDevices->SetToolTip(_("Available devices"));
|
||||
itemFlexGridSizer2->Add(cmbDevices, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5);
|
||||
|
||||
lblSource = new wxStaticText( itemPanel1, wxID_STATIC_SOURCE, _("Source:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
itemFlexGridSizer2->Add(lblSource, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL, 5);
|
||||
|
||||
wxArrayString cmbSourceStrings;
|
||||
cmbSource = new wxComboBox( itemPanel1, ID_COMBOBOX_SOURCE, wxEmptyString, wxDefaultPosition, wxDefaultSize, cmbSourceStrings, wxCB_READONLY );
|
||||
if (ScannerWidget::ShowToolTips())
|
||||
cmbSource->SetToolTip(_("Scan source"));
|
||||
itemFlexGridSizer2->Add(cmbSource, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5);
|
||||
|
||||
lblMode = new wxStaticText( itemPanel1, wxID_STATIC_MODE, _("Mode:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
itemFlexGridSizer2->Add(lblMode, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL, 5);
|
||||
|
||||
wxArrayString cmbModeStrings;
|
||||
cmbMode = new wxComboBox( itemPanel1, ID_COMBOBOX_MODE, wxEmptyString, wxDefaultPosition, wxDefaultSize, cmbModeStrings, wxCB_READONLY );
|
||||
if (ScannerWidget::ShowToolTips())
|
||||
cmbMode->SetToolTip(_("Scan mode"));
|
||||
itemFlexGridSizer2->Add(cmbMode, 0, wxGROW|wxALIGN_CENTER_VERTICAL|wxALL, 5);
|
||||
|
||||
lblResolution = new wxStaticText( itemPanel1, wxID_STATIC_RESOLUTION, _("Resolution:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
itemFlexGridSizer2->Add(lblResolution, 0, wxALIGN_RIGHT|wxALIGN_CENTER_VERTICAL|wxALL, 5);
|
||||
|
||||
wxArrayString cmbResolutionStrings;
|
||||
cmbResolution = new wxComboBox( itemPanel1, ID_COMBOBOX_RESOLUTION, wxEmptyString, wxDefaultPosition, wxDefaultSize, cmbResolutionStrings, wxCB_READONLY );
|
||||
if (ScannerWidget::ShowToolTips())
|
||||
cmbResolution->SetToolTip(_("Scan resolution"));
|
||||
itemFlexGridSizer2->Add(cmbResolution, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxALL, 5);
|
||||
|
||||
lblPaperSize = new wxStaticText( itemPanel1, wxID_STATIC, _("Paper size:"), wxDefaultPosition, wxDefaultSize, 0 );
|
||||
itemFlexGridSizer2->Add(lblPaperSize, 0, wxALIGN_CENTER_HORIZONTAL|wxALIGN_CENTER_VERTICAL|wxALL, 5);
|
||||
|
||||
wxArrayString cmbPaperSizeStrings;
|
||||
cmbPaperSize = new wxComboBox( itemPanel1, ID_COMBOBOX, wxEmptyString, wxDefaultPosition, wxDefaultSize, cmbPaperSizeStrings, wxCB_READONLY );
|
||||
itemFlexGridSizer2->Add(cmbPaperSize, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL|wxALL, 5);
|
||||
|
||||
itemFlexGridSizer2->AddGrowableCol(1);
|
||||
|
||||
////@end ScannerWidget content construction
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Should we show tooltips?
|
||||
*/
|
||||
|
||||
bool ScannerWidget::ShowToolTips()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get bitmap resources
|
||||
*/
|
||||
|
||||
wxBitmap ScannerWidget::GetBitmapResource( const wxString& name )
|
||||
{
|
||||
// Bitmap retrieval
|
||||
////@begin ScannerWidget bitmap retrieval
|
||||
wxUnusedVar(name);
|
||||
return wxNullBitmap;
|
||||
////@end ScannerWidget bitmap retrieval
|
||||
}
|
||||
|
||||
/*
|
||||
* Get icon resources
|
||||
*/
|
||||
|
||||
wxIcon ScannerWidget::GetIconResource( const wxString& name )
|
||||
{
|
||||
// Icon retrieval
|
||||
////@begin ScannerWidget icon retrieval
|
||||
wxUnusedVar(name);
|
||||
return wxNullIcon;
|
||||
////@end ScannerWidget icon retrieval
|
||||
}
|
||||
116
Resources/InsaneWidget/UI/ScannerWidget.h
Normal file
116
Resources/InsaneWidget/UI/ScannerWidget.h
Normal file
@@ -0,0 +1,116 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: ScannerWidget.h
|
||||
// Purpose:
|
||||
// Author: Saleem EDAH-TALLY
|
||||
// Modified by:
|
||||
// Created: dim. 15 juin 2025 19:39:52
|
||||
// RCS-ID:
|
||||
// Copyright: Copyright Saleem EDAH-TALLY. All rights reserved.
|
||||
// Licence: CeCILL-C
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _SCANNERWIDGET_H_
|
||||
#define _SCANNERWIDGET_H_
|
||||
|
||||
|
||||
/*!
|
||||
* Includes
|
||||
*/
|
||||
|
||||
////@begin includes
|
||||
////@end includes
|
||||
|
||||
/*!
|
||||
* Forward declarations
|
||||
*/
|
||||
|
||||
////@begin forward declarations
|
||||
////@end forward declarations
|
||||
|
||||
/*!
|
||||
* Control identifiers
|
||||
*/
|
||||
|
||||
////@begin control identifiers
|
||||
#define ID_SCANNERWIDGET 10000
|
||||
#define wxID_STATIC_IMAGE_TYPE 10031
|
||||
#define ID_COMBOBOX_IMAGE_TYPE 10007
|
||||
#define ID_BUTTON_REFRESH_DEVICES 10006
|
||||
#define wxID_STATIC_DEVICES 10029
|
||||
#define ID_COMBOBOX_Devices 10001
|
||||
#define wxID_STATIC_SOURCE 10028
|
||||
#define ID_COMBOBOX_SOURCE 10002
|
||||
#define wxID_STATIC_MODE 10027
|
||||
#define ID_COMBOBOX_MODE 10003
|
||||
#define wxID_STATIC_RESOLUTION 10030
|
||||
#define ID_COMBOBOX_RESOLUTION 10004
|
||||
#define ID_COMBOBOX 10005
|
||||
#define SYMBOL_SCANNERWIDGET_STYLE wxTAB_TRAVERSAL
|
||||
#define SYMBOL_SCANNERWIDGET_TITLE _("ScannerWidget")
|
||||
#define SYMBOL_SCANNERWIDGET_IDNAME ID_SCANNERWIDGET
|
||||
#define SYMBOL_SCANNERWIDGET_SIZE wxSize(400, 300)
|
||||
#define SYMBOL_SCANNERWIDGET_POSITION wxDefaultPosition
|
||||
////@end control identifiers
|
||||
|
||||
|
||||
/*!
|
||||
* ScannerWidget class declaration
|
||||
*/
|
||||
|
||||
class ScannerWidget: public wxPanel
|
||||
{
|
||||
DECLARE_DYNAMIC_CLASS( ScannerWidget )
|
||||
DECLARE_EVENT_TABLE()
|
||||
|
||||
public:
|
||||
/// Constructors
|
||||
ScannerWidget();
|
||||
ScannerWidget( wxWindow* parent, wxWindowID id = SYMBOL_SCANNERWIDGET_IDNAME, const wxPoint& pos = SYMBOL_SCANNERWIDGET_POSITION, const wxSize& size = SYMBOL_SCANNERWIDGET_SIZE, long style = SYMBOL_SCANNERWIDGET_STYLE );
|
||||
|
||||
/// Creation
|
||||
bool Create( wxWindow* parent, wxWindowID id = SYMBOL_SCANNERWIDGET_IDNAME, const wxPoint& pos = SYMBOL_SCANNERWIDGET_POSITION, const wxSize& size = SYMBOL_SCANNERWIDGET_SIZE, long style = SYMBOL_SCANNERWIDGET_STYLE );
|
||||
|
||||
/// Destructor
|
||||
~ScannerWidget();
|
||||
|
||||
/// Initialises member variables
|
||||
void Init();
|
||||
|
||||
/// Creates the controls and sizers
|
||||
void CreateControls();
|
||||
|
||||
////@begin ScannerWidget event handler declarations
|
||||
|
||||
////@end ScannerWidget event handler declarations
|
||||
|
||||
////@begin ScannerWidget member function declarations
|
||||
|
||||
/// Retrieves bitmap resources
|
||||
wxBitmap GetBitmapResource( const wxString& name );
|
||||
|
||||
/// Retrieves icon resources
|
||||
wxIcon GetIconResource( const wxString& name );
|
||||
////@end ScannerWidget member function declarations
|
||||
|
||||
/// Should we show tooltips?
|
||||
static bool ShowToolTips();
|
||||
|
||||
////@begin ScannerWidget member variables
|
||||
wxStaticText* lblImageType;
|
||||
wxComboBox* cmbOutputType;
|
||||
wxButton* btnRefreshDevices;
|
||||
wxStaticText* lblDevices;
|
||||
wxComboBox* cmbDevices;
|
||||
wxStaticText* lblSource;
|
||||
wxComboBox* cmbSource;
|
||||
wxStaticText* lblMode;
|
||||
wxComboBox* cmbMode;
|
||||
wxStaticText* lblResolution;
|
||||
wxComboBox* cmbResolution;
|
||||
wxStaticText* lblPaperSize;
|
||||
wxComboBox* cmbPaperSize;
|
||||
////@end ScannerWidget member variables
|
||||
};
|
||||
|
||||
#endif
|
||||
// _SCANNERWIDGET_H_
|
||||
412
Resources/InsaneWidget/XInsaneWidget.cpp
Normal file
412
Resources/InsaneWidget/XInsaneWidget.cpp
Normal file
@@ -0,0 +1,412 @@
|
||||
/*
|
||||
* File: XInsaneWidget.cpp
|
||||
* Author: Saleem Edah-Tally - nmset@yandex.com
|
||||
* License : CeCILL-C
|
||||
* Copyright Saleem Edah-Tally - © 2025
|
||||
*
|
||||
* Created on 15 06 2025, 21:24
|
||||
*/
|
||||
|
||||
#include "XInsaneWidget.h"
|
||||
#include <PopupTransientWindow.h>
|
||||
#include <MiscTools.h>
|
||||
#include "PixelToImageWriter.h"
|
||||
#include "PixelToPdfWriter.h"
|
||||
#include <Common.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
// When device discovery in a detached thread completes.
|
||||
// ----------------------------------------------------------------------------
|
||||
class BackgroundScannerDiscoveryEVH : public BackgroundScannerDiscoveryEvent
|
||||
{
|
||||
public:
|
||||
BackgroundScannerDiscoveryEVH(XInsaneWidget * owner)
|
||||
{
|
||||
m_owner = owner;
|
||||
}
|
||||
virtual ~BackgroundScannerDiscoveryEVH()
|
||||
{}
|
||||
void OnDone() override
|
||||
{
|
||||
if (!m_owner)
|
||||
return;
|
||||
m_owner->CallAfter(&XInsaneWidget::EnableScanButton, true);
|
||||
}
|
||||
private:
|
||||
wxWeakRef<XInsaneWidget> m_owner = nullptr;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
class ScanProjectHandler : public InsaneWorkerEvent
|
||||
{
|
||||
public:
|
||||
ScanProjectHandler(XInsaneWidget * owner, TimeredStatusBar * sb = nullptr)
|
||||
: InsaneWorkerEvent(), m_owner(owner), m_sb (sb)
|
||||
{
|
||||
}
|
||||
/*
|
||||
* mode, outputType, adf, doubleSided, total, PaperSize:
|
||||
* These are not updated here if there are pending jobs.
|
||||
* However,
|
||||
* deviceId, source, sourceIndex, mode, resolution, paperSize
|
||||
* can be changed if there are pending jobs in ConfigureDevice() since it is
|
||||
* called before these setters. They won't change on their own but by user
|
||||
* interaction.
|
||||
*/
|
||||
void SetMode(const string& mode)
|
||||
{
|
||||
if (m_pixelFiles.size())
|
||||
return;
|
||||
m_mode = mode;
|
||||
}
|
||||
void SetOutputType(int outputType)
|
||||
{
|
||||
if (m_pixelFiles.size())
|
||||
return;
|
||||
m_outputType = outputType;
|
||||
}
|
||||
void SetADF(bool adf)
|
||||
{
|
||||
if (m_pixelFiles.size())
|
||||
return;
|
||||
m_adf = adf;
|
||||
if (m_adf && m_doubleSided)
|
||||
m_startPageIndex = -2;
|
||||
else
|
||||
m_startPageIndex = -1;
|
||||
}
|
||||
void SetDoubleSided(bool doubleSided)
|
||||
{
|
||||
if (m_pixelFiles.size())
|
||||
return;
|
||||
m_doubleSided = doubleSided;
|
||||
if (m_adf && m_doubleSided)
|
||||
m_startPageIndex = -2;
|
||||
else
|
||||
m_startPageIndex = -1;
|
||||
}
|
||||
void SetTotalNumberOfSides(uint total)
|
||||
{
|
||||
if (m_pixelFiles.size())
|
||||
return;
|
||||
m_total = total;
|
||||
m_totalEven = total;
|
||||
if (total % 2)
|
||||
m_totalEven = total + 1;
|
||||
}
|
||||
void SetPaperSize(const wxString& paperSize)
|
||||
{
|
||||
if (m_pixelFiles.size())
|
||||
return;
|
||||
m_paperSize = paperSize;
|
||||
}
|
||||
std::pair<int, int> GetStartAndIncrement(InsaneWorker * insaneWorker)
|
||||
{
|
||||
wxASSERT_MSG(insaneWorker != nullptr, "insaneWorker is NULL.");
|
||||
std::pair<int, int> startAndIncrement = insaneWorker->UpdateStartAndIncrement(m_startPageIndex, m_increment,
|
||||
m_adf, m_doubleSided, m_total);
|
||||
m_startPageIndex = startAndIncrement.first;
|
||||
m_increment = startAndIncrement.second;
|
||||
return startAndIncrement;
|
||||
}
|
||||
void OnInsaneError ( const std::string& message ) override
|
||||
{
|
||||
cerr << message << endl;
|
||||
Reset();
|
||||
MiscTools::MessageBox(_("A scan library error occurred."), true);
|
||||
}
|
||||
void OnError ( const std::string& message ) override
|
||||
{
|
||||
cerr << message << endl;
|
||||
Reset();
|
||||
MiscTools::MessageBox(_("A general error occurred."), true);
|
||||
}
|
||||
void OnSessionReadError(const std::string & filePath) override
|
||||
{
|
||||
const wxString msg = _("A session read error occurred.");
|
||||
cerr << msg << endl;
|
||||
Reset();
|
||||
MiscTools::MessageBox(msg, true);
|
||||
}
|
||||
void OnSessionCancelled(const std::string & filePath) override
|
||||
{
|
||||
const wxString msg = _("Session cancelled.");
|
||||
Reset();
|
||||
MiscTools::MessageBox(msg, true);
|
||||
}
|
||||
// Every time a page is fully scanned.
|
||||
void OnPageEndScan(const std::string & filePath, uint pageIndex,
|
||||
const ImageAttributes& imageAttributes) override
|
||||
{
|
||||
m_startPageIndex = pageIndex;
|
||||
m_pixelFiles[pageIndex] = {filePath, imageAttributes};
|
||||
|
||||
auto informProgress = [&] ()
|
||||
{
|
||||
if (!m_sb || (m_total == 1))
|
||||
return;
|
||||
int max = (m_adf && m_doubleSided) ? m_totalEven : m_total;
|
||||
wxString progress = to_string(m_pixelFiles.size()) + "/" + to_string(max);
|
||||
wxString info = _("Scanning: ");
|
||||
if (m_increment == 2)
|
||||
info = _("Front face: ");
|
||||
else if (m_increment == -2)
|
||||
info = _("Back face: ");
|
||||
wxString msg = info + progress;
|
||||
if (m_increment == 2 && ((max / 2) == (m_pixelFiles.size())))
|
||||
{
|
||||
wxString upperBoundMessage = _(". Turn the whole stack of pages.");
|
||||
msg += upperBoundMessage;
|
||||
}
|
||||
|
||||
m_sb->SetStatusText(msg);
|
||||
};
|
||||
|
||||
if (m_outputType != PDF)
|
||||
{
|
||||
// Convert pixel file to PNG using netpbm.
|
||||
if (!PixelToImageWriter::Convert(filePath, imageAttributes.width, imageAttributes.height, m_outputType))
|
||||
{
|
||||
const wxString msg = _("Failed to create output image.");
|
||||
cerr << msg << endl;
|
||||
if (m_sb)
|
||||
m_sb->SetTransientText(msg);
|
||||
}
|
||||
wxRemoveFile(filePath);
|
||||
informProgress();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Append or insert PDF page from pixel file using PoDoFo.
|
||||
if (!m_pixelToPdfWriter.get())
|
||||
m_pixelToPdfWriter = std::unique_ptr<PixelToPdfWriter> (new PixelToPdfWriter());
|
||||
uint index = (m_increment > 0) // 1 or 2
|
||||
? m_pixelToPdfWriter->GetNumberOfPages() // Append.
|
||||
: m_totalEven - m_pixelToPdfWriter->GetNumberOfPages(); // Insert.
|
||||
PoDoFo::PdfPageSize pageSize = m_pixelToPdfWriter->GetPageSize(m_paperSize.ToStdString());
|
||||
if (pageSize == PoDoFo::PdfPageSize::Unknown)
|
||||
{
|
||||
const wxString msg = _("Wrong paper size: ") + m_paperSize + _("; using A4.");
|
||||
cerr << msg << endl;
|
||||
pageSize = PoDoFo::PdfPageSize::A4;
|
||||
}
|
||||
if (!m_pixelToPdfWriter->AddPageAt(filePath, imageAttributes.width, imageAttributes.height, index, pageSize))
|
||||
{
|
||||
const wxString msg = _("Failed to add page to PDF document.");
|
||||
cerr << msg << endl;
|
||||
if (m_sb)
|
||||
m_sb->SetTransientText(msg);
|
||||
}
|
||||
wxRemoveFile(filePath);
|
||||
informProgress();
|
||||
}
|
||||
}
|
||||
void OnEndScanSession(uint pageIndex, const ImageAttributes & imageAttributes) override
|
||||
{
|
||||
int max = (m_adf && m_doubleSided) ? m_totalEven : m_total;
|
||||
// A special case is made for (total == 1): double-sided does not have meaning.
|
||||
if (m_total == 1)
|
||||
max = m_total;
|
||||
if (m_pixelFiles.size() >= max)
|
||||
{
|
||||
// All pages have been scanned, accounting for ADF and double-sided.
|
||||
if (m_outputType != PDF)
|
||||
{
|
||||
// Remove the last image if an odd number of pages was requested.
|
||||
if (m_increment != 1 && (m_total != m_totalEven))
|
||||
{
|
||||
const string filePath = std::get<0> (m_pixelFiles.rbegin()->second) + "." + Extensions[m_outputType];
|
||||
wxRemoveFile(filePath);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Remove the last page if an odd number of pages was requested.
|
||||
if (m_increment != 1 && (m_total != m_totalEven))
|
||||
{
|
||||
uint lastIndex = m_pixelFiles.end()->first;
|
||||
m_pixelToPdfWriter->RemovePageAt(lastIndex - 1);
|
||||
}
|
||||
const string filePath = m_owner->txtNewDoc->GetValue().ToStdString() + "." + Extensions[m_outputType];
|
||||
m_pixelToPdfWriter->Save(filePath);
|
||||
m_pixelToPdfWriter.reset((new PixelToPdfWriter())); // For next scan project.
|
||||
}
|
||||
Reset();
|
||||
m_owner->txtNewDoc->Clear();
|
||||
if (m_sb)
|
||||
{
|
||||
const wxString msg = _("Finished.");
|
||||
m_sb->SetTransientText(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
void Reset()
|
||||
{
|
||||
// Don't reset calculated variables that depend on widgets.
|
||||
m_startPageIndex = 0;
|
||||
m_increment = 1;
|
||||
m_totalEven = 0;
|
||||
m_pixelFiles.clear();
|
||||
}
|
||||
|
||||
private:
|
||||
wxWeakRef<XInsaneWidget> m_owner = nullptr;
|
||||
wxWeakRef<TimeredStatusBar> m_sb = nullptr;
|
||||
std::unique_ptr<PixelToPdfWriter> m_pixelToPdfWriter;
|
||||
PixelFilesMap m_pixelFiles;
|
||||
string m_mode = "Color";
|
||||
uint m_outputType = PDF;
|
||||
wxString m_paperSize = _T("A4");
|
||||
bool m_adf = false;
|
||||
bool m_doubleSided = false;
|
||||
int m_total = 0;
|
||||
int m_totalEven = 0;
|
||||
int m_startPageIndex = 0;
|
||||
int m_increment = 1;
|
||||
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
XInsaneWidget::XInsaneWidget(wxWindow* parent, TimeredStatusBar * sb, wxConfig * config, wxWindowID id, const wxPoint& pos, const wxSize& size, long style)
|
||||
: InsaneWidget(parent, id, pos, size, style)
|
||||
{
|
||||
UpdateExtensionsMap();
|
||||
m_config = config;
|
||||
m_sb = sb;
|
||||
lblNewDoc->Bind ( wxEVT_RIGHT_UP, &XInsaneWidget::OnLblNewDocRightClick, this );
|
||||
txtNewDoc->Bind ( wxEVT_KEY_UP, &XInsaneWidget::OnTxtNewDocKeyPressed, this );
|
||||
|
||||
m_ptwScannerWidget = std::unique_ptr<wxPopupTransientWindow> (new wxPopupTransientWindow ( wxApp::GetGUIInstance()->GetTopWindow() ));
|
||||
m_ptwScannerWidget->Show ( false );
|
||||
m_scanProject = std::make_unique<ScanProjectHandler>(this, m_sb);
|
||||
m_insaneWorker = std::make_unique<InsaneWorker>(m_scanProject.get());
|
||||
m_scannerWidget = std::make_unique<XScannerWidget> ( m_ptwScannerWidget.get(), m_sb, m_insaneWorker.get() );
|
||||
m_scannerWidget->SetConfig ( m_config );
|
||||
|
||||
btnScan->Enable(false);
|
||||
btnScan->Bind ( wxEVT_RIGHT_UP, &XInsaneWidget::OnBtnScanRightClick, this );
|
||||
btnScan->Bind ( wxEVT_LEFT_UP, &XInsaneWidget::OnBtnScanClick, this );
|
||||
m_backgroundScannerDiscoveryEvh = std::make_unique<BackgroundScannerDiscoveryEVH>(this);
|
||||
BackgroundScannerDiscovery * backgroundDiscovery = new BackgroundScannerDiscovery ( m_scannerWidget.get(),
|
||||
m_backgroundScannerDiscoveryEvh.get());
|
||||
backgroundDiscovery->Run();
|
||||
}
|
||||
|
||||
XInsaneWidget::~XInsaneWidget() = default; // Important for mixing unique_ptr and PIMPL.
|
||||
|
||||
// Show a popup to specifiy the number of pages to scan and back-sided scanning.
|
||||
void XInsaneWidget::OnLblNewDocRightClick ( wxMouseEvent& evt )
|
||||
{
|
||||
/*
|
||||
* The previous ConfigEditorPopup is deleted here, which commits the
|
||||
* parameters to the config file. At any time, the current parameter values
|
||||
* can be lost if a crash occurs.
|
||||
*/
|
||||
m_pageStack.reset(new ConfigEditorPopup(wxApp::GetGUIInstance()->GetTopWindow(), m_config));
|
||||
PopupTransientWindow * ptw = m_pageStack->CreatePopup();
|
||||
if ( !ptw )
|
||||
{
|
||||
evt.Skip();
|
||||
return;
|
||||
}
|
||||
wxCheckBox * cb = m_pageStack->AddCheckBox (_("Double sided:"),_T("/Scanner/DoubleSided") );
|
||||
cb->SetToolTip (_("Scan all front faces first, then all back faces in reverse order.") );
|
||||
wxSpinCtrl * spn = m_pageStack->AddSpinCtrl (_("Total:"),_T("/Scanner/Total") );
|
||||
spn->SetRange ( 1, 50 );
|
||||
spn->SetToolTip (_("Total number of sides to scan (not total number of sheets).") );
|
||||
m_pageStack->ShowPopup();
|
||||
evt.Skip();
|
||||
}
|
||||
|
||||
void XInsaneWidget::OnTxtNewDocKeyPressed ( wxKeyEvent& evt )
|
||||
{
|
||||
if ( evt.GetKeyCode() == WXK_BACK )
|
||||
{
|
||||
txtNewDoc->Clear();
|
||||
}
|
||||
evt.Skip();
|
||||
}
|
||||
|
||||
// Show the scanner widget.
|
||||
void XInsaneWidget::OnBtnScanRightClick ( wxMouseEvent& evt )
|
||||
{
|
||||
if ( m_scannerWidget->cmbDevices->GetCount() )
|
||||
{
|
||||
const wxSize current = m_scannerWidget->GetSize();
|
||||
m_scannerWidget->SetSize ( wxSize ( 500, current.GetHeight() ) );
|
||||
}
|
||||
MiscTools::ShowTransientPopup ( m_ptwScannerWidget.get(), m_scannerWidget.get() );
|
||||
evt.Skip();
|
||||
}
|
||||
|
||||
// Start scanning.
|
||||
void XInsaneWidget::OnBtnScanClick ( wxMouseEvent& evt )
|
||||
{
|
||||
const wxString dest = txtNewDoc->GetValue();
|
||||
if (dest.IsEmpty())
|
||||
{
|
||||
MiscTools::MessageBox(_("Destination file missing."), true);
|
||||
evt.Skip();
|
||||
return;
|
||||
}
|
||||
const uint outputType = m_scannerWidget->GetScannerOutputType();
|
||||
bool adf = false;
|
||||
bool doubleSided = false;
|
||||
uint total = 1;
|
||||
wxString paperSize = _T("A4");
|
||||
if (m_config)
|
||||
{
|
||||
doubleSided = m_config->ReadBool("/Scanner/DoubleSided", false);
|
||||
total = m_config->ReadLong("/Scanner/Total", 1);
|
||||
m_config->Read("/Scanner/Last/PaperSize", &paperSize, "A4");
|
||||
}
|
||||
|
||||
wxFileName destFile(dest);
|
||||
const string deviceId = m_scannerWidget->GetCurrentDeviceId().ToStdString();
|
||||
const std::pair<int, wxString> sourceAttributes = m_scannerWidget->GetScannerSource();
|
||||
const string source = sourceAttributes.second.ToStdString();
|
||||
const string mode = m_scannerWidget->GetScannerMode().ToStdString();
|
||||
int resolution = 300;
|
||||
if ( !m_scannerWidget->GetScannerResolution().IsEmpty() )
|
||||
{
|
||||
resolution = std::stoi ( m_scannerWidget->GetScannerResolution().ToStdString() );
|
||||
}
|
||||
int sourceIndex = sourceAttributes.first == wxNOT_FOUND
|
||||
? 0 : sourceAttributes.first;
|
||||
adf = m_insaneWorker->IsADF(deviceId, sourceIndex);
|
||||
if (m_insaneWorker->ConfigureDevice(deviceId, source, sourceIndex, mode, resolution, paperSize.ToStdString()))
|
||||
{
|
||||
m_scanProject->SetADF(adf);
|
||||
m_scanProject->SetMode(mode);
|
||||
m_scanProject->SetOutputType(outputType);
|
||||
m_scanProject->SetPaperSize(paperSize);
|
||||
m_scanProject->SetDoubleSided(doubleSided);
|
||||
m_scanProject->SetTotalNumberOfSides(total);
|
||||
|
||||
std::pair<int, int> startAndIncrement = m_scanProject->GetStartAndIncrement(m_insaneWorker.get());
|
||||
|
||||
const int padWidth = ( ushort ) m_config->Read (_T("/Scanner/Counter/Length"), 2 );
|
||||
bool res = m_insaneWorker->Scan(destFile.GetPath().ToStdString(),
|
||||
destFile.GetName().ToStdString(),
|
||||
startAndIncrement.first, padWidth, startAndIncrement.second);
|
||||
}
|
||||
evt.Skip();
|
||||
}
|
||||
|
||||
void XInsaneWidget::ResetScanProject()
|
||||
{
|
||||
if (m_scanProject)
|
||||
m_scanProject->Reset();
|
||||
}
|
||||
|
||||
void XInsaneWidget::CancelScanning()
|
||||
{
|
||||
if (m_insaneWorker)
|
||||
m_insaneWorker->Cancel();
|
||||
}
|
||||
|
||||
void XInsaneWidget::EnableScanButton(bool enable)
|
||||
{
|
||||
btnScan->Enable(enable);
|
||||
}
|
||||
81
Resources/InsaneWidget/XInsaneWidget.h
Normal file
81
Resources/InsaneWidget/XInsaneWidget.h
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* File: XInsaneWidget.h
|
||||
* Author: Saleem Edah-Tally - nmset@yandex.com
|
||||
* License : CeCILL-C
|
||||
* Copyright Saleem Edah-Tally - © 2025
|
||||
*
|
||||
* Created on 15 06 2025, 21:24
|
||||
*/
|
||||
|
||||
#ifndef XINSANEWIDGET_H
|
||||
#define XINSANEWIDGET_H
|
||||
|
||||
#include <wx/wx.h>
|
||||
#include <wx/config.h>
|
||||
#include <wx/popupwin.h>
|
||||
#include <InsaneWidget.h>
|
||||
#include <InsaneWorker.h>
|
||||
#include <XScannerWidget.h>
|
||||
#include <TimeredStatusBar.h>
|
||||
#include <ConfigEditorPopup.h>
|
||||
#include <memory>
|
||||
|
||||
class BackgroundScannerDiscoveryEVH;
|
||||
class ScanProjectHandler; // An event handler extending InsaneWorkerEvent.
|
||||
|
||||
// Page index (not page number), {pixel file path, {pixel count, image width, image height}}.
|
||||
typedef std::map<uint, std::tuple<std::string, InsaneWorkerEvent::ImageAttributes>> PixelFilesMap;
|
||||
|
||||
/**
|
||||
* Shows a label, a disabled text box and a button.
|
||||
*
|
||||
* Label:
|
||||
* - Right click: define the number of pages to scan and double-sided scanning.
|
||||
* - Number of pages: it's the number of sides, not the number of sheets.
|
||||
* - Backface: if an automatic document feeder is used. If 5 pages are to be
|
||||
* scanned, feed 3 pages on front face, turn the whole stack including the
|
||||
* 6th page to scan the backfaces; the last page will be discarded.
|
||||
* With a feeder, the 'double-sided' option can be off if all backfaces
|
||||
* are blank.
|
||||
* With a flatbed scanner, the 'double-sided' should typically be off and
|
||||
* the pages scanned in their logical order.
|
||||
*
|
||||
* Text box:
|
||||
* - shows the path and the basename of the files to create. This must be set
|
||||
* by the application in any conveniant manner.
|
||||
* Pressing the backspace key clears the text box.
|
||||
*
|
||||
* Button:
|
||||
* - Right click: shows the scanner widget.
|
||||
* - Left click: starts scanning.
|
||||
*/
|
||||
class XInsaneWidget : public InsaneWidget
|
||||
{
|
||||
public:
|
||||
virtual ~XInsaneWidget();
|
||||
XInsaneWidget( wxWindow* parent, TimeredStatusBar * sb, wxConfig * config, wxWindowID id = SYMBOL_INSANEWIDGET_IDNAME, const wxPoint& pos = SYMBOL_INSANEWIDGET_POSITION, const wxSize& size = SYMBOL_INSANEWIDGET_SIZE, long style = SYMBOL_INSANEWIDGET_STYLE );
|
||||
|
||||
void ResetScanProject();
|
||||
void CancelScanning(); // Not tested, probably doesn't work as intended.
|
||||
void EnableScanButton(bool enable); // For CallAfter.
|
||||
private:
|
||||
wxConfig * m_config;
|
||||
wxWeakRef<TimeredStatusBar> m_sb;
|
||||
|
||||
// Contains a popup to define the number of pages and double-sided scanning.
|
||||
std::unique_ptr<ConfigEditorPopup> m_pageStack;
|
||||
// Contains the scanner widget.
|
||||
std::unique_ptr<wxPopupTransientWindow> m_ptwScannerWidget;
|
||||
// Available devices and minimal options.
|
||||
std::unique_ptr<XScannerWidget> m_scannerWidget;
|
||||
std::unique_ptr<InsaneWorker> m_insaneWorker;
|
||||
std::unique_ptr<BackgroundScannerDiscoveryEVH> m_backgroundScannerDiscoveryEvh;
|
||||
std::unique_ptr<ScanProjectHandler> m_scanProject;
|
||||
|
||||
void OnLblNewDocRightClick ( wxMouseEvent& evt );
|
||||
void OnTxtNewDocKeyPressed ( wxKeyEvent& evt );
|
||||
void OnBtnScanRightClick ( wxMouseEvent& evt );
|
||||
void OnBtnScanClick ( wxMouseEvent& evt );
|
||||
};
|
||||
|
||||
#endif // XINSANEWIDGET_H
|
||||
318
Resources/InsaneWidget/XScannerWidget.cpp
Normal file
318
Resources/InsaneWidget/XScannerWidget.cpp
Normal file
@@ -0,0 +1,318 @@
|
||||
/*
|
||||
* File: XScannerWidget.cpp
|
||||
* Author: Saleem Edah-Tally - nmset@yandex.com
|
||||
* License: CeCILL-C
|
||||
* Copyright Saleem Edah-Tally - © 2024
|
||||
*
|
||||
* Created on ?
|
||||
*/
|
||||
|
||||
#include "XScannerWidget.h"
|
||||
#include "XClientData.hpp"
|
||||
#include "Common.h"
|
||||
#include <libinsane/constants.h>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
|
||||
XScannerWidget::~XScannerWidget()
|
||||
{}
|
||||
|
||||
XScannerWidget::XScannerWidget ( wxWindow* parent, TimeredStatusBar * sb,
|
||||
InsaneWorker * insaneWorker,
|
||||
wxWindowID id, const wxPoint& pos, const wxSize& size, long int style )
|
||||
: ScannerWidget ( parent, id, pos, size, style )
|
||||
{
|
||||
UpdateExtensionsMap();
|
||||
m_sb = sb;
|
||||
m_insaneWorker = insaneWorker;
|
||||
if (m_insaneWorker)
|
||||
m_insaneWorkerEvh = m_insaneWorker->GetEventHandler();
|
||||
cmbOutputType->Append (Extensions[PDF]); // Use the file extension and the enum index without client data.
|
||||
#if wxUSE_LIBPNG
|
||||
cmbOutputType->Append (Extensions[PNG]);
|
||||
#endif
|
||||
#if wxUSE_LIBJPEG
|
||||
cmbOutputType->Append (Extensions[JPEG]);
|
||||
#endif
|
||||
#if wxUSE_LIBTIFF
|
||||
cmbOutputType->Append (Extensions[TIFF]);
|
||||
#endif
|
||||
#if wxUSE_PNM
|
||||
cmbOutputType->Append (Extensions[PNM]);
|
||||
#endif
|
||||
// Paper sizes handled by podofo.
|
||||
cmbPaperSize->Append(wxArrayString({"A0", "A1", "A2", "A3", "A4", "A5", "A6",
|
||||
"Letter", "Legal", "Tabloid"}));
|
||||
|
||||
btnRefreshDevices->Bind ( wxEVT_COMMAND_BUTTON_CLICKED, &XScannerWidget::OnButtonRefreshDevices, this );
|
||||
cmbDevices->Bind ( wxEVT_COMMAND_COMBOBOX_SELECTED, &XScannerWidget::OnDeviceSelected, this );
|
||||
cmbOutputType->Bind ( wxEVT_COMMAND_COMBOBOX_SELECTED, &XScannerWidget::OnImageTypeSelected, this );
|
||||
cmbSource->Bind ( wxEVT_COMMAND_COMBOBOX_SELECTED, &XScannerWidget::OnSourceSelected, this );
|
||||
cmbMode->Bind ( wxEVT_COMMAND_COMBOBOX_SELECTED, &XScannerWidget::OnModeSelected, this );
|
||||
cmbResolution->Bind ( wxEVT_COMMAND_COMBOBOX_SELECTED, &XScannerWidget::OnResolutionSelected, this );
|
||||
cmbPaperSize->Bind ( wxEVT_COMMAND_COMBOBOX_SELECTED, &XScannerWidget::OnPaperSizeSelected, this );
|
||||
GetParent()->Bind ( wxEVT_SHOW, &XScannerWidget::OnActivated, this );
|
||||
}
|
||||
|
||||
bool XScannerWidget::FindDevices ( bool async )
|
||||
{
|
||||
if ( m_sb && !async )
|
||||
m_sb->SetTransientText (_("Searching for devices...") );
|
||||
if ( !m_insaneWorker->Init() )
|
||||
{
|
||||
const wxString msg = _("Could not initialise insane api.");
|
||||
cerr << msg << endl;
|
||||
if (m_insaneWorkerEvh)
|
||||
m_insaneWorkerEvh->OnInsaneError(msg.ToStdString());
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<InsaneWorker::DeviceDescriptor> devices = m_insaneWorker->GetDeviceDescriptors();
|
||||
|
||||
CallAfter ( &XScannerWidget::ClearScannerItems );
|
||||
uint numberOfDevices = devices.size();
|
||||
|
||||
for ( uint i = 0; i < numberOfDevices; i++ )
|
||||
{
|
||||
InsaneWorker::DeviceDescriptor device = devices.at(i);
|
||||
CallAfter ( &XScannerWidget::AppendScannerItem, device.GetLabel(), device.id );
|
||||
}
|
||||
|
||||
if ( m_sb )
|
||||
{
|
||||
const wxString msg = wxVariant ( ( long ) numberOfDevices ).GetString() + _(" device(s) found.");
|
||||
// Should be but don't : it's as if the above code has not been run.
|
||||
// m_sb->CallAfter(&TimeredStatusBar::SetTransientText, msg, 3000);
|
||||
m_sb->SetTransientText(msg);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void XScannerWidget::AppendScannerItem ( const wxString& display, const wxString& clientData )
|
||||
{
|
||||
cmbDevices->Append ( display, new XClientData ( clientData ) );
|
||||
}
|
||||
|
||||
void XScannerWidget::ClearScannerItems()
|
||||
{
|
||||
cmbDevices->Clear();
|
||||
cmbSource->Clear();
|
||||
cmbMode->Clear();
|
||||
cmbResolution->Clear();
|
||||
}
|
||||
|
||||
void XScannerWidget::OnButtonRefreshDevices ( wxCommandEvent& evt )
|
||||
{
|
||||
btnRefreshDevices->Enable ( false );
|
||||
m_insaneWorker->Init();
|
||||
FindDevices();
|
||||
evt.Skip();
|
||||
btnRefreshDevices->Enable ( true );
|
||||
}
|
||||
|
||||
void XScannerWidget::SetConfig ( wxFileConfig* config )
|
||||
{
|
||||
m_config = config;
|
||||
if ( !m_config )
|
||||
return;
|
||||
|
||||
wxString lastImageType;
|
||||
m_config->Read (_T("/Scanner/Last/OutputType"), &lastImageType );
|
||||
if ( cmbOutputType->FindString ( lastImageType, true ) != wxNOT_FOUND )
|
||||
cmbOutputType->SetStringSelection ( lastImageType );
|
||||
else
|
||||
cmbOutputType->Select(0);
|
||||
|
||||
wxString lastPaperSize;
|
||||
m_config->Read (_T("/Scanner/Last/PaperSize"), &lastPaperSize );
|
||||
if ( cmbPaperSize->FindString ( lastPaperSize, true ) != wxNOT_FOUND )
|
||||
cmbPaperSize->SetStringSelection ( lastPaperSize );
|
||||
else
|
||||
cmbPaperSize->Select(4);
|
||||
}
|
||||
|
||||
|
||||
void XScannerWidget::OnDeviceSelected ( wxCommandEvent& evt )
|
||||
{
|
||||
if ( !m_config || ( cmbDevices->GetSelection() == wxNOT_FOUND ) )
|
||||
return;
|
||||
|
||||
int currentSelection = cmbDevices->GetCurrentSelection();
|
||||
if ( currentSelection == wxNOT_FOUND )
|
||||
return;
|
||||
XClientData * lastDevice = static_cast<XClientData*> ( cmbDevices->GetClientObject ( currentSelection ) );
|
||||
if ( !lastDevice )
|
||||
return;
|
||||
m_config->Write ( "/Scanner/Last/Device", lastDevice->GetData().GetString() );
|
||||
m_config->Flush();
|
||||
UpdateScannerOptions ( lastDevice->GetData().GetString() );
|
||||
}
|
||||
|
||||
void XScannerWidget::OnImageTypeSelected ( wxCommandEvent& evt )
|
||||
{
|
||||
if ( !m_config )
|
||||
return;
|
||||
|
||||
m_config->Write ( "/Scanner/Last/OutputType", cmbOutputType->GetStringSelection() );
|
||||
m_config->Flush();
|
||||
}
|
||||
|
||||
void XScannerWidget::OnSourceSelected ( wxCommandEvent& evt )
|
||||
{
|
||||
if ( !m_config )
|
||||
return;
|
||||
const wxString deviceId = GetCurrentDeviceId();
|
||||
if ( wxIsEmpty ( deviceId ) )
|
||||
return;
|
||||
const wxString key =_T("/Scanner/") + deviceId +_T("/") + _T ( OPT_NAME_SOURCE );
|
||||
m_config->Write ( key, cmbSource->GetStringSelection() );
|
||||
m_config->Flush();
|
||||
}
|
||||
|
||||
void XScannerWidget::OnModeSelected ( wxCommandEvent& evt )
|
||||
{
|
||||
if ( !m_config )
|
||||
return;
|
||||
const wxString deviceId = GetCurrentDeviceId();
|
||||
if ( wxIsEmpty ( deviceId ) )
|
||||
return;
|
||||
const wxString key =_T("/Scanner/") + deviceId +_T("/") + _T ( OPT_NAME_MODE );
|
||||
m_config->Write ( key, cmbMode->GetStringSelection() );
|
||||
m_config->Flush();
|
||||
}
|
||||
|
||||
void XScannerWidget::OnResolutionSelected ( wxCommandEvent& evt )
|
||||
{
|
||||
if ( !m_config )
|
||||
return;
|
||||
const wxString deviceId = GetCurrentDeviceId();
|
||||
if ( wxIsEmpty ( deviceId ) )
|
||||
return;
|
||||
const wxString key =_T("/Scanner/") + deviceId +_T("/") + _T ( OPT_NAME_RESOLUTION );
|
||||
m_config->Write ( key, cmbResolution->GetStringSelection() );
|
||||
m_config->Flush();
|
||||
}
|
||||
|
||||
void XScannerWidget::OnPaperSizeSelected(wxCommandEvent& evt)
|
||||
{
|
||||
if ( !m_config )
|
||||
return;
|
||||
|
||||
m_config->Write ( "/Scanner/Last/PaperSize", cmbPaperSize->GetStringSelection() );
|
||||
m_config->Flush();
|
||||
}
|
||||
|
||||
void XScannerWidget::UpdateScannerOptions ( const wxString& deviceId )
|
||||
{
|
||||
if ( wxIsEmpty ( deviceId ) )
|
||||
return;
|
||||
|
||||
auto addListConstrainedOptions = [&] ( wxComboBox * cmb, const wxString& lastKey )
|
||||
{
|
||||
if (!cmb)
|
||||
return;
|
||||
cmb->Clear();
|
||||
vector<string> possible;
|
||||
const string defaultValue = m_insaneWorker->GetOptionPossibleValues(deviceId.ToStdString(), lastKey.ToStdString(), possible);
|
||||
for (string itemValue : possible)
|
||||
{
|
||||
cmb->Append(itemValue);
|
||||
}
|
||||
cmb->Enable(cmb->GetCount());
|
||||
if ( m_config )
|
||||
{
|
||||
wxString savedValue;
|
||||
const wxString key =_T("Scanner/") + deviceId +_T("/") + lastKey;
|
||||
m_config->Read ( key, &savedValue );
|
||||
if ( !savedValue.IsEmpty() )
|
||||
{
|
||||
cmb->SetStringSelection ( savedValue );
|
||||
return;
|
||||
}
|
||||
}
|
||||
cmb->SetStringSelection ( defaultValue );
|
||||
};
|
||||
|
||||
/*
|
||||
* For a device with flatbed and ADF, there are multiple sources, each with a name.
|
||||
* The display name obtained here is different from the child devices of lis_item.
|
||||
* Each child item is a source. The root item must not be used for scanning
|
||||
* following the documentation. Fortunately, they are listed in the same order
|
||||
* with both enumerations.
|
||||
* Ex: Brother DCP-L8410CDW
|
||||
* 0 - FlatBed - flatbed
|
||||
* 1 - Automatic Document Feeder(left aligned) - feeder(left aligned)
|
||||
* 2 - Automatic Document Feeder(centrally aligned) - feeder(centrally aligned)
|
||||
* We must therefore select a source by its index.
|
||||
*/
|
||||
addListConstrainedOptions(cmbSource, OPT_NAME_SOURCE);
|
||||
addListConstrainedOptions(cmbMode, OPT_NAME_MODE);
|
||||
addListConstrainedOptions(cmbResolution, OPT_NAME_RESOLUTION);
|
||||
}
|
||||
|
||||
|
||||
wxString XScannerWidget::GetCurrentDeviceId() const
|
||||
{
|
||||
int currentSelection = cmbDevices->GetCurrentSelection();
|
||||
if ( currentSelection == wxNOT_FOUND )
|
||||
return wxEmptyString;
|
||||
XClientData * clientData = static_cast<XClientData*> ( cmbDevices->GetClientObject ( currentSelection ) );
|
||||
if ( !clientData )
|
||||
return wxEmptyString;
|
||||
return clientData->GetData().GetString();
|
||||
}
|
||||
|
||||
void XScannerWidget::OnActivated ( wxShowEvent& evt )
|
||||
{
|
||||
if ( evt.IsShown() && cmbDevices->GetCount() && cmbDevices->GetCurrentSelection() == wxNOT_FOUND )
|
||||
{
|
||||
if ( m_config )
|
||||
{
|
||||
wxString lastDevice;
|
||||
m_config->Read (_T("/Scanner/Last/Device"), &lastDevice );
|
||||
if ( lastDevice.IsEmpty() || !cmbDevices->GetCount() )
|
||||
{
|
||||
evt.Skip();
|
||||
return;
|
||||
}
|
||||
|
||||
for ( uint i = 0; i < cmbDevices->GetCount(); i++ )
|
||||
{
|
||||
XClientData * clientData = static_cast<XClientData*> ( cmbDevices->GetClientObject ( i ) );
|
||||
if ( !clientData )
|
||||
continue;
|
||||
if ( clientData->GetData().GetString() == lastDevice )
|
||||
{
|
||||
cmbDevices->Select ( i );
|
||||
UpdateScannerOptions ( lastDevice );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
evt.Skip();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
wxThread::ExitCode BackgroundScannerDiscovery::Entry()
|
||||
{
|
||||
if (m_owner)
|
||||
{
|
||||
m_owner->FindDevices ( true );
|
||||
wxShowEvent evt;
|
||||
evt.SetShow ( true );
|
||||
m_owner->OnActivated ( evt );
|
||||
if (m_evh)
|
||||
m_evh->OnDone();
|
||||
}
|
||||
return ( wxThread::ExitCode ) 0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void BackgroundScannerDiscoveryEvent::OnDone()
|
||||
{}
|
||||
|
||||
120
Resources/InsaneWidget/XScannerWidget.h
Normal file
120
Resources/InsaneWidget/XScannerWidget.h
Normal file
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* File: XScannerWidget.h
|
||||
* Author: Saleem Edah-Tally - nmset@yandex.com
|
||||
* License: CeCILL-C
|
||||
* Copyright Saleem Edah-Tally - © 2024
|
||||
*
|
||||
* Created on ?
|
||||
*/
|
||||
|
||||
#ifndef XSCANNERWIDGET_H
|
||||
#define XSCANNERWIDGET_H
|
||||
|
||||
#include <wx/wx.h>
|
||||
#include <wx/thread.h>
|
||||
#include <wx/config.h>
|
||||
#include <ScannerWidget.h>
|
||||
#include "TimeredStatusBar.h"
|
||||
#include "InsaneWorker.h"
|
||||
#include "Common.h"
|
||||
#include <map>
|
||||
|
||||
class BackgroundScannerDiscoveryEvent;
|
||||
|
||||
/**
|
||||
* Find available scanner devices, USB or network attached.\n
|
||||
* Show the devices and their minimal properties in a popup.\n
|
||||
* Make the properties available through API.\n
|
||||
* Specify output file format and page sizes.\n
|
||||
* All selections are saved and restored using wxConfig.\n
|
||||
* Devices can be searched in a detached thread, typically on application
|
||||
* startup.\n
|
||||
*/
|
||||
|
||||
class XScannerWidget : public ScannerWidget
|
||||
{
|
||||
friend class BackgroundScannerDiscovery;
|
||||
public:
|
||||
XScannerWidget() {};
|
||||
~XScannerWidget();
|
||||
|
||||
|
||||
XScannerWidget ( wxWindow* parent, TimeredStatusBar * sb,
|
||||
InsaneWorker * insaneWorker,
|
||||
wxWindowID id = wxID_ANY,
|
||||
const wxPoint& pos = wxDefaultPosition,
|
||||
const wxSize& size = SYMBOL_SCANNERWIDGET_SIZE,
|
||||
long int style = SYMBOL_SCANNERWIDGET_STYLE );
|
||||
|
||||
void SetConfig ( wxConfig * config );
|
||||
bool FindDevices ( bool async = false );
|
||||
wxString GetCurrentDeviceId() const;
|
||||
wxString GetScannerMode() const
|
||||
{
|
||||
return cmbMode->GetValue();
|
||||
}
|
||||
std::pair<int, wxString> GetScannerSource() const
|
||||
{
|
||||
return {cmbSource->GetCurrentSelection(), cmbSource->GetValue()};
|
||||
}
|
||||
wxString GetScannerResolution() const
|
||||
{
|
||||
return cmbResolution->GetValue();
|
||||
}
|
||||
uint GetScannerOutputType()
|
||||
{
|
||||
return cmbOutputType->GetCurrentSelection();
|
||||
}
|
||||
wxString GetPaperSize() const
|
||||
{
|
||||
return cmbPaperSize->GetValue();
|
||||
}
|
||||
|
||||
private:
|
||||
wxWeakRef<TimeredStatusBar> m_sb = nullptr;
|
||||
wxConfig * m_config = nullptr;
|
||||
|
||||
InsaneWorker * m_insaneWorker;
|
||||
InsaneWorkerEvent * m_insaneWorkerEvh;
|
||||
|
||||
void OnButtonRefreshDevices ( wxCommandEvent& evt );
|
||||
/*
|
||||
* For synchronous and asynchronous calls/
|
||||
*/
|
||||
void AppendScannerItem ( const wxString& display, const wxString& clientData );
|
||||
void ClearScannerItems();
|
||||
|
||||
void OnActivated ( wxShowEvent& evt );
|
||||
void OnImageTypeSelected ( wxCommandEvent& evt );
|
||||
void OnDeviceSelected ( wxCommandEvent& evt );
|
||||
void OnSourceSelected ( wxCommandEvent& evt );
|
||||
void OnModeSelected ( wxCommandEvent& evt );
|
||||
void OnResolutionSelected ( wxCommandEvent& evt );
|
||||
void OnPaperSizeSelected ( wxCommandEvent& evt );
|
||||
void UpdateScannerOptions ( const wxString& deviceId );
|
||||
};
|
||||
|
||||
// Asynchronous device discovery.
|
||||
class BackgroundScannerDiscovery : public wxThread
|
||||
{
|
||||
public:
|
||||
BackgroundScannerDiscovery ( XScannerWidget * owner, BackgroundScannerDiscoveryEvent * evh )
|
||||
{
|
||||
m_owner = owner;
|
||||
m_evh = evh;
|
||||
}
|
||||
virtual ~BackgroundScannerDiscovery() {};
|
||||
virtual ExitCode Entry();
|
||||
private:
|
||||
XScannerWidget * m_owner = nullptr;
|
||||
BackgroundScannerDiscoveryEvent * m_evh = nullptr;
|
||||
};
|
||||
|
||||
class BackgroundScannerDiscoveryEvent
|
||||
{
|
||||
public:
|
||||
virtual void OnDone();
|
||||
|
||||
};
|
||||
|
||||
#endif // XSCANNERWIDGET_H
|
||||
21
Resources/Lokalize/0_getstrings.sh
Executable file
21
Resources/Lokalize/0_getstrings.sh
Executable file
@@ -0,0 +1,21 @@
|
||||
#!/bin/bash
|
||||
if [ ! -x 0_getstrings.sh ]
|
||||
then
|
||||
echo "Wrong working directory. Please cd to the directory containing this script."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
COMPONENT_NAME=S7
|
||||
|
||||
SRC=../../
|
||||
DOMAIN=fr
|
||||
DEST=$DOMAIN/${COMPONENT_NAME}.po
|
||||
[ ! -d $DOMAIN ] && mkdir $DOMAIN
|
||||
[ -f $DEST ] && JOIN="-j"
|
||||
[ -f $DEST ] && cp $DEST $DEST.bak-$(date +%F-%T)
|
||||
[ ! -f $DEST ] && touch $DEST
|
||||
|
||||
xgettext --keyword=_ -d $DOMAIN $JOIN -o $DEST --c++ --from-code=UTF-8 $(find $SRC -type f -name "*.cpp")
|
||||
xgettext --keyword=_ -d $DOMAIN -j -o $DEST --c++ --from-code=UTF-8 $(find $SRC -type f -name "*.h")
|
||||
|
||||
exit 0
|
||||
14
Resources/Lokalize/2_makemo.sh
Executable file
14
Resources/Lokalize/2_makemo.sh
Executable file
@@ -0,0 +1,14 @@
|
||||
#!/bin/bash
|
||||
if [ ! -x 2_makemo.sh ]
|
||||
then
|
||||
echo "Wrong working directory. Please cd to the directory containing this script."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
DOMAIN=fr
|
||||
|
||||
COMPONENT_NAME=S7
|
||||
msgfmt $DOMAIN/${COMPONENT_NAME}.po -o $DOMAIN/${COMPONENT_NAME}.mo
|
||||
|
||||
exit 0
|
||||
|
||||
BIN
Resources/Lokalize/fr/CB7.mo
Normal file
BIN
Resources/Lokalize/fr/CB7.mo
Normal file
Binary file not shown.
302
Resources/Lokalize/fr/S7.po
Normal file
302
Resources/Lokalize/fr/S7.po
Normal file
@@ -0,0 +1,302 @@
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2025 Saleem EDAH-TALLY <set@nmset.info>
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-06-26 22:47+0200\n"
|
||||
"PO-Revision-Date: 2025-06-26 22:47+0200\n"
|
||||
"Last-Translator: Saleem EDAH-TALLY <set@nmset.info>\n"
|
||||
"Language-Team: French <kde-francophone@kde.org>\n"
|
||||
"Language: fr_FR\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
"X-Generator: Lokalize 25.04.2\n"
|
||||
|
||||
#: ../../Resources/UI/S7/s7.cpp:126 ../..//Resources/UI/S7/s7.cpp:126
|
||||
msgid ""
|
||||
"Select a destination directory.\n"
|
||||
"Double-click to go to the selected directory."
|
||||
msgstr ""
|
||||
"Choisissez un dossier destination\n"
|
||||
"Double-clic pour aller au dossier."
|
||||
|
||||
#: ../../Resources/UI/S7/s7.cpp:130 ../..//Resources/UI/S7/s7.cpp:130
|
||||
msgid "Basename"
|
||||
msgstr "Nom de base"
|
||||
|
||||
#: ../../Resources/UI/S7/s7.cpp:132 ../..//Resources/UI/S7/s7.cpp:132
|
||||
msgid ""
|
||||
"Specify a destination file basename (without extension).\n"
|
||||
"\n"
|
||||
"'CTRL + click' for about information."
|
||||
msgstr ""
|
||||
"Spécifiez un nom de base du fichier de destination (sans l'extension).\n"
|
||||
"\n"
|
||||
"'CTRL + clic' : à propos"
|
||||
|
||||
#: ../../Resources/InsaneWidget/UI/InsaneWidget.cpp:128
|
||||
msgid "New"
|
||||
msgstr "Nouveau"
|
||||
|
||||
#: ../../Resources/InsaneWidget/UI/InsaneWidget.cpp:130
|
||||
msgid "'Right' click to define a scan project."
|
||||
msgstr "Clic droit pour définir un projet de numérisation"
|
||||
|
||||
#: ../../Resources/InsaneWidget/UI/InsaneWidget.cpp:135
|
||||
msgid ""
|
||||
"Full path to destination file without the extension; it is determined by the "
|
||||
"output type."
|
||||
msgstr ""
|
||||
"Chemin complet du fichier de destination sans l'extension; elle est "
|
||||
"déterminée par le format de sortie."
|
||||
|
||||
#: ../../Resources/InsaneWidget/UI/InsaneWidget.cpp:138
|
||||
msgid "Scan"
|
||||
msgstr "Numériser"
|
||||
|
||||
#: ../../Resources/InsaneWidget/UI/InsaneWidget.cpp:140
|
||||
msgid ""
|
||||
"'Left click' to start the scan project.\n"
|
||||
"'Right click' to show the scanner widget."
|
||||
msgstr ""
|
||||
"'Clic gauche' pour démarrer la numérisation.\n"
|
||||
"'Clic droit' pour afficher les options du numériseur."
|
||||
|
||||
#: ../../Resources/InsaneWidget/UI/ScannerWidget.cpp:144
|
||||
msgid "Output document format"
|
||||
msgstr "Format du fichier de sortie"
|
||||
|
||||
#: ../../Resources/InsaneWidget/UI/ScannerWidget.cpp:152
|
||||
msgid "Refresh available devices"
|
||||
msgstr "Rafraîchir la liste des périphériques"
|
||||
|
||||
#: ../../Resources/InsaneWidget/UI/ScannerWidget.cpp:161
|
||||
msgid "Available devices"
|
||||
msgstr "Périphériques disponibles"
|
||||
|
||||
#: ../../Resources/InsaneWidget/UI/ScannerWidget.cpp:170
|
||||
msgid "Scan source"
|
||||
msgstr "Sources disponibles du numériseur"
|
||||
|
||||
#: ../../Resources/InsaneWidget/UI/ScannerWidget.cpp:179
|
||||
msgid "Scan mode"
|
||||
msgstr "Mode de numérisation"
|
||||
|
||||
#: ../../Resources/InsaneWidget/UI/ScannerWidget.cpp:188
|
||||
msgid "Scan resolution"
|
||||
msgstr "Résolution de la numérisation"
|
||||
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:128
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:107
|
||||
msgid "A scan library error occurred."
|
||||
msgstr "Une erreur de bibliothèque est survenue."
|
||||
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:134
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:113
|
||||
msgid "A general error occurred."
|
||||
msgstr "Une erreur générale est survenue."
|
||||
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:138
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:117
|
||||
msgid "A session read error occurred."
|
||||
msgstr "Une erreur de lecture est survenue."
|
||||
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:145
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:124
|
||||
msgid "Session cancelled."
|
||||
msgstr "Session annulée."
|
||||
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:162
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:141
|
||||
msgid "Scanning: "
|
||||
msgstr "Numérisation :"
|
||||
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:164
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:143
|
||||
msgid "Front face: "
|
||||
msgstr "Recto :"
|
||||
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:166
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:145
|
||||
msgid "Back face: "
|
||||
msgstr "Verso :"
|
||||
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:170
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:149
|
||||
msgid ". Turn the whole stack of pages."
|
||||
msgstr ". Retournez toute la pile de pages."
|
||||
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:182
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:161
|
||||
msgid "Failed to create PNG image."
|
||||
msgstr "Échec de création d'image PNG."
|
||||
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:201
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:180
|
||||
msgid "Wrong paper size: "
|
||||
msgstr "Mauvaise taille de papier :"
|
||||
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:201
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:180
|
||||
msgid "; using A4."
|
||||
msgstr "; utilisation du format A4."
|
||||
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:207
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:186
|
||||
msgid "Failed to add page to PDF document."
|
||||
msgstr "Échec d'ajout de page au document PDF."
|
||||
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:217
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:255
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:196
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:234
|
||||
msgid "Unhandled output file format."
|
||||
msgstr "Format de fichier de sortie non pris en charge."
|
||||
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:264
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:243
|
||||
msgid "Finished."
|
||||
msgstr "Terminé."
|
||||
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:333
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:317
|
||||
msgid "Scan all front faces first, then all back faces in reverse order."
|
||||
msgstr ""
|
||||
"Numériser tous les faces recto, puis toutes les faces verso en ordre inverse."
|
||||
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:336
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:320
|
||||
msgid "Total number of sides to scan (not total number of sheets)."
|
||||
msgstr ""
|
||||
"Nombre total de faces à numériser (et non pas le nombre total de feuilles)."
|
||||
|
||||
#: ../../Resources/InsaneWidget/lib/TimeredStatusBar.cpp:44
|
||||
#: ../../Resources/Utilities/TimeredStatusBar.cpp:44
|
||||
#: ../..//Resources/Utilities/TimeredStatusBar.cpp:44
|
||||
msgid "NUM"
|
||||
msgstr "NUM"
|
||||
|
||||
#: ../../Resources/InsaneWidget/lib/TimeredStatusBar.cpp:52
|
||||
#: ../../Resources/Utilities/TimeredStatusBar.cpp:52
|
||||
#: ../..//Resources/Utilities/TimeredStatusBar.cpp:52
|
||||
msgid "CAPS"
|
||||
msgstr "CAPS"
|
||||
|
||||
#: ../../Resources/InsaneWidget/XScannerWidget.cpp:50
|
||||
msgid "Searching for devices..."
|
||||
msgstr "Recherche de périphériques..."
|
||||
|
||||
#: ../../Resources/InsaneWidget/XScannerWidget.cpp:53
|
||||
msgid "Could not initialise insane api."
|
||||
msgstr "Échec d'initialisation de la bibliothèque 'insane'."
|
||||
|
||||
#: ../../XS7.cpp:46
|
||||
msgid "'Shift + left' click'' to generate a new destination file name."
|
||||
msgstr "'Maj + clic gauche' pour générer un nouveau fichier de sortie."
|
||||
|
||||
#: ../../XS7.cpp:69 ../../XS7.cpp:104
|
||||
msgid "Could not launch default file manager"
|
||||
msgstr "Échec de lancement du gestionnaire de fichier par défaut."
|
||||
|
||||
#: ../../XS7.cpp:93 ../../XS7.cpp:128
|
||||
msgid "Invalid folder name."
|
||||
msgstr "Nom de dossier invalide."
|
||||
|
||||
#: ../../XS7.cpp:101 ../../XS7.cpp:136
|
||||
msgid "Invalid file basename."
|
||||
msgstr "Nom de base de fichier invalide."
|
||||
|
||||
#: ../../XS7.cpp:123 ../../XS7.cpp:158
|
||||
msgid "Copyright: Saleem Edah-Tally [Surgeon] [Hobbyist developer]\n"
|
||||
msgstr "Copyright: Saleem Edah-Tally [Chirurgien] [Développeur par hobby]\n"
|
||||
|
||||
#: ../../XS7.cpp:124 ../../XS7.cpp:159
|
||||
msgid "License: CeCILL/CeCILL-C per file header."
|
||||
msgstr "Licence : CeCILL/CeCILL-C selon les entêtes de fichier."
|
||||
|
||||
#: ../../Resources/UI/S7/s7.h:44 ../..//Resources/UI/S7/s7.h:44
|
||||
msgid "S7"
|
||||
msgstr "S7"
|
||||
|
||||
#: ../../Resources/InsaneWidget/UI/InsaneWidget.h:40
|
||||
msgid "InsaneWidget"
|
||||
msgstr "InsaneWidget"
|
||||
|
||||
#: ../../Resources/InsaneWidget/UI/ScannerWidget.h:49
|
||||
msgid "ScannerWidget"
|
||||
msgstr "ScannerWidget"
|
||||
|
||||
#: ../../Resources/InsaneWidget/UI/ScannerWidget.cpp:138
|
||||
msgid "Format:"
|
||||
msgstr "Format : "
|
||||
|
||||
#: ../../Resources/InsaneWidget/UI/ScannerWidget.cpp:155
|
||||
msgid "Devices:"
|
||||
msgstr "Périphériques :"
|
||||
|
||||
#: ../../Resources/InsaneWidget/UI/ScannerWidget.cpp:164
|
||||
msgid "Source:"
|
||||
msgstr "Source :"
|
||||
|
||||
#: ../../Resources/InsaneWidget/UI/ScannerWidget.cpp:173
|
||||
msgid "Mode:"
|
||||
msgstr "Mode :"
|
||||
|
||||
#: ../../Resources/InsaneWidget/UI/ScannerWidget.cpp:182
|
||||
msgid "Resolution:"
|
||||
msgstr "Résolution :"
|
||||
|
||||
#: ../../Resources/InsaneWidget/UI/ScannerWidget.cpp:191
|
||||
msgid "Paper size:"
|
||||
msgstr "Format de page :"
|
||||
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:332
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:316
|
||||
msgid "Double sided:"
|
||||
msgstr "Recto-verso :"
|
||||
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:334
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:318
|
||||
msgid "Total:"
|
||||
msgstr "Total :"
|
||||
|
||||
#: ../../XS7.cpp:46 ../../XS7.cpp:81
|
||||
msgid "'Shift + left' click to generate a new destination file name."
|
||||
msgstr "'Maj + clic gauche' pour générer un nouveau fichier de sortie."
|
||||
|
||||
#: ../../XS7.cpp:121 ../../XS7.cpp:45 ../../XS7.cpp:156
|
||||
msgid " - version "
|
||||
msgstr " - version "
|
||||
|
||||
#: ../../XS7.cpp:122 ../../XS7.cpp:157
|
||||
msgid ""
|
||||
", using InsaneWidget.\n"
|
||||
"\n"
|
||||
msgstr ""
|
||||
", utilisant InsaneWidget.\n"
|
||||
"\n"
|
||||
|
||||
#: ../../Resources/InsaneWidget/XScannerWidget.cpp:73
|
||||
msgid " device(s) found."
|
||||
msgstr " périphériques trouvé(s)."
|
||||
|
||||
#: ../../XS7.cpp:29
|
||||
msgid "Config file tag."
|
||||
msgstr "Suffixe du fichier de configuration."
|
||||
|
||||
#: ../../XS7.cpp:30
|
||||
msgid "Show version and quit."
|
||||
msgstr "Afficher la version et quitter."
|
||||
|
||||
#: ../../XS7.cpp:31
|
||||
msgid "Show help and quit."
|
||||
msgstr "Afficher l'aide et quitter."
|
||||
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:352
|
||||
msgid "Destination file missing."
|
||||
msgstr "Fichier de destination manquant."
|
||||
298
Resources/Lokalize/fr/S7.po.bak-2025-06-26-22:47:15
Normal file
298
Resources/Lokalize/fr/S7.po.bak-2025-06-26-22:47:15
Normal file
@@ -0,0 +1,298 @@
|
||||
# SOME DESCRIPTIVE TITLE.
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2025-06-26 21:20+0200\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"Language: \n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: ../../Resources/UI/S7/s7.cpp:126 ../..//Resources/UI/S7/s7.cpp:126
|
||||
msgid ""
|
||||
"Select a destination directory.\n"
|
||||
"Double-click to go to the selected directory."
|
||||
msgstr ""
|
||||
"Choisissez un dossier destination\n"
|
||||
"Double-clic pour aller au dossier."
|
||||
|
||||
#: ../../Resources/UI/S7/s7.cpp:130 ../..//Resources/UI/S7/s7.cpp:130
|
||||
msgid "Basename"
|
||||
msgstr "Nom de base"
|
||||
|
||||
#: ../../Resources/UI/S7/s7.cpp:132 ../..//Resources/UI/S7/s7.cpp:132
|
||||
msgid ""
|
||||
"Specify a destination file basename (without extension).\n"
|
||||
"\n"
|
||||
"'CTRL + click' for about information."
|
||||
msgstr ""
|
||||
"Spécifiez un nom de base du fichier de destination (sans l'extension).\n"
|
||||
"\n"
|
||||
"'CTRL + clic' : à propos"
|
||||
|
||||
#: ../../Resources/InsaneWidget/UI/InsaneWidget.cpp:128
|
||||
msgid "New"
|
||||
msgstr "Nouveau"
|
||||
|
||||
#: ../../Resources/InsaneWidget/UI/InsaneWidget.cpp:130
|
||||
msgid "'Right' click to define a scan project."
|
||||
msgstr "Clic droit pour définir un projet de numérisation"
|
||||
|
||||
#: ../../Resources/InsaneWidget/UI/InsaneWidget.cpp:135
|
||||
msgid ""
|
||||
"Full path to destination file without the extension; it is determined by the "
|
||||
"output type."
|
||||
msgstr ""
|
||||
"Chemin complet du fichier de destination sans l'extension; elle est "
|
||||
"déterminée par le format de sortie."
|
||||
|
||||
#: ../../Resources/InsaneWidget/UI/InsaneWidget.cpp:138
|
||||
msgid "Scan"
|
||||
msgstr "Numériser"
|
||||
|
||||
#: ../../Resources/InsaneWidget/UI/InsaneWidget.cpp:140
|
||||
msgid ""
|
||||
"'Left click' to start the scan project.\n"
|
||||
"'Right click' to show the scanner widget."
|
||||
msgstr ""
|
||||
"'Clic gauche' pour démarrer la numérisation.\n"
|
||||
"'Clic droit' pour afficher les options du numériseur."
|
||||
|
||||
#: ../../Resources/InsaneWidget/UI/ScannerWidget.cpp:144
|
||||
msgid "Output document format"
|
||||
msgstr "Format du fichier de sortie"
|
||||
|
||||
#: ../../Resources/InsaneWidget/UI/ScannerWidget.cpp:152
|
||||
msgid "Refresh available devices"
|
||||
msgstr "Rafraîchir la liste des périphériques"
|
||||
|
||||
#: ../../Resources/InsaneWidget/UI/ScannerWidget.cpp:161
|
||||
msgid "Available devices"
|
||||
msgstr "Périphériques disponibles"
|
||||
|
||||
#: ../../Resources/InsaneWidget/UI/ScannerWidget.cpp:170
|
||||
msgid "Scan source"
|
||||
msgstr "Sources disponibles du numériseur"
|
||||
|
||||
#: ../../Resources/InsaneWidget/UI/ScannerWidget.cpp:179
|
||||
msgid "Scan mode"
|
||||
msgstr "Mode de numérisation"
|
||||
|
||||
#: ../../Resources/InsaneWidget/UI/ScannerWidget.cpp:188
|
||||
msgid "Scan resolution"
|
||||
msgstr "Résolution de la numérisation"
|
||||
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:128
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:107
|
||||
msgid "A scan library error occurred."
|
||||
msgstr "Une erreur de bibliothèque est survenue."
|
||||
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:134
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:113
|
||||
msgid "A general error occurred."
|
||||
msgstr "Une erreur générale est survenue."
|
||||
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:138
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:117
|
||||
msgid "A session read error occurred."
|
||||
msgstr "Une erreur de lecture est survenue."
|
||||
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:145
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:124
|
||||
msgid "Session cancelled."
|
||||
msgstr "Session annulée."
|
||||
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:162
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:141
|
||||
msgid "Scanning: "
|
||||
msgstr "Numérisation :"
|
||||
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:164
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:143
|
||||
msgid "Front face: "
|
||||
msgstr "Recto :"
|
||||
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:166
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:145
|
||||
msgid "Back face: "
|
||||
msgstr "Verso :"
|
||||
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:170
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:149
|
||||
msgid ". Turn the whole stack of pages."
|
||||
msgstr ". Retournez toute la pile de pages."
|
||||
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:182
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:161
|
||||
msgid "Failed to create PNG image."
|
||||
msgstr "Échec de création d'image PNG."
|
||||
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:201
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:180
|
||||
msgid "Wrong paper size: "
|
||||
msgstr "Mauvaise taille de papier :"
|
||||
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:201
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:180
|
||||
msgid "; using A4."
|
||||
msgstr "; utilisation du format A4."
|
||||
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:207
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:186
|
||||
msgid "Failed to add page to PDF document."
|
||||
msgstr "Échec d'ajout de page au document PDF."
|
||||
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:217
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:255
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:196
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:234
|
||||
msgid "Unhandled output file format."
|
||||
msgstr "Format de fichier de sortie non pris en charge."
|
||||
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:264
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:243
|
||||
msgid "Finished."
|
||||
msgstr "Terminé."
|
||||
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:333
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:317
|
||||
msgid "Scan all front faces first, then all back faces in reverse order."
|
||||
msgstr ""
|
||||
"Numériser tous les faces recto, puis toutes les faces verso en ordre inverse."
|
||||
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:336
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:320
|
||||
msgid "Total number of sides to scan (not total number of sheets)."
|
||||
msgstr ""
|
||||
"Nombre total de faces à numériser (et non pas le nombre total de feuilles)."
|
||||
|
||||
#: ../../Resources/InsaneWidget/lib/TimeredStatusBar.cpp:44
|
||||
#: ../../Resources/Utilities/TimeredStatusBar.cpp:44
|
||||
#: ../..//Resources/Utilities/TimeredStatusBar.cpp:44
|
||||
msgid "NUM"
|
||||
msgstr "NUM"
|
||||
|
||||
#: ../../Resources/InsaneWidget/lib/TimeredStatusBar.cpp:52
|
||||
#: ../../Resources/Utilities/TimeredStatusBar.cpp:52
|
||||
#: ../..//Resources/Utilities/TimeredStatusBar.cpp:52
|
||||
msgid "CAPS"
|
||||
msgstr "CAPS"
|
||||
|
||||
#: ../../Resources/InsaneWidget/XScannerWidget.cpp:50
|
||||
msgid "Searching for devices..."
|
||||
msgstr "Recherche de périphériques..."
|
||||
|
||||
#: ../../Resources/InsaneWidget/XScannerWidget.cpp:53
|
||||
msgid "Could not initialise insane api."
|
||||
msgstr "Échec d'initialisation de la bibliothèque 'insane'."
|
||||
|
||||
#: ../../XS7.cpp:46
|
||||
msgid "'Shift + left' click'' to generate a new destination file name."
|
||||
msgstr "'Maj + clic gauche' pour générer un nouveau fichier de sortie."
|
||||
|
||||
#: ../../XS7.cpp:69 ../../XS7.cpp:104
|
||||
msgid "Could not launch default file manager"
|
||||
msgstr "Échec de lancement du gestionnaire de fichier par défaut."
|
||||
|
||||
#: ../../XS7.cpp:93 ../../XS7.cpp:128
|
||||
msgid "Invalid folder name."
|
||||
msgstr "Nom de dossier invalide."
|
||||
|
||||
#: ../../XS7.cpp:101 ../../XS7.cpp:136
|
||||
msgid "Invalid file basename."
|
||||
msgstr "Nom de base de fichier invalide."
|
||||
|
||||
#: ../../XS7.cpp:123 ../../XS7.cpp:158
|
||||
msgid "Copyright: Saleem Edah-Tally [Surgeon] [Hobbyist developer]\n"
|
||||
msgstr "Copyright: Saleem Edah-Tally [Chirurgien] [Développeur par hobby]\n"
|
||||
|
||||
#: ../../XS7.cpp:124 ../../XS7.cpp:159
|
||||
msgid "License: CeCILL/CeCILL-C per file header."
|
||||
msgstr "Licence : CeCILL/CeCILL-C selon les entêtes de fichier."
|
||||
|
||||
#: ../../Resources/UI/S7/s7.h:44 ../..//Resources/UI/S7/s7.h:44
|
||||
msgid "S7"
|
||||
msgstr "S7"
|
||||
|
||||
#: ../../Resources/InsaneWidget/UI/InsaneWidget.h:40
|
||||
msgid "InsaneWidget"
|
||||
msgstr "InsaneWidget"
|
||||
|
||||
#: ../../Resources/InsaneWidget/UI/ScannerWidget.h:49
|
||||
msgid "ScannerWidget"
|
||||
msgstr "ScannerWidget"
|
||||
|
||||
#: ../../Resources/InsaneWidget/UI/ScannerWidget.cpp:138
|
||||
msgid "Format:"
|
||||
msgstr "Format : "
|
||||
|
||||
#: ../../Resources/InsaneWidget/UI/ScannerWidget.cpp:155
|
||||
msgid "Devices:"
|
||||
msgstr "Périphériques :"
|
||||
|
||||
#: ../../Resources/InsaneWidget/UI/ScannerWidget.cpp:164
|
||||
msgid "Source:"
|
||||
msgstr "Source :"
|
||||
|
||||
#: ../../Resources/InsaneWidget/UI/ScannerWidget.cpp:173
|
||||
msgid "Mode:"
|
||||
msgstr "Mode :"
|
||||
|
||||
#: ../../Resources/InsaneWidget/UI/ScannerWidget.cpp:182
|
||||
msgid "Resolution:"
|
||||
msgstr "Résolution :"
|
||||
|
||||
#: ../../Resources/InsaneWidget/UI/ScannerWidget.cpp:191
|
||||
msgid "Paper size:"
|
||||
msgstr "Format de page :"
|
||||
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:332
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:316
|
||||
msgid "Double sided:"
|
||||
msgstr "Recto-verso :"
|
||||
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:334
|
||||
#: ../../Resources/InsaneWidget/XInsaneWidget.cpp:318
|
||||
msgid "Total:"
|
||||
msgstr "Total :"
|
||||
|
||||
#: ../../XS7.cpp:46 ../../XS7.cpp:81
|
||||
msgid "'Shift + left' click to generate a new destination file name."
|
||||
msgstr "'Maj + clic gauche' pour générer un nouveau fichier de sortie."
|
||||
|
||||
#: ../../XS7.cpp:121 ../../XS7.cpp:45 ../../XS7.cpp:156
|
||||
msgid " - version "
|
||||
msgstr " - version "
|
||||
|
||||
#: ../../XS7.cpp:122 ../../XS7.cpp:157
|
||||
msgid ""
|
||||
", using InsaneWidget.\n"
|
||||
"\n"
|
||||
msgstr ""
|
||||
", utilisant InsaneWidget.\n"
|
||||
"\n"
|
||||
|
||||
#: ../../Resources/InsaneWidget/XScannerWidget.cpp:73
|
||||
msgid " device(s) found."
|
||||
msgstr " périphériques trouvé(s)."
|
||||
|
||||
#: ../../XS7.cpp:29
|
||||
msgid "Config file tag."
|
||||
msgstr "Suffixe du fichier de configuration."
|
||||
|
||||
#: ../../XS7.cpp:30
|
||||
msgid "Show version and quit."
|
||||
msgstr "Afficher la version et quitter."
|
||||
|
||||
#: ../../XS7.cpp:31
|
||||
msgid "Show help and quit."
|
||||
msgstr "Afficher l'aide et quitter."
|
||||
31
Resources/PKGBUILD
Normal file
31
Resources/PKGBUILD
Normal file
@@ -0,0 +1,31 @@
|
||||
#Simple PKGBUILD that suits my need.
|
||||
|
||||
pkgname=(s7)
|
||||
pkgver=1
|
||||
pkgrel=0
|
||||
arch=('x86_64' 'i686' 'armv7h' 'aarch64')
|
||||
url='http://github.com/nmset/s7/'
|
||||
# Add 'wxwidgets-gtk3' below.
|
||||
depends=('libinsane' 'podofo' 'libpaper')
|
||||
license=('CeCILL' 'CeCILL-C')
|
||||
OPTIONS=(strip)
|
||||
|
||||
build() {
|
||||
cd ${startdir}
|
||||
[ ! -d build ] && mkdir build
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE:STRING=Release -DCMAKE_INSTALL_PREFIX:PATH=${pkgdir}/usr/local ../../
|
||||
make -j8
|
||||
cd ${startdir}/../Resources/Lokalize
|
||||
./2_makemo.sh
|
||||
cd -
|
||||
}
|
||||
|
||||
package() {
|
||||
cd ${startdir}/build
|
||||
make install
|
||||
cd -
|
||||
mkdir -p ${pkgdir}/usr/local/share/locale/fr/LC_MESSAGES
|
||||
cp ${startdir}/../Resources/Lokalize/fr/S7.mo ${pkgdir}/usr/local/share/locale/fr/LC_MESSAGES
|
||||
rm -fr ${startdir}/build
|
||||
}
|
||||
622
Resources/UI/S7/S7.pjd
Normal file
622
Resources/UI/S7/S7.pjd
Normal file
@@ -0,0 +1,622 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<anthemion-project version="1.0.0.0" xmlns="http://www.anthemion.co.uk">
|
||||
<header>
|
||||
<bool name="always_generate_xrc">1</bool>
|
||||
<string name="app_class_name">"Application"</string>
|
||||
<string name="app_file_header">"app.h"</string>
|
||||
<string name="app_file_implementation">"app.cpp"</string>
|
||||
<string name="app_kind">"Standard"</string>
|
||||
<bool name="archive_all_image_files">0</bool>
|
||||
<bool name="archive_image_files">1</bool>
|
||||
<bool name="archive_xrc_files">1</bool>
|
||||
<string name="author">""</string>
|
||||
<string name="configuration">"<None>"</string>
|
||||
<string name="copyright_string">"Copyright Saleem EDAH-TALLY. All rights reserved."</string>
|
||||
<string name="cpp_function_declaration_comment">" /// %BODY%
|
||||
"</string>
|
||||
<string name="cpp_function_implementation_comment">"
|
||||
/*
|
||||
* %BODY%
|
||||
*/
|
||||
|
||||
"</string>
|
||||
<string name="cpp_header_comment">"/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: %HEADER-FILENAME%
|
||||
// Purpose:
|
||||
// Author: %AUTHOR%
|
||||
// Modified by:
|
||||
// Created: %DATE%
|
||||
// RCS-ID:
|
||||
// Copyright: %COPYRIGHT%
|
||||
// Licence:
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
"</string>
|
||||
<string name="cpp_header_preamble">""</string>
|
||||
<string name="cpp_implementation_comment">"/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: %SOURCE-FILENAME%
|
||||
// Purpose:
|
||||
// Author: %AUTHOR%
|
||||
// Modified by:
|
||||
// Created: %DATE%
|
||||
// RCS-ID:
|
||||
// Copyright: %COPYRIGHT%
|
||||
// Licence:
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
"</string>
|
||||
<string name="cpp_implementation_preamble">"// For compilers that support precompilation, includes "wx/wx.h".
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/wx.h"
|
||||
#endif
|
||||
|
||||
"</string>
|
||||
<string name="cpp_symbols_file_comment">"/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: %SYMBOLS-FILENAME%
|
||||
// Purpose: Symbols file
|
||||
// Author: %AUTHOR%
|
||||
// Modified by:
|
||||
// Created: %DATE%
|
||||
// RCS-ID:
|
||||
// Copyright: %COPYRIGHT%
|
||||
// Licence:
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
"</string>
|
||||
<string name="current_platform">"<All platforms>"</string>
|
||||
<string name="description">""</string>
|
||||
<string name="external_symbol_filenames">""</string>
|
||||
<bool name="extract_strings">0</bool>
|
||||
<bool name="generate_app_class">0</bool>
|
||||
<bool name="generate_cpp_for_xrc">0</bool>
|
||||
<bool name="generate_for_xrced">0</bool>
|
||||
<bool name="generate_virtual_eventhandlers">0</bool>
|
||||
<string name="html_path">""</string>
|
||||
<long name="image_mode">0</long>
|
||||
<long name="indent_size">4</long>
|
||||
<bool name="inline_images">0</bool>
|
||||
<bool name="make_unicode_strings">1</bool>
|
||||
<long name="name_counter">0</long>
|
||||
<string name="project_encoding">"utf-8"</string>
|
||||
<string name="resource_archive">""</string>
|
||||
<string name="resource_class_name">"AppResources"</string>
|
||||
<string name="resource_file_header">"app_resources.h"</string>
|
||||
<string name="resource_file_implementation">"app_resources.cpp"</string>
|
||||
<string name="resource_prefix">""</string>
|
||||
<string name="resource_xrc_cpp">""</string>
|
||||
<string name="source_encoding">"utf-8"</string>
|
||||
<string name="target_wx_version">"2.9.2"</string>
|
||||
<long name="text_file_type">0</long>
|
||||
<string name="title">""</string>
|
||||
<bool name="translate_strings">1</bool>
|
||||
<bool name="use_enums">0</bool>
|
||||
<bool name="use_generated_xrc_cpp">0</bool>
|
||||
<bool name="use_help_text_for_tooltips">1</bool>
|
||||
<bool name="use_id_name_for_name">0</bool>
|
||||
<bool name="use_resource_archive">0</bool>
|
||||
<bool name="use_sizer_pixel_compatibility">0</bool>
|
||||
<bool name="use_tabs">0</bool>
|
||||
<bool name="use_two_step_construction">0</bool>
|
||||
<string name="user_name">"Saleem EDAH-TALLY"</string>
|
||||
<string name="whitespace_after_return_type">" "</string>
|
||||
<long name="working_mode">1</long>
|
||||
<string name="xrc_encoding">"utf-8"</string>
|
||||
<string name="xrc_filename">""</string>
|
||||
<bool name="xrc_generate_id_tags">0</bool>
|
||||
<bool name="xrc_retain_relative_paths">1</bool>
|
||||
<bool name="xrc_use_name_property">0</bool>
|
||||
</header>
|
||||
<data>
|
||||
<document>
|
||||
<string name="title">""</string>
|
||||
<string name="type">"data-document"</string>
|
||||
<string name="filename">""</string>
|
||||
<string name="icon-name">""</string>
|
||||
<long name="is-transient">0</long>
|
||||
<long name="owns-file">1</long>
|
||||
<long name="title-mode">0</long>
|
||||
<long name="locked">0</long>
|
||||
<document>
|
||||
<string name="Build mode">"Debug"</string>
|
||||
<string name="C command">"%AUTO%"</string>
|
||||
<string name="C++ command">"%AUTO%"</string>
|
||||
<string name="CFG">""</string>
|
||||
<string name="Compiler bin path">"%AUTO%"</string>
|
||||
<string name="Compiler include path">"%AUTO%"</string>
|
||||
<string name="Compiler lib path">"%AUTO%"</string>
|
||||
<string name="Compiler location">"%AUTO%"</string>
|
||||
<string name="Compiler name">""</string>
|
||||
<string name="Debug flags">"%AUTO%"</string>
|
||||
<bool name="dirty">1</bool>
|
||||
<bool name="Enable makefile generation">1</bool>
|
||||
<string name="Executable name">"%EXECUTABLE%"</string>
|
||||
<string name="Extra compile flags">"%AUTO%"</string>
|
||||
<string name="Extra dependencies">"%AUTO%"</string>
|
||||
<string name="filename">""</string>
|
||||
<string name="GUI mode">"GUI"</string>
|
||||
<string name="icon-name">""</string>
|
||||
<string name="Include path">"%AUTO%"</string>
|
||||
<long name="is-transient">0</long>
|
||||
<string name="Libraries">"%AUTO%"</string>
|
||||
<string name="Library path">"%AUTO%"</string>
|
||||
<string name="Linker command">"%AUTO%"</string>
|
||||
<string name="Linker flags">"%AUTO%"</string>
|
||||
<long name="locked">0</long>
|
||||
<string name="Make command">"%AUTO%"</string>
|
||||
<long name="makefile-last-written">4286447616</long>
|
||||
<string name="Modularity">"Modular"</string>
|
||||
<string name="Objects path">"%AUTO%"</string>
|
||||
<string name="Optimizations">"%AUTO%"</string>
|
||||
<string name="Output path">"%AUTO%"</string>
|
||||
<long name="owns-file">1</long>
|
||||
<string name="PATH variable">"%AUTO%"</string>
|
||||
<string name="Preprocessor flags">"%AUTO%"</string>
|
||||
<string name="Processor type">"Default"</string>
|
||||
<string name="Program arguments">""</string>
|
||||
<string name="Project makefile">"%AUTO%"</string>
|
||||
<string name="Resource compiler">"%AUTO%"</string>
|
||||
<string name="Resource flags">"%AUTO%"</string>
|
||||
<string name="Resource path">"%AUTO%"</string>
|
||||
<string name="Runtime linking">"Dynamic"</string>
|
||||
<string name="Shared mode">"Static"</string>
|
||||
<bool name="Suppress source rules">0</bool>
|
||||
<string name="template-name">""</string>
|
||||
<string name="title">"Configurations"</string>
|
||||
<long name="title-mode">0</long>
|
||||
<string name="Toolkit">"wxGTK+2"</string>
|
||||
<string name="type">"config-data-document"</string>
|
||||
<string name="Unicode mode">"Unicode"</string>
|
||||
<string name="Use exceptions">"Yes"</string>
|
||||
<string name="Use ODBC">"No"</string>
|
||||
<string name="Use OpenGL">"No"</string>
|
||||
<string name="Use wxAUI">"Yes"</string>
|
||||
<string name="Use wxHTML">"Yes"</string>
|
||||
<string name="Use wxMediaCtrl">"No"</string>
|
||||
<string name="Use wxPropertyGrid">"Yes"</string>
|
||||
<string name="Use wxRegEx">"builtin"</string>
|
||||
<string name="Use wxRibbonControl">"Yes"</string>
|
||||
<string name="Use wxRichTextCtrl">"Yes"</string>
|
||||
<string name="Use wxSTC">"Yes"</string>
|
||||
<string name="Use XRC">"Yes"</string>
|
||||
<string name="Warnings">"%AUTO%"</string>
|
||||
<string name="Working path">"%AUTO%"</string>
|
||||
<string name="wxWidgets build command">"%AUTO%"</string>
|
||||
<string name="wxWidgets build path">"%AUTO%"</string>
|
||||
<string name="wxWidgets clean command">"%AUTO%"</string>
|
||||
<string name="wxWidgets location">"%AUTO%"</string>
|
||||
<string name="wxWidgets makefile">"%AUTO%"</string>
|
||||
<string name="wxWidgets version">"%WXVERSION%"</string>
|
||||
</document>
|
||||
</document>
|
||||
</data>
|
||||
|
||||
<documents>
|
||||
<document>
|
||||
<string name="title">"Projects"</string>
|
||||
<string name="type">"root-document"</string>
|
||||
<string name="filename">""</string>
|
||||
<string name="icon-name">"project"</string>
|
||||
<long name="is-transient">1</long>
|
||||
<long name="owns-file">1</long>
|
||||
<long name="title-mode">0</long>
|
||||
<long name="locked">1</long>
|
||||
<document>
|
||||
<string name="title">"Windows"</string>
|
||||
<string name="type">"html-document"</string>
|
||||
<string name="filename">""</string>
|
||||
<string name="icon-name">"dialogsfolder"</string>
|
||||
<long name="is-transient">1</long>
|
||||
<long name="owns-file">1</long>
|
||||
<long name="title-mode">0</long>
|
||||
<long name="locked">1</long>
|
||||
<document>
|
||||
<string name="proxy-type">"wbAppProxy"</string>
|
||||
<string name="app-kind">"Standard"</string>
|
||||
<long name="base-id">10000</long>
|
||||
<string name="filename">""</string>
|
||||
<string name="icon-name">"app"</string>
|
||||
<string name="id-prefix">""</string>
|
||||
<string name="id-suffix">""</string>
|
||||
<long name="is-transient">0</long>
|
||||
<long name="locked">0</long>
|
||||
<long name="owns-file">1</long>
|
||||
<string name="proxy-Base class">"wxApp"</string>
|
||||
<string name="proxy-Class">"S7App"</string>
|
||||
<string name="proxy-Event sources">""</string>
|
||||
<string name="proxy-Header filename">"s7app.h"</string>
|
||||
<string name="proxy-Help filename">""</string>
|
||||
<string name="proxy-Implementation filename">"s7app.cpp"</string>
|
||||
<string name="proxy-Main window">""</string>
|
||||
<string name="title">"S7App"</string>
|
||||
<long name="title-mode">0</long>
|
||||
<string name="type">"dialog-document"</string>
|
||||
<bool name="use-id-prefix">0</bool>
|
||||
<bool name="use-id-suffix">0</bool>
|
||||
<long name="use-xrc">0</long>
|
||||
<long name="working-mode">0</long>
|
||||
</document>
|
||||
<document>
|
||||
<string name="proxy-type">"wbFrameProxy"</string>
|
||||
<string name="app-kind">"Standard"</string>
|
||||
<long name="base-id">10000</long>
|
||||
<string name="filename">""</string>
|
||||
<string name="icon-name">"frame"</string>
|
||||
<string name="id-prefix">""</string>
|
||||
<string name="id-suffix">""</string>
|
||||
<string name="identifier">"itemFrame1"</string>
|
||||
<long name="is-transient">0</long>
|
||||
<long name="locked">0</long>
|
||||
<long name="owns-file">1</long>
|
||||
<bool name="proxy-AUI manager">0</bool>
|
||||
<string name="proxy-Background colour">""</string>
|
||||
<string name="proxy-Base class">"wxFrame"</string>
|
||||
<bool name="proxy-Centre">1</bool>
|
||||
<string name="proxy-Class">"S7"</string>
|
||||
<string name="proxy-Custom styles">""</string>
|
||||
<string name="proxy-Data class header filename">""</string>
|
||||
<string name="proxy-Data class implementation filename">""</string>
|
||||
<string name="proxy-Data class manager window">""</string>
|
||||
<string name="proxy-Data class name">""</string>
|
||||
<string name="proxy-Data source">""</string>
|
||||
<bool name="proxy-Dialog units">0</bool>
|
||||
<bool name="proxy-Enabled">1</bool>
|
||||
<string name="proxy-Event sources">""</string>
|
||||
<bool name="proxy-Fit to content">1</bool>
|
||||
<string name="proxy-Font">""</string>
|
||||
<string name="proxy-Foreground colour">""</string>
|
||||
<string name="proxy-Header filename">"s7.h"</string>
|
||||
<long name="proxy-Height">300</long>
|
||||
<string name="proxy-Help text">""</string>
|
||||
<bool name="proxy-Hidden">0</bool>
|
||||
<string name="proxy-Icon">""</string>
|
||||
<string name="proxy-Id name">"ID_S7"</string>
|
||||
<long name="proxy-Id value">10000</long>
|
||||
<string name="proxy-Implementation filename">"s7.cpp"</string>
|
||||
<string name="proxy-Platform">"<Any platform>"</string>
|
||||
<string name="proxy-Title">"S7"</string>
|
||||
<string name="proxy-Tooltip text">""</string>
|
||||
<long name="proxy-Width">400</long>
|
||||
<bool name="proxy-wxBORDER_THEME">0</bool>
|
||||
<bool name="proxy-wxCAPTION">1</bool>
|
||||
<bool name="proxy-wxCLIP_CHILDREN">0</bool>
|
||||
<bool name="proxy-wxCLOSE_BOX">1</bool>
|
||||
<bool name="proxy-wxDEFAULT_FRAME_STYLE">0</bool>
|
||||
<bool name="proxy-wxDOUBLE_BORDER">0</bool>
|
||||
<bool name="proxy-wxFRAME_EX_CONTEXTHELP">0</bool>
|
||||
<bool name="proxy-wxFRAME_FLOAT_ON_PARENT">0</bool>
|
||||
<bool name="proxy-wxFRAME_NO_TASKBAR">0</bool>
|
||||
<bool name="proxy-wxFRAME_TOOL_WINDOW">0</bool>
|
||||
<bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
|
||||
<bool name="proxy-wxMAXIMIZE">0</bool>
|
||||
<bool name="proxy-wxMAXIMIZE_BOX">0</bool>
|
||||
<bool name="proxy-wxMINIMIZE">0</bool>
|
||||
<bool name="proxy-wxMINIMIZE_BOX">0</bool>
|
||||
<bool name="proxy-wxNO_BORDER">0</bool>
|
||||
<bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
|
||||
<bool name="proxy-wxRAISED_BORDER">0</bool>
|
||||
<bool name="proxy-wxRESIZE_BORDER">1</bool>
|
||||
<bool name="proxy-wxSIMPLE_BORDER">0</bool>
|
||||
<bool name="proxy-wxSTATIC_BORDER">0</bool>
|
||||
<bool name="proxy-wxSTAY_ON_TOP">0</bool>
|
||||
<bool name="proxy-wxSUNKEN_BORDER">0</bool>
|
||||
<bool name="proxy-wxSYSTEM_MENU">1</bool>
|
||||
<bool name="proxy-wxTAB_TRAVERSAL">0</bool>
|
||||
<bool name="proxy-wxWANTS_CHARS">0</bool>
|
||||
<bool name="proxy-wxWS_EX_BLOCK_EVENTS">0</bool>
|
||||
<bool name="proxy-wxWS_EX_TRANSIENT">0</bool>
|
||||
<bool name="proxy-wxWS_EX_VALIDATE_RECURSIVELY">0</bool>
|
||||
<long name="proxy-X">-1</long>
|
||||
<string name="proxy-XRC filename">""</string>
|
||||
<long name="proxy-Y">-1</long>
|
||||
<string name="title">"S7"</string>
|
||||
<long name="title-mode">0</long>
|
||||
<string name="type">"dialog-document"</string>
|
||||
<bool name="use-id-prefix">0</bool>
|
||||
<bool name="use-id-suffix">0</bool>
|
||||
<long name="use-xrc">0</long>
|
||||
<long name="working-mode">0</long>
|
||||
<document>
|
||||
<string name="proxy-type">"wbPanelProxy"</string>
|
||||
<string name="filename">""</string>
|
||||
<string name="icon-name">"panel"</string>
|
||||
<string name="identifier">"itemPanel1"</string>
|
||||
<long name="is-transient">0</long>
|
||||
<long name="locked">0</long>
|
||||
<long name="owns-file">1</long>
|
||||
<string name="proxy-AlignH">"Centre"</string>
|
||||
<string name="proxy-AlignV">"Centre"</string>
|
||||
<bool name="proxy-AUI manager">0</bool>
|
||||
<string name="proxy-Background colour">""</string>
|
||||
<string name="proxy-Base class">"wxPanel"</string>
|
||||
<long name="proxy-Border">5</long>
|
||||
<string name="proxy-Class">"wxPanel"</string>
|
||||
<string name="proxy-Custom arguments">""</string>
|
||||
<string name="proxy-Custom ctor arguments">""</string>
|
||||
<string name="proxy-Custom styles">""</string>
|
||||
<string name="proxy-Data class header filename">""</string>
|
||||
<string name="proxy-Data class implementation filename">""</string>
|
||||
<string name="proxy-Data class manager window">""</string>
|
||||
<string name="proxy-Data class name">""</string>
|
||||
<string name="proxy-Data source">""</string>
|
||||
<bool name="proxy-Enabled">1</bool>
|
||||
<string name="proxy-Event sources">""</string>
|
||||
<bool name="proxy-External implementation">1</bool>
|
||||
<bool name="proxy-Fit to content">1</bool>
|
||||
<string name="proxy-Font">""</string>
|
||||
<string name="proxy-Foreground colour">""</string>
|
||||
<string name="proxy-Header filename">""</string>
|
||||
<long name="proxy-Height">-1</long>
|
||||
<string name="proxy-Help text">""</string>
|
||||
<bool name="proxy-Hidden">0</bool>
|
||||
<string name="proxy-Id name">"ID_PANEL"</string>
|
||||
<long name="proxy-Id value">10001</long>
|
||||
<string name="proxy-Implementation filename">""</string>
|
||||
<string name="proxy-Member variable name">"panMain"</string>
|
||||
<string name="proxy-Name">""</string>
|
||||
<string name="proxy-Platform">"<Any platform>"</string>
|
||||
<bool name="proxy-Separate files">0</bool>
|
||||
<long name="proxy-Stretch factor">0</long>
|
||||
<string name="proxy-Texture">""</string>
|
||||
<string name="proxy-Texture style">"Tiled"</string>
|
||||
<string name="proxy-Tooltip text">""</string>
|
||||
<long name="proxy-Width">-1</long>
|
||||
<bool name="proxy-wxADJUST_MINSIZE">0</bool>
|
||||
<bool name="proxy-wxALWAYS_SHOW_SB">0</bool>
|
||||
<bool name="proxy-wxBORDER_THEME">0</bool>
|
||||
<bool name="proxy-wxBOTTOM">1</bool>
|
||||
<bool name="proxy-wxCLIP_CHILDREN">0</bool>
|
||||
<bool name="proxy-wxDOUBLE_BORDER">0</bool>
|
||||
<bool name="proxy-wxFIXED_MINSIZE">0</bool>
|
||||
<bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
|
||||
<bool name="proxy-wxHSCROLL">0</bool>
|
||||
<bool name="proxy-wxLEFT">1</bool>
|
||||
<bool name="proxy-wxNO_BORDER">0</bool>
|
||||
<bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
|
||||
<bool name="proxy-wxRAISED_BORDER">0</bool>
|
||||
<bool name="proxy-wxRESERVE_SPACE_EVEN_IF_HIDDEN">0</bool>
|
||||
<bool name="proxy-wxRIGHT">1</bool>
|
||||
<bool name="proxy-wxSHAPED">0</bool>
|
||||
<bool name="proxy-wxSIMPLE_BORDER">0</bool>
|
||||
<bool name="proxy-wxSTATIC_BORDER">0</bool>
|
||||
<bool name="proxy-wxSUNKEN_BORDER">1</bool>
|
||||
<bool name="proxy-wxTAB_TRAVERSAL">1</bool>
|
||||
<bool name="proxy-wxTOP">1</bool>
|
||||
<bool name="proxy-wxVSCROLL">0</bool>
|
||||
<bool name="proxy-wxWANTS_CHARS">0</bool>
|
||||
<bool name="proxy-wxWS_EX_BLOCK_EVENTS">0</bool>
|
||||
<bool name="proxy-wxWS_EX_VALIDATE_RECURSIVELY">1</bool>
|
||||
<long name="proxy-X">-1</long>
|
||||
<long name="proxy-Y">-1</long>
|
||||
<string name="title">"wxPanel: ID_PANEL"</string>
|
||||
<long name="title-mode">0</long>
|
||||
<string name="type">"dialog-control-document"</string>
|
||||
<document>
|
||||
<string name="proxy-type">"wbBoxSizerProxy"</string>
|
||||
<string name="filename">""</string>
|
||||
<string name="icon-name">"sizer"</string>
|
||||
<string name="identifier">"itemBoxSizer2"</string>
|
||||
<long name="is-transient">0</long>
|
||||
<long name="locked">0</long>
|
||||
<long name="owns-file">1</long>
|
||||
<string name="proxy-AlignH">"Centre"</string>
|
||||
<string name="proxy-AlignV">"Centre"</string>
|
||||
<long name="proxy-Border">5</long>
|
||||
<string name="proxy-Member variable name">"szMain"</string>
|
||||
<string name="proxy-Orientation">"Vertical"</string>
|
||||
<string name="proxy-Platform">"<Any platform>"</string>
|
||||
<long name="proxy-Stretch factor">0</long>
|
||||
<bool name="proxy-wxADJUST_MINSIZE">0</bool>
|
||||
<bool name="proxy-wxBOTTOM">1</bool>
|
||||
<bool name="proxy-wxFIXED_MINSIZE">0</bool>
|
||||
<bool name="proxy-wxLEFT">1</bool>
|
||||
<bool name="proxy-wxRESERVE_SPACE_EVEN_IF_HIDDEN">0</bool>
|
||||
<bool name="proxy-wxRIGHT">1</bool>
|
||||
<bool name="proxy-wxSHAPED">0</bool>
|
||||
<bool name="proxy-wxTOP">1</bool>
|
||||
<string name="title">"wxBoxSizer V"</string>
|
||||
<long name="title-mode">0</long>
|
||||
<string name="type">"dialog-control-document"</string>
|
||||
<document>
|
||||
<string name="proxy-type">"wbDirPickerCtrlProxy"</string>
|
||||
<string name="filename">""</string>
|
||||
<string name="icon-name">"dialogcontrol"</string>
|
||||
<string name="identifier">"itemDirPickerCtrl3"</string>
|
||||
<long name="is-transient">0</long>
|
||||
<long name="locked">0</long>
|
||||
<long name="owns-file">1</long>
|
||||
<string name="proxy-AlignH">"Expand"</string>
|
||||
<string name="proxy-AlignV">"Centre"</string>
|
||||
<string name="proxy-Background colour">""</string>
|
||||
<string name="proxy-Base class">"wxDirPickerCtrl"</string>
|
||||
<long name="proxy-Border">5</long>
|
||||
<string name="proxy-Class">"wxDirPickerCtrl"</string>
|
||||
<string name="proxy-Custom arguments">""</string>
|
||||
<string name="proxy-Custom ctor arguments">""</string>
|
||||
<string name="proxy-Custom styles">""</string>
|
||||
<string name="proxy-Data class header filename">""</string>
|
||||
<string name="proxy-Data class implementation filename">""</string>
|
||||
<string name="proxy-Data class manager window">""</string>
|
||||
<string name="proxy-Data class name">""</string>
|
||||
<string name="proxy-Data source">""</string>
|
||||
<string name="proxy-Data validator">""</string>
|
||||
<string name="proxy-Data variable">""</string>
|
||||
<string name="proxy-Default path">""</string>
|
||||
<bool name="proxy-Enabled">1</bool>
|
||||
<bool name="proxy-External implementation">1</bool>
|
||||
<string name="proxy-Font">""</string>
|
||||
<string name="proxy-Foreground colour">""</string>
|
||||
<string name="proxy-Header filename">""</string>
|
||||
<long name="proxy-Height">-1</long>
|
||||
<string name="proxy-Help text">""</string>
|
||||
<bool name="proxy-Hidden">0</bool>
|
||||
<string name="proxy-Id name">"ID_DIRPICKERCTRL"</string>
|
||||
<long name="proxy-Id value">10002</long>
|
||||
<string name="proxy-Implementation filename">""</string>
|
||||
<string name="proxy-Member variable name">"dpkDestination"</string>
|
||||
<string name="proxy-Message">""</string>
|
||||
<string name="proxy-Name">""</string>
|
||||
<string name="proxy-Platform">"<Any platform>"</string>
|
||||
<bool name="proxy-Separate files">0</bool>
|
||||
<long name="proxy-Stretch factor">0</long>
|
||||
<string name="proxy-Tooltip text">"Select a destination directory.
|
||||
Double-click to go to the selected directory."</string>
|
||||
<long name="proxy-Width">-1</long>
|
||||
<bool name="proxy-wxADJUST_MINSIZE">0</bool>
|
||||
<bool name="proxy-wxBORDER_THEME">0</bool>
|
||||
<bool name="proxy-wxBOTTOM">1</bool>
|
||||
<bool name="proxy-wxCLIP_CHILDREN">0</bool>
|
||||
<bool name="proxy-wxDIRP_CHANGE_DIR">0</bool>
|
||||
<bool name="proxy-wxDIRP_DEFAULT_STYLE">1</bool>
|
||||
<bool name="proxy-wxDIRP_DIR_MUST_EXIST">0</bool>
|
||||
<bool name="proxy-wxDIRP_USE_TEXTCTRL">1</bool>
|
||||
<bool name="proxy-wxDOUBLE_BORDER">0</bool>
|
||||
<bool name="proxy-wxFIXED_MINSIZE">0</bool>
|
||||
<bool name="proxy-wxLEFT">1</bool>
|
||||
<bool name="proxy-wxNO_BORDER">0</bool>
|
||||
<bool name="proxy-wxRAISED_BORDER">0</bool>
|
||||
<bool name="proxy-wxRESERVE_SPACE_EVEN_IF_HIDDEN">0</bool>
|
||||
<bool name="proxy-wxRIGHT">1</bool>
|
||||
<bool name="proxy-wxSHAPED">0</bool>
|
||||
<bool name="proxy-wxSIMPLE_BORDER">0</bool>
|
||||
<bool name="proxy-wxSTATIC_BORDER">0</bool>
|
||||
<bool name="proxy-wxSUNKEN_BORDER">0</bool>
|
||||
<bool name="proxy-wxTOP">1</bool>
|
||||
<bool name="proxy-wxWANTS_CHARS">0</bool>
|
||||
<long name="proxy-X">-1</long>
|
||||
<long name="proxy-Y">-1</long>
|
||||
<string name="title">"wxDirPickerCtrl: ID_DIRPICKERCTRL"</string>
|
||||
<long name="title-mode">0</long>
|
||||
<string name="type">"dialog-control-document"</string>
|
||||
</document>
|
||||
<document>
|
||||
<string name="proxy-type">"wbTextCtrlProxy"</string>
|
||||
<string name="filename">""</string>
|
||||
<string name="icon-name">"textctrl"</string>
|
||||
<string name="identifier">"itemTextCtrl4"</string>
|
||||
<long name="is-transient">0</long>
|
||||
<long name="locked">0</long>
|
||||
<long name="owns-file">1</long>
|
||||
<string name="proxy-AlignH">"Expand"</string>
|
||||
<string name="proxy-AlignV">"Centre"</string>
|
||||
<string name="proxy-Background colour">""</string>
|
||||
<string name="proxy-Base class">"wxTextCtrl"</string>
|
||||
<long name="proxy-Border">5</long>
|
||||
<string name="proxy-Class">"wxTextCtrl"</string>
|
||||
<string name="proxy-Custom arguments">""</string>
|
||||
<string name="proxy-Custom ctor arguments">""</string>
|
||||
<string name="proxy-Custom styles">""</string>
|
||||
<string name="proxy-Data class header filename">""</string>
|
||||
<string name="proxy-Data class implementation filename">""</string>
|
||||
<string name="proxy-Data class manager window">""</string>
|
||||
<string name="proxy-Data class name">""</string>
|
||||
<string name="proxy-Data source">""</string>
|
||||
<string name="proxy-Data validator">""</string>
|
||||
<string name="proxy-Data variable">""</string>
|
||||
<bool name="proxy-Enabled">1</bool>
|
||||
<bool name="proxy-External implementation">1</bool>
|
||||
<string name="proxy-Font">""</string>
|
||||
<string name="proxy-Foreground colour">""</string>
|
||||
<string name="proxy-Header filename">""</string>
|
||||
<long name="proxy-Height">-1</long>
|
||||
<string name="proxy-Help text">"Basename"</string>
|
||||
<bool name="proxy-Hidden">0</bool>
|
||||
<string name="proxy-Id name">"ID_TEXTCTRL"</string>
|
||||
<long name="proxy-Id value">10003</long>
|
||||
<string name="proxy-Implementation filename">""</string>
|
||||
<string name="proxy-Initial value">""</string>
|
||||
<long name="proxy-Max length">0</long>
|
||||
<string name="proxy-Member variable name">"txtBasename"</string>
|
||||
<string name="proxy-Name">""</string>
|
||||
<string name="proxy-Platform">"<Any platform>"</string>
|
||||
<bool name="proxy-Separate files">0</bool>
|
||||
<long name="proxy-Stretch factor">0</long>
|
||||
<string name="proxy-Tooltip text">"Specify a destination file basename (without extension).
|
||||
|
||||
'CTRL + click' for about information."</string>
|
||||
<long name="proxy-Width">-1</long>
|
||||
<bool name="proxy-wxADJUST_MINSIZE">0</bool>
|
||||
<bool name="proxy-wxBORDER_THEME">0</bool>
|
||||
<bool name="proxy-wxBOTTOM">1</bool>
|
||||
<bool name="proxy-wxDOUBLE_BORDER">0</bool>
|
||||
<bool name="proxy-wxFIXED_MINSIZE">0</bool>
|
||||
<bool name="proxy-wxFULL_REPAINT_ON_RESIZE">0</bool>
|
||||
<bool name="proxy-wxHSCROLL">0</bool>
|
||||
<bool name="proxy-wxLEFT">1</bool>
|
||||
<bool name="proxy-wxNO_BORDER">0</bool>
|
||||
<bool name="proxy-wxNO_FULL_REPAINT_ON_RESIZE">0</bool>
|
||||
<bool name="proxy-wxRAISED_BORDER">0</bool>
|
||||
<bool name="proxy-wxRESERVE_SPACE_EVEN_IF_HIDDEN">0</bool>
|
||||
<bool name="proxy-wxRIGHT">1</bool>
|
||||
<bool name="proxy-wxSHAPED">0</bool>
|
||||
<bool name="proxy-wxSIMPLE_BORDER">0</bool>
|
||||
<bool name="proxy-wxSTATIC_BORDER">0</bool>
|
||||
<bool name="proxy-wxSUNKEN_BORDER">0</bool>
|
||||
<bool name="proxy-wxTE_AUTO_URL">0</bool>
|
||||
<bool name="proxy-wxTE_CAPITALIZE">0</bool>
|
||||
<bool name="proxy-wxTE_CENTRE">0</bool>
|
||||
<bool name="proxy-wxTE_CHARWRAP">0</bool>
|
||||
<bool name="proxy-wxTE_LEFT">0</bool>
|
||||
<bool name="proxy-wxTE_MULTILINE">0</bool>
|
||||
<bool name="proxy-wxTE_NOHIDESEL">0</bool>
|
||||
<bool name="proxy-wxTE_PASSWORD">0</bool>
|
||||
<bool name="proxy-wxTE_PROCESS_ENTER">0</bool>
|
||||
<bool name="proxy-wxTE_PROCESS_TAB">0</bool>
|
||||
<bool name="proxy-wxTE_READONLY">0</bool>
|
||||
<bool name="proxy-wxTE_RICH">0</bool>
|
||||
<bool name="proxy-wxTE_RICH2">0</bool>
|
||||
<bool name="proxy-wxTE_RIGHT">0</bool>
|
||||
<bool name="proxy-wxTE_WORDWRAP">0</bool>
|
||||
<bool name="proxy-wxTOP">1</bool>
|
||||
<bool name="proxy-wxWANTS_CHARS">0</bool>
|
||||
<long name="proxy-X">-1</long>
|
||||
<long name="proxy-Y">-1</long>
|
||||
<string name="title">"wxTextCtrl: ID_TEXTCTRL"</string>
|
||||
<long name="title-mode">0</long>
|
||||
<string name="type">"dialog-control-document"</string>
|
||||
</document>
|
||||
</document>
|
||||
</document>
|
||||
</document>
|
||||
</document>
|
||||
<document>
|
||||
<string name="title">"Sources"</string>
|
||||
<string name="type">"html-document"</string>
|
||||
<string name="filename">""</string>
|
||||
<string name="icon-name">"sourcesfolder"</string>
|
||||
<long name="is-transient">1</long>
|
||||
<long name="owns-file">1</long>
|
||||
<long name="title-mode">0</long>
|
||||
<long name="locked">1</long>
|
||||
<document>
|
||||
<string name="title">"S7.rc"</string>
|
||||
<string name="type">"source-editor-document"</string>
|
||||
<string name="filename">"S7.rc"</string>
|
||||
<string name="icon-name">"source-editor"</string>
|
||||
<long name="is-transient">0</long>
|
||||
<long name="owns-file">0</long>
|
||||
<long name="title-mode">1</long>
|
||||
<long name="locked">0</long>
|
||||
<string name="created">"16/6/2025"</string>
|
||||
<string name="language">""</string>
|
||||
</document>
|
||||
</document>
|
||||
<document>
|
||||
<string name="title">"Images"</string>
|
||||
<string name="type">"html-document"</string>
|
||||
<string name="filename">""</string>
|
||||
<string name="icon-name">"bitmapsfolder"</string>
|
||||
<long name="is-transient">1</long>
|
||||
<long name="owns-file">1</long>
|
||||
<long name="title-mode">0</long>
|
||||
<long name="locked">1</long>
|
||||
</document>
|
||||
</document>
|
||||
</documents>
|
||||
|
||||
</anthemion-project>
|
||||
1
Resources/UI/S7/S7.rc
Normal file
1
Resources/UI/S7/S7.rc
Normal file
@@ -0,0 +1 @@
|
||||
#include "wx/msw/wx.rc"
|
||||
172
Resources/UI/S7/s7.cpp
Normal file
172
Resources/UI/S7/s7.cpp
Normal file
@@ -0,0 +1,172 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: s7.cpp
|
||||
// Purpose:
|
||||
// Author: Saleem EDAH-TALLY
|
||||
// Modified by:
|
||||
// Created: lun. 16 juin 2025 22:42:13
|
||||
// RCS-ID:
|
||||
// Copyright: Copyright Saleem EDAH-TALLY. All rights reserved.
|
||||
// Licence:
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// For compilers that support precompilation, includes "wx/wx.h".
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/wx.h"
|
||||
#endif
|
||||
|
||||
////@begin includes
|
||||
////@end includes
|
||||
|
||||
#include "s7.h"
|
||||
|
||||
////@begin XPM images
|
||||
////@end XPM images
|
||||
|
||||
|
||||
/*
|
||||
* S7 type definition
|
||||
*/
|
||||
|
||||
IMPLEMENT_CLASS( S7, wxFrame )
|
||||
|
||||
|
||||
/*
|
||||
* S7 event table definition
|
||||
*/
|
||||
|
||||
BEGIN_EVENT_TABLE( S7, wxFrame )
|
||||
|
||||
////@begin S7 event table entries
|
||||
////@end S7 event table entries
|
||||
|
||||
END_EVENT_TABLE()
|
||||
|
||||
|
||||
/*
|
||||
* S7 constructors
|
||||
*/
|
||||
|
||||
S7::S7()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
S7::S7( wxWindow* parent, wxWindowID id, const wxString& caption, const wxPoint& pos, const wxSize& size, long style )
|
||||
{
|
||||
Init();
|
||||
Create( parent, id, caption, pos, size, style );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* S7 creator
|
||||
*/
|
||||
|
||||
bool S7::Create( wxWindow* parent, wxWindowID id, const wxString& caption, const wxPoint& pos, const wxSize& size, long style )
|
||||
{
|
||||
////@begin S7 creation
|
||||
wxFrame::Create( parent, id, caption, pos, size, style );
|
||||
|
||||
CreateControls();
|
||||
Centre();
|
||||
////@end S7 creation
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* S7 destructor
|
||||
*/
|
||||
|
||||
S7::~S7()
|
||||
{
|
||||
////@begin S7 destruction
|
||||
////@end S7 destruction
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Member initialisation
|
||||
*/
|
||||
|
||||
void S7::Init()
|
||||
{
|
||||
////@begin S7 member initialisation
|
||||
panMain = NULL;
|
||||
szMain = NULL;
|
||||
dpkDestination = NULL;
|
||||
txtBasename = NULL;
|
||||
////@end S7 member initialisation
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Control creation for S7
|
||||
*/
|
||||
|
||||
void S7::CreateControls()
|
||||
{
|
||||
////@begin S7 content construction
|
||||
S7* itemFrame1 = this;
|
||||
|
||||
panMain = new wxPanel( itemFrame1, ID_PANEL, wxDefaultPosition, wxDefaultSize, wxSUNKEN_BORDER|wxTAB_TRAVERSAL );
|
||||
panMain->SetExtraStyle(wxWS_EX_VALIDATE_RECURSIVELY);
|
||||
|
||||
szMain = new wxBoxSizer(wxVERTICAL);
|
||||
panMain->SetSizer(szMain);
|
||||
|
||||
dpkDestination = new wxDirPickerCtrl( panMain, ID_DIRPICKERCTRL, wxEmptyString, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxDIRP_DEFAULT_STYLE|wxDIRP_USE_TEXTCTRL );
|
||||
if (S7::ShowToolTips())
|
||||
dpkDestination->SetToolTip(_("Select a destination directory.\nDouble-click to go to the selected directory."));
|
||||
szMain->Add(dpkDestination, 0, wxGROW|wxALL, 5);
|
||||
|
||||
txtBasename = new wxTextCtrl( panMain, ID_TEXTCTRL, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0 );
|
||||
txtBasename->SetHelpText(_("Basename"));
|
||||
if (S7::ShowToolTips())
|
||||
txtBasename->SetToolTip(_("Specify a destination file basename (without extension).\n\n'CTRL + click' for about information."));
|
||||
szMain->Add(txtBasename, 0, wxGROW|wxALL, 5);
|
||||
|
||||
////@end S7 content construction
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Should we show tooltips?
|
||||
*/
|
||||
|
||||
bool S7::ShowToolTips()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get bitmap resources
|
||||
*/
|
||||
|
||||
wxBitmap S7::GetBitmapResource( const wxString& name )
|
||||
{
|
||||
// Bitmap retrieval
|
||||
////@begin S7 bitmap retrieval
|
||||
wxUnusedVar(name);
|
||||
return wxNullBitmap;
|
||||
////@end S7 bitmap retrieval
|
||||
}
|
||||
|
||||
/*
|
||||
* Get icon resources
|
||||
*/
|
||||
|
||||
wxIcon S7::GetIconResource( const wxString& name )
|
||||
{
|
||||
// Icon retrieval
|
||||
////@begin S7 icon retrieval
|
||||
wxUnusedVar(name);
|
||||
return wxNullIcon;
|
||||
////@end S7 icon retrieval
|
||||
}
|
||||
101
Resources/UI/S7/s7.h
Normal file
101
Resources/UI/S7/s7.h
Normal file
@@ -0,0 +1,101 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: s7.h
|
||||
// Purpose:
|
||||
// Author: Saleem EDAH-TALLY
|
||||
// Modified by:
|
||||
// Created: lun. 16 juin 2025 22:42:13
|
||||
// RCS-ID:
|
||||
// Copyright: Copyright Saleem EDAH-TALLY. All rights reserved.
|
||||
// Licence:
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _S7_H_
|
||||
#define _S7_H_
|
||||
|
||||
|
||||
/*!
|
||||
* Includes
|
||||
*/
|
||||
|
||||
////@begin includes
|
||||
#include "wx/frame.h"
|
||||
#include "wx/filepicker.h"
|
||||
////@end includes
|
||||
#include "wx/panel.h"
|
||||
/*!
|
||||
* Forward declarations
|
||||
*/
|
||||
|
||||
////@begin forward declarations
|
||||
class wxBoxSizer;
|
||||
class wxDirPickerCtrl;
|
||||
////@end forward declarations
|
||||
|
||||
/*!
|
||||
* Control identifiers
|
||||
*/
|
||||
|
||||
////@begin control identifiers
|
||||
#define ID_S7 10000
|
||||
#define ID_PANEL 10001
|
||||
#define ID_DIRPICKERCTRL 10002
|
||||
#define ID_TEXTCTRL 10003
|
||||
#define SYMBOL_S7_STYLE wxCAPTION|wxRESIZE_BORDER|wxSYSTEM_MENU|wxCLOSE_BOX
|
||||
#define SYMBOL_S7_TITLE _("S7")
|
||||
#define SYMBOL_S7_IDNAME ID_S7
|
||||
#define SYMBOL_S7_SIZE wxSize(400, 300)
|
||||
#define SYMBOL_S7_POSITION wxDefaultPosition
|
||||
////@end control identifiers
|
||||
|
||||
|
||||
/*!
|
||||
* S7 class declaration
|
||||
*/
|
||||
|
||||
class S7: public wxFrame
|
||||
{
|
||||
DECLARE_CLASS( S7 )
|
||||
DECLARE_EVENT_TABLE()
|
||||
|
||||
public:
|
||||
/// Constructors
|
||||
S7();
|
||||
S7( wxWindow* parent, wxWindowID id = SYMBOL_S7_IDNAME, const wxString& caption = SYMBOL_S7_TITLE, const wxPoint& pos = SYMBOL_S7_POSITION, const wxSize& size = SYMBOL_S7_SIZE, long style = SYMBOL_S7_STYLE );
|
||||
|
||||
bool Create( wxWindow* parent, wxWindowID id = SYMBOL_S7_IDNAME, const wxString& caption = SYMBOL_S7_TITLE, const wxPoint& pos = SYMBOL_S7_POSITION, const wxSize& size = SYMBOL_S7_SIZE, long style = SYMBOL_S7_STYLE );
|
||||
|
||||
/// Destructor
|
||||
~S7();
|
||||
|
||||
/// Initialises member variables
|
||||
void Init();
|
||||
|
||||
/// Creates the controls and sizers
|
||||
void CreateControls();
|
||||
|
||||
////@begin S7 event handler declarations
|
||||
|
||||
////@end S7 event handler declarations
|
||||
|
||||
////@begin S7 member function declarations
|
||||
|
||||
/// Retrieves bitmap resources
|
||||
wxBitmap GetBitmapResource( const wxString& name );
|
||||
|
||||
/// Retrieves icon resources
|
||||
wxIcon GetIconResource( const wxString& name );
|
||||
////@end S7 member function declarations
|
||||
|
||||
/// Should we show tooltips?
|
||||
static bool ShowToolTips();
|
||||
|
||||
////@begin S7 member variables
|
||||
wxPanel* panMain;
|
||||
wxBoxSizer* szMain;
|
||||
wxDirPickerCtrl* dpkDestination;
|
||||
wxTextCtrl* txtBasename;
|
||||
////@end S7 member variables
|
||||
};
|
||||
|
||||
#endif
|
||||
// _S7_H_
|
||||
149
Resources/UI/S7/s7app.cpp
Normal file
149
Resources/UI/S7/s7app.cpp
Normal file
@@ -0,0 +1,149 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: s7app.cpp
|
||||
// Purpose:
|
||||
// Author: Saleem EDAH-TALLY
|
||||
// Modified by:
|
||||
// Created: lun. 16 juin 2025 22:41:03
|
||||
// RCS-ID:
|
||||
// Copyright: Copyright Saleem EDAH-TALLY. All rights reserved.
|
||||
// Licence:
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// For compilers that support precompilation, includes "wx/wx.h".
|
||||
#include "wx/wxprec.h"
|
||||
|
||||
#ifdef __BORLANDC__
|
||||
#pragma hdrstop
|
||||
#endif
|
||||
|
||||
#ifndef WX_PRECOMP
|
||||
#include "wx/wx.h"
|
||||
#endif
|
||||
|
||||
////@begin includes
|
||||
////@end includes
|
||||
|
||||
#include <globals.h>
|
||||
#include "s7app.h"
|
||||
#include <XS7.h>
|
||||
|
||||
////@begin XPM images
|
||||
|
||||
////@end XPM images
|
||||
|
||||
|
||||
/*
|
||||
* Application instance implementation
|
||||
*/
|
||||
|
||||
////@begin implement app
|
||||
IMPLEMENT_APP( S7App )
|
||||
////@end implement app
|
||||
|
||||
|
||||
/*
|
||||
* S7App type definition
|
||||
*/
|
||||
|
||||
IMPLEMENT_CLASS( S7App, wxApp )
|
||||
|
||||
|
||||
/*
|
||||
* S7App event table definition
|
||||
*/
|
||||
|
||||
BEGIN_EVENT_TABLE( S7App, wxApp )
|
||||
|
||||
////@begin S7App event table entries
|
||||
////@end S7App event table entries
|
||||
|
||||
END_EVENT_TABLE()
|
||||
|
||||
|
||||
/*
|
||||
* Constructor for S7App
|
||||
*/
|
||||
|
||||
S7App::S7App()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Member initialisation
|
||||
*/
|
||||
|
||||
void S7App::Init()
|
||||
{
|
||||
////@begin S7App member initialisation
|
||||
////@end S7App member initialisation
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialisation for S7App
|
||||
*/
|
||||
|
||||
bool S7App::OnInit()
|
||||
{
|
||||
////@begin S7App initialisation
|
||||
// Remove the comment markers above and below this block
|
||||
// to make permanent changes to the code.
|
||||
|
||||
#if wxUSE_XPM
|
||||
wxImage::AddHandler(new wxXPMHandler);
|
||||
#endif
|
||||
#if wxUSE_LIBPNG
|
||||
wxImage::AddHandler(new wxPNGHandler);
|
||||
#endif
|
||||
#if wxUSE_LIBJPEG
|
||||
wxImage::AddHandler(new wxJPEGHandler);
|
||||
#endif
|
||||
#if wxUSE_GIF
|
||||
wxImage::AddHandler(new wxGIFHandler);
|
||||
#endif
|
||||
////@end S7App initialisation
|
||||
|
||||
#if wxUSE_LIBTIFF
|
||||
wxImage::AddHandler(new wxTIFFHandler);
|
||||
#endif
|
||||
#if wxUSE_PNM
|
||||
wxImage::AddHandler(new wxPNMHandler);
|
||||
#endif
|
||||
|
||||
m_locale.Init ( wxLANGUAGE_DEFAULT );
|
||||
m_locale.AddCatalog ( _APPNAME_ );
|
||||
|
||||
SetAppName(_APPNAME_);
|
||||
wxTranslations * translations = wxTranslations::Get();
|
||||
if (translations)
|
||||
{
|
||||
translations->AddStdCatalog();
|
||||
translations->AddCatalog(_APPNAME_);
|
||||
}
|
||||
|
||||
XS7 * appWindow = new XS7(nullptr);
|
||||
SetTopWindow(appWindow);
|
||||
appWindow->Show ( false );
|
||||
bool res = appWindow->ParseCmdLine();
|
||||
if ( res )
|
||||
{
|
||||
appWindow->Setup();
|
||||
appWindow->Show();
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Cleanup for S7App
|
||||
*/
|
||||
|
||||
int S7App::OnExit()
|
||||
{
|
||||
////@begin S7App cleanup
|
||||
return wxApp::OnExit();
|
||||
////@end S7App cleanup
|
||||
}
|
||||
|
||||
80
Resources/UI/S7/s7app.h
Normal file
80
Resources/UI/S7/s7app.h
Normal file
@@ -0,0 +1,80 @@
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Name: s7app.h
|
||||
// Purpose:
|
||||
// Author: Saleem EDAH-TALLY
|
||||
// Modified by:
|
||||
// Created: lun. 16 juin 2025 22:41:03
|
||||
// RCS-ID:
|
||||
// Copyright: Copyright Saleem EDAH-TALLY. All rights reserved.
|
||||
// Licence:
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef _S7APP_H_
|
||||
#define _S7APP_H_
|
||||
|
||||
|
||||
/*!
|
||||
* Includes
|
||||
*/
|
||||
|
||||
////@begin includes
|
||||
#include "wx/image.h"
|
||||
////@end includes
|
||||
|
||||
/*!
|
||||
* Forward declarations
|
||||
*/
|
||||
|
||||
////@begin forward declarations
|
||||
////@end forward declarations
|
||||
|
||||
/*!
|
||||
* Control identifiers
|
||||
*/
|
||||
|
||||
////@begin control identifiers
|
||||
////@end control identifiers
|
||||
|
||||
/*!
|
||||
* S7App class declaration
|
||||
*/
|
||||
|
||||
class S7App: public wxApp
|
||||
{
|
||||
DECLARE_CLASS( S7App )
|
||||
DECLARE_EVENT_TABLE()
|
||||
|
||||
public:
|
||||
/// Constructor
|
||||
S7App();
|
||||
|
||||
void Init();
|
||||
|
||||
/// Initialises the application
|
||||
virtual bool OnInit();
|
||||
|
||||
/// Called on exit
|
||||
virtual int OnExit();
|
||||
|
||||
////@begin S7App event handler declarations
|
||||
////@end S7App event handler declarations
|
||||
|
||||
////@begin S7App member function declarations
|
||||
////@end S7App member function declarations
|
||||
|
||||
////@begin S7App member variables
|
||||
////@end S7App member variables
|
||||
private:
|
||||
wxLocale m_locale;
|
||||
};
|
||||
|
||||
/*!
|
||||
* Application instance declaration
|
||||
*/
|
||||
|
||||
////@begin declare app
|
||||
DECLARE_APP(S7App)
|
||||
////@end declare app
|
||||
|
||||
#endif
|
||||
// _S7APP_H_
|
||||
17
Resources/Utilities/CMakeLists.txt
Normal file
17
Resources/Utilities/CMakeLists.txt
Normal file
@@ -0,0 +1,17 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
project(MinimalUtilities)
|
||||
|
||||
find_package(wxWidgets COMPONENTS base core CONFIG REQUIRED)
|
||||
|
||||
add_library(minutils STATIC
|
||||
ConfigEditorPopup.cpp
|
||||
MiscTools.cpp
|
||||
PopupTransientWindow.cpp
|
||||
TimeredStatusBar.cpp
|
||||
XClientData.hpp
|
||||
)
|
||||
|
||||
target_link_libraries(minutils
|
||||
${wxWidgets_LIBRARIES}
|
||||
)
|
||||
123
Resources/Utilities/ConfigEditorPopup.cpp
Normal file
123
Resources/Utilities/ConfigEditorPopup.cpp
Normal file
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* File: ConfigEditorPopup.cpp
|
||||
* Author: Saleem EDAH-TALLY - nmset@yandex.com
|
||||
* License: CeCILL-C
|
||||
* Copyright Saleem EDAH-TALLY - © 2017
|
||||
*
|
||||
* Created on 4 mars 2017, 19:06
|
||||
*/
|
||||
|
||||
#include "ConfigEditorPopup.h"
|
||||
#include "MiscTools.h"
|
||||
|
||||
ConfigEditorPopup::ConfigEditorPopup ( wxWindow * parent, wxFileConfig* config )
|
||||
{
|
||||
m_owner = parent;
|
||||
m_config = config;
|
||||
}
|
||||
|
||||
ConfigEditorPopup::~ConfigEditorPopup() = default;
|
||||
|
||||
PopupTransientWindow* ConfigEditorPopup::CreatePopup()
|
||||
{
|
||||
wxASSERT_MSG ( ( m_config != nullptr ),_T("CONFIG IS nullptr") );
|
||||
m_popup = new PopupTransientWindow ( m_owner );
|
||||
m_pan = new wxPanel ( m_popup );
|
||||
m_flxsz = new wxFlexGridSizer ( 0, 2, 0, 0 );
|
||||
m_pan->SetSizer ( m_flxsz );
|
||||
m_flxsz->AddGrowableCol ( 1 );
|
||||
m_popup->Bind ( wxEVT_DESTROY, &ConfigEditorPopup::OnPopupDestroy, this );
|
||||
return m_popup;
|
||||
}
|
||||
|
||||
wxCheckBox* ConfigEditorPopup::AddCheckBox ( const wxString& label, const wxString& configPath )
|
||||
{
|
||||
wxASSERT_MSG ( ( m_config != nullptr ),_T("CONFIG IS nullptr") );
|
||||
wxString * cPath = new wxString ( configPath );
|
||||
wxStaticText * lbl = new wxStaticText ( m_pan, wxID_ANY, label );
|
||||
m_flxsz->Add ( lbl, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL | wxALL, 0 );
|
||||
wxCheckBox * cb = new wxCheckBox ( m_pan, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxCHK_2STATE );
|
||||
m_flxsz->Add ( cb, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL | wxALL, 0 );
|
||||
cb->SetValue ( m_config->ReadBool ( configPath, false ) );
|
||||
cb->SetClientData ( cPath );
|
||||
cb->Bind ( wxEVT_DESTROY, &ConfigEditorPopup::OnControlDestroy, this );
|
||||
return cb;
|
||||
}
|
||||
|
||||
wxSpinCtrl* ConfigEditorPopup::AddSpinCtrl ( const wxString& label, const wxString& configPath )
|
||||
{
|
||||
wxASSERT_MSG ( ( m_config != nullptr ),_T("CONFIG IS nullptr") );
|
||||
wxString * cPath = new wxString ( configPath );
|
||||
wxStaticText * lbl = new wxStaticText ( m_pan, wxID_ANY, label );
|
||||
m_flxsz->Add ( lbl, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL | wxGROW | wxALL, 0 );
|
||||
wxSpinCtrl * spn = new wxSpinCtrl ( m_pan, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS | wxALIGN_RIGHT, -100, 100 );
|
||||
m_flxsz->Add ( spn, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL | wxALL, 0 );
|
||||
spn->SetValue ( ( int ) m_config->ReadLong ( configPath, 0 ) );
|
||||
spn->SetClientData ( cPath );
|
||||
spn->Bind ( wxEVT_DESTROY, &ConfigEditorPopup::OnControlDestroy, this );
|
||||
return spn;
|
||||
}
|
||||
|
||||
wxTextCtrl* ConfigEditorPopup::AddTextCtrl ( const wxString& label, const wxString& configPath )
|
||||
{
|
||||
wxASSERT_MSG ( ( m_config != nullptr ),_T("CONFIG IS nullptr") );
|
||||
wxString * cPath = new wxString ( configPath );
|
||||
wxStaticText * lbl = new wxStaticText ( m_pan, wxID_ANY, label );
|
||||
m_flxsz->Add ( lbl, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL | wxGROW | wxALL, 0 );
|
||||
wxTextCtrl * txt = new wxTextCtrl ( m_pan, wxID_ANY );
|
||||
m_flxsz->Add ( txt, 0, wxALIGN_LEFT | wxALIGN_CENTER_VERTICAL | wxALL, 0 );
|
||||
txt->SetValue ( m_config->Read ( configPath, wxEmptyString ) );
|
||||
txt->SetClientData ( cPath );
|
||||
txt->Bind ( wxEVT_DESTROY, &ConfigEditorPopup::OnControlDestroy, this );
|
||||
return txt;
|
||||
}
|
||||
|
||||
void ConfigEditorPopup::OnControlDestroy ( wxWindowDestroyEvent& evt )
|
||||
{
|
||||
//cout << "ConfigEditorPopup::OnControlDestroy" << endl;
|
||||
evt.Skip();
|
||||
wxControl * ctrl = static_cast<wxControl*> ( evt.GetEventObject() );
|
||||
if ( !ctrl ) return;
|
||||
|
||||
const wxString className ( ctrl->GetClassInfo()->GetClassName() );
|
||||
const wxString * cPath = static_cast<wxString*> ( ctrl->GetClientData() );
|
||||
if ( className ==_T("wxCheckBox") )
|
||||
{
|
||||
wxCheckBox * cb = static_cast<wxCheckBox*> ( evt.GetEventObject() );
|
||||
m_config->Write ( *cPath, cb->GetValue() );
|
||||
}
|
||||
if ( className ==_T("wxSpinCtrl") )
|
||||
{
|
||||
wxSpinCtrl * spn = static_cast<wxSpinCtrl*> ( evt.GetEventObject() );
|
||||
m_config->Write ( *cPath, spn->GetValue() );
|
||||
}
|
||||
if ( className ==_T("wxTextCtrl") )
|
||||
{
|
||||
wxTextCtrl * txt = static_cast<wxTextCtrl*> ( evt.GetEventObject() );
|
||||
if ( txt->IsEmpty() )
|
||||
{
|
||||
m_config->DeleteEntry ( *cPath, true );
|
||||
}
|
||||
else
|
||||
{
|
||||
m_config->Write ( *cPath, txt->GetValue() );
|
||||
}
|
||||
}
|
||||
|
||||
m_config->Flush();
|
||||
delete cPath;
|
||||
}
|
||||
|
||||
void ConfigEditorPopup::OnPopupDestroy ( wxWindowDestroyEvent& evt )
|
||||
{
|
||||
//cout << "ConfigEditorPopup::OnPopupDestroy" << endl;
|
||||
evt.Skip();
|
||||
}
|
||||
|
||||
void ConfigEditorPopup::ShowPopup()
|
||||
{
|
||||
m_pan->GetSizer()->SetSizeHints ( m_pan );
|
||||
MiscTools::ShowTransientPopup ( m_popup, m_pan, m_pan->GetSize().GetWidth(), m_pan->GetSize().GetHeight() );
|
||||
}
|
||||
|
||||
|
||||
46
Resources/Utilities/ConfigEditorPopup.h
Normal file
46
Resources/Utilities/ConfigEditorPopup.h
Normal file
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* File: ConfigEditorPopup.h
|
||||
* Author: Saleem EDAH-TALLY - nmset@yandex.com
|
||||
* License: CeCILL-C
|
||||
* Copyright Saleem EDAH-TALLY - © 2017
|
||||
*
|
||||
* Created on 4 mars 2017, 19:06
|
||||
*/
|
||||
|
||||
#ifndef CONFIGEDITORPOPUP_H
|
||||
#define CONFIGEDITORPOPUP_H
|
||||
|
||||
#include <wx/wx.h>
|
||||
#include <wx/config.h>
|
||||
#include "PopupTransientWindow.h"
|
||||
#include <wx/spinctrl.h>
|
||||
|
||||
/**
|
||||
* Edits wxConfig keys using check boxes, text and spin controls, with supplied
|
||||
* paths. When a control is created, it reads the values. When it is destroyed,
|
||||
* it saves back the value.
|
||||
*/
|
||||
class ConfigEditorPopup
|
||||
{
|
||||
public:
|
||||
ConfigEditorPopup ( wxWindow * parent, wxConfig * config );
|
||||
virtual ~ConfigEditorPopup();
|
||||
PopupTransientWindow* CreatePopup();
|
||||
void ShowPopup();
|
||||
wxCheckBox* AddCheckBox ( const wxString& label, const wxString& configPath );
|
||||
wxSpinCtrl* AddSpinCtrl ( const wxString& label, const wxString& configPath );
|
||||
wxTextCtrl * AddTextCtrl ( const wxString& label, const wxString& configPath );
|
||||
|
||||
private:
|
||||
wxConfig * m_config = nullptr;
|
||||
wxWeakRef<wxWindow> m_owner = nullptr;
|
||||
wxFlexGridSizer * m_flxsz = nullptr;
|
||||
PopupTransientWindow * m_popup = nullptr;
|
||||
wxPanel * m_pan = nullptr;
|
||||
|
||||
void OnControlDestroy ( wxWindowDestroyEvent& evt );
|
||||
void OnPopupDestroy ( wxWindowDestroyEvent& evt );
|
||||
};
|
||||
|
||||
#endif /* CONFIGEDITORPOPUP_H */
|
||||
|
||||
132
Resources/Utilities/MiscTools.cpp
Normal file
132
Resources/Utilities/MiscTools.cpp
Normal file
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* File: MiscTools.cpp
|
||||
* Author: Saleem EDAH-TALLY - nmset@yandex.com
|
||||
* License: CeCILL-C
|
||||
* Copyright Saleem EDAH-TALLY - © 2017
|
||||
*
|
||||
* Created on 4 mars 2017, 11:40
|
||||
*/
|
||||
|
||||
#include "MiscTools.h"
|
||||
#include <wx/notifmsg.h>
|
||||
#include <wx/msgdlg.h>
|
||||
|
||||
MiscTools::MiscTools()
|
||||
{
|
||||
}
|
||||
|
||||
MiscTools::~MiscTools()
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Under this... thing called Wayland, GetPosition() returns (0, 0)!
|
||||
* Use "GDK_BACKEND=x11".
|
||||
*/
|
||||
void MiscTools::SaveSizePos(wxConfig* config, wxWindow* wind, const wxString& pathPrefix)
|
||||
{
|
||||
wxASSERT_MSG ( ( config != nullptr ),_T("config IS nullptr") );
|
||||
wxASSERT_MSG ( ( wind != nullptr ),_T("wind IS nullptr") );
|
||||
config->Write ( pathPrefix +_T("/Width"), wind->GetSize().GetWidth() );
|
||||
config->Write ( pathPrefix +_T("/Height"), wind->GetSize().GetHeight() );
|
||||
config->Write ( pathPrefix +_T("/X"), wind->GetPosition().x );
|
||||
config->Write ( pathPrefix +_T("/Y"), wind->GetPosition().y );
|
||||
config->Flush();
|
||||
}
|
||||
|
||||
void MiscTools::RestoreSizePos ( wxConfig* config, wxWindow* wind, const wxString& pathPrefix )
|
||||
{
|
||||
wxASSERT_MSG ( ( config != nullptr ),_T("config IS nullptr") );
|
||||
wxASSERT_MSG ( ( wind != nullptr ),_T("wind IS nullptr") );
|
||||
long w = 0, h = 0;
|
||||
config->Read ( pathPrefix +_T("/Width"), &w );
|
||||
config->Read ( pathPrefix +_T("/Height"), &h );
|
||||
if ( w && h )
|
||||
{
|
||||
wind->SetSize ( w, h );
|
||||
}
|
||||
|
||||
wxScreenDC dc;
|
||||
const int screenWidth = dc.GetSize().GetWidth();
|
||||
const int screenHeight = dc.GetSize().GetHeight();
|
||||
if (screenWidth && screenHeight)
|
||||
{
|
||||
long x = 0, y = 0;
|
||||
bool res = config->Read ( pathPrefix +_T("/X"), &x );
|
||||
res = config->Read ( pathPrefix +_T("/Y"), &y );
|
||||
if ( !res )
|
||||
{
|
||||
wind->Centre();
|
||||
return;
|
||||
}
|
||||
wind->SetPosition ( wxPoint ( x, y ) );
|
||||
}
|
||||
}
|
||||
|
||||
void MiscTools::ShowTransientPopup ( wxPopupTransientWindow* p, wxWindow* content,
|
||||
const int width, const int height )
|
||||
{
|
||||
wxASSERT_MSG ( ( p != nullptr ),_T("p IS nullptr") );
|
||||
wxASSERT_MSG ( ( content != nullptr ),_T("content IS nullptr") );
|
||||
wxBoxSizer * sz = new wxBoxSizer ( wxVERTICAL );
|
||||
p->SetSizer ( sz );
|
||||
int popupWidth = width;
|
||||
int popupHeight = height;
|
||||
if ( width < 1 )
|
||||
popupWidth = content->GetSize().GetWidth();
|
||||
if ( height < 1 )
|
||||
popupHeight = content->GetSize().GetHeight();
|
||||
p->SetSize ( wxSize ( popupWidth, popupHeight ) );
|
||||
|
||||
sz->Add ( content, 0, wxGROW | wxALL );
|
||||
sz->Layout();
|
||||
/*
|
||||
* Under Wayland, screen size is invalid (0, 0) with wxScreenDC.
|
||||
* wxVideoMode obtained from wxApp doesn't help, it's even worse.
|
||||
* Using GDK_BACKEND="x11" fixes the placement issue with wxScreenDC,
|
||||
* but not with wxVideoMode.
|
||||
*/
|
||||
wxScreenDC dc;
|
||||
const int screenWidth = dc.GetSize().GetWidth();
|
||||
const int screenHeight = dc.GetSize().GetHeight();
|
||||
const wxPoint mousePos = wxGetMousePosition();
|
||||
wxPoint dest ( mousePos.x, mousePos.y );
|
||||
if (screenWidth && screenHeight)
|
||||
{
|
||||
if ( mousePos.x > ( screenWidth - popupWidth ) ) dest.x = ( screenWidth - popupWidth );
|
||||
if ( mousePos.y > ( screenHeight - popupHeight ) ) dest.y = ( screenHeight - popupHeight );
|
||||
if ( popupWidth > screenWidth ) dest.x = 0;
|
||||
if ( popupHeight > screenHeight ) dest.y = 0;
|
||||
}
|
||||
p->SetPosition ( dest );
|
||||
p->Popup();
|
||||
}
|
||||
|
||||
void MiscTools::MessageBox ( const wxString& msg, const bool notify )
|
||||
{
|
||||
wxApp * app = static_cast<wxApp*> ( wxApp::GetInstance() );
|
||||
if ( !notify )
|
||||
{
|
||||
wxMessageBox ( msg, app->GetAppName(), wxOK, app->GetTopWindow() );
|
||||
}
|
||||
else
|
||||
{
|
||||
wxNotificationMessage notifMsg ( app->GetAppName(), msg, app->GetTopWindow() );
|
||||
notifMsg.Show();
|
||||
}
|
||||
}
|
||||
|
||||
wxTextValidator* MiscTools::MakeFileNameValidator ( bool excludeSpace )
|
||||
{
|
||||
wxTextValidator * tval = new wxTextValidator ( wxFILTER_EXCLUDE_CHAR_LIST );
|
||||
const wxString xcl = wxFileName::GetForbiddenChars();
|
||||
wxArrayString arr;
|
||||
for ( unsigned short i = 0; i < xcl.Length(); i++ )
|
||||
{
|
||||
arr.Add ( xcl.GetChar ( i ) );
|
||||
}
|
||||
if ( excludeSpace ) arr.Add (_T(" ") );
|
||||
arr.Add ( wxFileName::GetPathSeparator() );
|
||||
tval->SetExcludes ( arr );
|
||||
return tval;
|
||||
}
|
||||
60
Resources/Utilities/MiscTools.h
Normal file
60
Resources/Utilities/MiscTools.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* File: MiscTools.h
|
||||
* Author: Saleem EDAH-TALLY - nmset@yandex.com
|
||||
* License: CeCILL-C
|
||||
* Copyright Saleem EDAH-TALLY - © 2017
|
||||
*
|
||||
* Created on 4 mars 2017, 11:40
|
||||
*/
|
||||
|
||||
#ifndef MISCTOOLS_H
|
||||
#define MISCTOOLS_H
|
||||
|
||||
#include <wx/wx.h>
|
||||
#include <wx/config.h>
|
||||
#include <wx/popupwin.h>
|
||||
|
||||
/**
|
||||
* Miscellaneous static functions.
|
||||
*/
|
||||
class MiscTools
|
||||
{
|
||||
public:
|
||||
MiscTools();
|
||||
virtual ~MiscTools();
|
||||
|
||||
/**
|
||||
* Saves size and position of a wxWindow.
|
||||
*/
|
||||
static void SaveSizePos ( wxConfig * config, wxWindow * wind, const wxString& pathPrefix );
|
||||
|
||||
/**
|
||||
* Restores size and position of a wxWindow.
|
||||
*/
|
||||
static void RestoreSizePos ( wxConfig * config, wxWindow * wind, const wxString& pathPrefix );
|
||||
|
||||
/**
|
||||
* Shows a transient popup at mouse cursor.
|
||||
* Position the popup relative to screen edges and popup dimensions,
|
||||
* if possible.
|
||||
*/
|
||||
static void ShowTransientPopup ( wxPopupTransientWindow * p, wxWindow* content,
|
||||
const int width = 0, const int height = 0 );
|
||||
|
||||
/**
|
||||
* Shows a message as a modal dialog or as a notification.
|
||||
*/
|
||||
static void MessageBox ( const wxString& msg, const bool notify = false );
|
||||
|
||||
/**
|
||||
* Creates a validator excluding file name forbidden characters, path
|
||||
* separator and optionally space character.
|
||||
*/
|
||||
static wxTextValidator* MakeFileNameValidator ( bool excludeSpace = true );
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
#endif /* MISCTOOLS_H */
|
||||
|
||||
29
Resources/Utilities/PopupTransientWindow.cpp
Normal file
29
Resources/Utilities/PopupTransientWindow.cpp
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* File: PopupTransientWindow.cpp
|
||||
* Author: Saleem EDAH-TALLY - nmset@yandex.com
|
||||
* License: CeCILL-C
|
||||
* Copyright Saleem EDAH-TALLY - © 2017
|
||||
*
|
||||
* Created on 3 mars 2017, 19:45
|
||||
*/
|
||||
|
||||
#include "PopupTransientWindow.h"
|
||||
|
||||
IMPLEMENT_CLASS ( PopupTransientWindow, wxPopupTransientWindow )
|
||||
|
||||
PopupTransientWindow::PopupTransientWindow()
|
||||
: wxPopupTransientWindow()
|
||||
{}
|
||||
|
||||
PopupTransientWindow::PopupTransientWindow ( wxWindow* parent, int flags )
|
||||
: wxPopupTransientWindow ( parent, flags )
|
||||
{}
|
||||
|
||||
PopupTransientWindow::~PopupTransientWindow()
|
||||
{}
|
||||
|
||||
void PopupTransientWindow::Dismiss()
|
||||
{
|
||||
Destroy();
|
||||
}
|
||||
|
||||
33
Resources/Utilities/PopupTransientWindow.h
Normal file
33
Resources/Utilities/PopupTransientWindow.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* File: PopupTransientWindow.h
|
||||
* Author: Saleem EDAH-TALLY - nmset@yandex.com
|
||||
* License: CeCILL-C
|
||||
* Copyright Saleem EDAH-TALLY - © 2017
|
||||
*
|
||||
* Created on 3 mars 2017, 19:45
|
||||
*/
|
||||
|
||||
#ifndef POPUPTRANSIENTWINDOW_H
|
||||
#define POPUPTRANSIENTWINDOW_H
|
||||
|
||||
#include <wx/wx.h>
|
||||
#include <wx/popupwin.h>
|
||||
|
||||
/** No further functionality provided here on top of wxPopupTransientWindow.\n
|
||||
* Just calls Destroy() on dismiss.
|
||||
*/
|
||||
class PopupTransientWindow : public wxPopupTransientWindow
|
||||
{
|
||||
DECLARE_CLASS ( PopupTransientWindow )
|
||||
public:
|
||||
PopupTransientWindow();
|
||||
PopupTransientWindow ( wxWindow *parent, int flags = wxBORDER_NONE );
|
||||
virtual ~PopupTransientWindow();
|
||||
|
||||
void Dismiss() override;
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
#endif /* POPUPTRANSIENTWINDOW_H */
|
||||
|
||||
58
Resources/Utilities/TimeredStatusBar.cpp
Normal file
58
Resources/Utilities/TimeredStatusBar.cpp
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* File: TimeredStatusBar.cpp
|
||||
* Author: Saleem EDAH-TALLY - nmset@yandex.com
|
||||
* License: CeCILL-C
|
||||
* Copyright Saleem EDAH-TALLY - © 2017
|
||||
*
|
||||
* Created on April 22, 2018, 3:55 PM
|
||||
*/
|
||||
|
||||
#include "TimeredStatusBar.h"
|
||||
|
||||
TimeredStatusBar::TimeredStatusBar ( wxWindow * parent)
|
||||
: wxStatusBar ( parent, wxID_ANY )
|
||||
{
|
||||
m_numFields = 3;
|
||||
/* We use default reasonable widths for CAPS and NUM. */
|
||||
const int widths[3] = {-1, 70, 70};
|
||||
SetFieldsCount ( m_numFields, widths );
|
||||
m_timer.Stop();
|
||||
m_timer.SetOwner ( this );
|
||||
Bind ( wxEVT_TIMER, &TimeredStatusBar::OnTimer, this );
|
||||
Bind ( wxEVT_IDLE, &TimeredStatusBar::OnIdle, this );
|
||||
}
|
||||
|
||||
TimeredStatusBar::~TimeredStatusBar()
|
||||
{
|
||||
}
|
||||
|
||||
void TimeredStatusBar::SetTransientText ( const wxString& text, int duration )
|
||||
{
|
||||
wxStatusBar::SetStatusText ( text, 0 );
|
||||
m_timer.Start ( duration, wxTIMER_ONE_SHOT );
|
||||
}
|
||||
|
||||
void TimeredStatusBar::OnTimer ( wxTimerEvent& evt )
|
||||
{
|
||||
wxStatusBar::SetStatusText ( wxEmptyString, 0 );
|
||||
}
|
||||
|
||||
void TimeredStatusBar::OnIdle ( wxIdleEvent& evt )
|
||||
{
|
||||
if ( wxGetKeyState ( WXK_NUMLOCK ) )
|
||||
{
|
||||
SetStatusText (_("NUM"), m_numFields - 2 );
|
||||
}
|
||||
else
|
||||
{
|
||||
SetStatusText ( wxEmptyString, m_numFields - 2 );
|
||||
}
|
||||
if ( wxGetKeyState ( WXK_CAPITAL ) )
|
||||
{
|
||||
SetStatusText (_("CAPS"), m_numFields - 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
SetStatusText ( wxEmptyString, m_numFields - 1 );
|
||||
}
|
||||
}
|
||||
38
Resources/Utilities/TimeredStatusBar.h
Normal file
38
Resources/Utilities/TimeredStatusBar.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* File: TimeredStatusBar.h
|
||||
* Author: Saleem EDAH-TALLY - nmset@yandex.com
|
||||
* License: CeCILL-C
|
||||
* Copyright Saleem EDAH-TALLY - © 2017
|
||||
*
|
||||
* Created on April 22, 2018, 3:55 PM
|
||||
*/
|
||||
|
||||
#ifndef TIMEREDSTATUSBAR_H
|
||||
#define TIMEREDSTATUSBAR_H
|
||||
|
||||
#include <wx/wx.h>
|
||||
#include <wx/timer.h>
|
||||
|
||||
/**
|
||||
* We want to show a transient message.\n
|
||||
* The widget show also CAPS and NUM status.\n
|
||||
*/
|
||||
class TimeredStatusBar : public wxStatusBar
|
||||
{
|
||||
public:
|
||||
TimeredStatusBar ( wxWindow * parent );
|
||||
virtual ~TimeredStatusBar();
|
||||
|
||||
/**
|
||||
* Called by the application to display 'text' transiently.
|
||||
*/
|
||||
void SetTransientText ( const wxString& text, int duration = 3000);
|
||||
void OnIdle ( wxIdleEvent& evt );
|
||||
private:
|
||||
uint m_numFields = 3;
|
||||
wxTimer m_timer;
|
||||
void OnTimer ( wxTimerEvent& evt );
|
||||
};
|
||||
|
||||
#endif /* TIMEREDSTATUSBAR_H */
|
||||
|
||||
35
Resources/Utilities/XClientData.hpp
Normal file
35
Resources/Utilities/XClientData.hpp
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* File: XClientData.hpp
|
||||
* Author: Saleem Edah-Tally - nmset@yandex.com
|
||||
* License: CeCILL-C
|
||||
* Copyright Saleem Edah-Tally - © 2024
|
||||
*
|
||||
* Created on ?
|
||||
*/
|
||||
|
||||
#ifndef XCLIENTDATA_H
|
||||
#define XCLIENTDATA_H
|
||||
|
||||
#include <wx/wx.h>
|
||||
|
||||
/**
|
||||
* For the available scanner list.
|
||||
*/
|
||||
class XClientData : public wxClientData
|
||||
{
|
||||
public :
|
||||
XClientData ( const wxVariant& data ) : wxClientData()
|
||||
{
|
||||
m_data = data;
|
||||
}
|
||||
virtual ~XClientData() {};
|
||||
|
||||
wxVariant GetData() const
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
private:
|
||||
wxVariant m_data;
|
||||
};
|
||||
|
||||
#endif // XCLIENTDATA_H
|
||||
163
XS7.cpp
Normal file
163
XS7.cpp
Normal file
@@ -0,0 +1,163 @@
|
||||
// /*
|
||||
// * File: XS7.cpp
|
||||
// * Author: Saleem Edah-Tally - nmset@yandex.com
|
||||
// * License : CeCILL
|
||||
// * Copyright Saleem Edah-Tally - © 2023
|
||||
// *
|
||||
// * Created on 18 06 2025, 22:42
|
||||
// */
|
||||
|
||||
#include "XS7.h"
|
||||
#include "globals.h"
|
||||
#include "TimeredStatusBar.h"
|
||||
#include "MiscTools.h"
|
||||
#include "page.xpm"
|
||||
#include <wx/stdpaths.h>
|
||||
#include <wx/cmdline.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
XS7::XS7(wxWindow* parent, wxWindowID id, const wxString& caption, const wxPoint& pos, const wxSize& size, long style)
|
||||
: S7(parent, id, caption, pos, size, style)
|
||||
{}
|
||||
|
||||
bool XS7::ParseCmdLine()
|
||||
{
|
||||
wxCmdLineParser p;
|
||||
p.SetCmdLine ( wxApp::GetInstance()->argc, wxApp::GetInstance()->argv );
|
||||
p.SetSwitchChars ( _T ( "-" ) );
|
||||
p.AddOption ( _T ( "c" ), wxEmptyString, _ ( "Config file tag." ) );
|
||||
p.AddSwitch ( _T ( "v" ), wxEmptyString, _ ( "Show version and quit." ) );
|
||||
p.AddSwitch ( _T ( "h" ), wxEmptyString, _ ( "Show help and quit." ) );
|
||||
p.Parse ( false );
|
||||
if ( p.Found ( _T ( "c" ) ) )
|
||||
{
|
||||
p.Found ( _T ( "c" ), &m_configTag );
|
||||
return true;
|
||||
}
|
||||
if ( p.Found ( _T ( "h" ) ) )
|
||||
{
|
||||
p.Usage();
|
||||
return false; //Exit code is 255, not clean.
|
||||
}
|
||||
if ( p.Found ( _T ( "v" ) ) )
|
||||
{
|
||||
cout << ( _APPNAME_ + _ ( " - version " ) + to_string(_APPVERSION_) ) << endl;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void XS7::Setup()
|
||||
{
|
||||
const wxString configDir = wxFileConfig::GetLocalFile ( _APPNAME_, wxCONFIG_USE_SUBDIR ).GetPath();
|
||||
if ( !wxFileName::Exists ( configDir ) )
|
||||
wxFileName::Mkdir ( configDir );
|
||||
|
||||
const wxString configBaseName = m_configTag.IsEmpty()
|
||||
? _APPNAME_
|
||||
: _APPNAME_ + wxString("-") + m_configTag;
|
||||
m_config = std::make_unique<wxFileConfig>(_APPNAME_, _T("SET"), configBaseName,
|
||||
wxEmptyString, wxCONFIG_USE_SUBDIR);
|
||||
TimeredStatusBar * sb = new TimeredStatusBar(this);
|
||||
SetStatusBar(sb);
|
||||
|
||||
m_insaneWidget = new XInsaneWidget(panMain, sb, m_config.get());
|
||||
szMain->Add(m_insaneWidget, 0, wxGROW | wxALL);
|
||||
|
||||
dpkDestination->Bind ( wxEVT_DIRPICKER_CHANGED, &XS7::OnDpkRepositoryChange, this );
|
||||
dpkDestination->GetTextCtrl()->Bind ( wxEVT_LEFT_DCLICK, &XS7::OnDpkDoubleClick, this );
|
||||
Bind(wxEVT_CHAR_HOOK, &XS7::OnAppKeyPressed, this);
|
||||
m_insaneWidget->lblNewDoc->Bind ( wxEVT_LEFT_UP, &XS7::OnNewDocLeftClick, this );
|
||||
dpkDestination->SetPath(m_config->Read("/Docroot"));
|
||||
|
||||
txtBasename->SetValidator(*MiscTools::MakeFileNameValidator(false));
|
||||
txtBasename->Bind(wxEVT_LEFT_UP, &XS7::OnAbout, this);
|
||||
MiscTools::RestoreSizePos(m_config.get(), this, wxString("/" + wxString(_APPNAME_)));
|
||||
|
||||
S7::SetTitle(wxString(_APPNAME_) + " - version " + to_string(_APPVERSION_));
|
||||
|
||||
SetIcon(wxICON(page));
|
||||
wxString fixedTip = _("'Shift + left' click to generate a new destination file name.");
|
||||
fixedTip += _T("\n") + m_insaneWidget->lblNewDoc->GetToolTipText();
|
||||
m_insaneWidget->lblNewDoc->SetToolTip(fixedTip);
|
||||
}
|
||||
|
||||
XS7::~XS7()
|
||||
{
|
||||
if (m_config)
|
||||
MiscTools::SaveSizePos(m_config.get(), this, wxString("/") + _APPNAME_);
|
||||
}
|
||||
|
||||
void XS7::OnDpkRepositoryChange ( wxFileDirPickerEvent& evt )
|
||||
{
|
||||
m_config->Write ( _T ( "/DocRoot" ), dpkDestination->GetPath() );
|
||||
m_config->Flush();
|
||||
evt.Skip();
|
||||
}
|
||||
|
||||
void XS7::OnDpkDoubleClick ( wxMouseEvent& evt )
|
||||
{
|
||||
const wxString command = _T ( "xdg-open " ) + dpkDestination->GetPath();
|
||||
if ( wxExecute ( command ) == 0 )
|
||||
{
|
||||
const wxString msg = _( "Could not launch default file manager" );
|
||||
MiscTools::MessageBox( msg, true );
|
||||
cerr << msg << endl;
|
||||
}
|
||||
evt.Skip();
|
||||
}
|
||||
|
||||
void XS7::OnAppKeyPressed(wxKeyEvent& evt)
|
||||
{
|
||||
if (evt.GetKeyCode() == WXK_ESCAPE)
|
||||
if (m_insaneWidget)
|
||||
m_insaneWidget->CancelScanning();
|
||||
evt.Skip();
|
||||
}
|
||||
|
||||
void XS7::OnNewDocLeftClick ( wxMouseEvent& evt )
|
||||
{
|
||||
if ( !evt.ShiftDown() )
|
||||
{
|
||||
evt.Skip();
|
||||
return;
|
||||
}
|
||||
if ( !dpkDestination->GetDirName().Exists() )
|
||||
{
|
||||
const wxString msg = _( "Invalid folder name." );
|
||||
MiscTools::MessageBox ( msg, true );
|
||||
cerr << msg << endl;
|
||||
evt.Skip();
|
||||
return;
|
||||
}
|
||||
if ( txtBasename->GetValue().IsEmpty() )
|
||||
{
|
||||
const wxString msg = _( "Invalid file basename." );
|
||||
MiscTools::MessageBox ( msg, true );
|
||||
cerr << msg << endl;
|
||||
evt.Skip();
|
||||
return;
|
||||
}
|
||||
const wxString filepath = dpkDestination->GetPath() + wxFileName::GetPathSeparator() + txtBasename->GetValue();
|
||||
|
||||
m_insaneWidget->txtNewDoc->SetValue ( filepath );
|
||||
m_insaneWidget->ResetScanProject();
|
||||
evt.Skip();
|
||||
}
|
||||
|
||||
void XS7::OnAbout(wxMouseEvent& evt)
|
||||
{
|
||||
if (!evt.ControlDown())
|
||||
{
|
||||
evt.Skip();
|
||||
return;
|
||||
}
|
||||
const wxString msg = wxString(_APPNAME_) + _(" - version ") + to_string((_APPVERSION_))
|
||||
+ _ (", using InsaneWidget.\n\n")
|
||||
+ _ ( "Copyright: Saleem Edah-Tally [Surgeon] [Hobbyist developer]\n" )
|
||||
+ _ ( "License: CeCILL/CeCILL-C per file header." );
|
||||
|
||||
MiscTools::MessageBox(msg);
|
||||
evt.Skip();
|
||||
}
|
||||
44
XS7.h
Normal file
44
XS7.h
Normal file
@@ -0,0 +1,44 @@
|
||||
// /*
|
||||
// * File: XS7.h
|
||||
// * Author: Saleem Edah-Tally - nmset@yandex.com
|
||||
// * License : CeCILL
|
||||
// * Copyright Saleem Edah-Tally - © 2023
|
||||
// *
|
||||
// * Created on 18 06 2025, 22:42
|
||||
// */
|
||||
|
||||
#ifndef XS7_H
|
||||
#define XS7_H
|
||||
|
||||
#include "s7.h"
|
||||
#include <wx/wx.h>
|
||||
#include <XInsaneWidget.h>
|
||||
#include <fstream>
|
||||
|
||||
class XS7 : public S7
|
||||
{
|
||||
public:
|
||||
XS7(wxWindow* parent, wxWindowID id = SYMBOL_S7_IDNAME, const wxString& caption = SYMBOL_S7_TITLE,
|
||||
const wxPoint& pos = SYMBOL_S7_POSITION, const wxSize& size = SYMBOL_S7_SIZE, long style = SYMBOL_S7_STYLE );
|
||||
virtual ~XS7();
|
||||
bool ParseCmdLine();
|
||||
void Setup();
|
||||
|
||||
private:
|
||||
std::unique_ptr<wxConfig> m_config = nullptr;
|
||||
XInsaneWidget * m_insaneWidget = nullptr;
|
||||
|
||||
/*
|
||||
* An optional tag for wxConfig files. This allows using different profiles
|
||||
* by specifying the -c command line option.
|
||||
*/
|
||||
wxString m_configTag;
|
||||
|
||||
void OnDpkRepositoryChange ( wxFileDirPickerEvent& evt );
|
||||
void OnDpkDoubleClick ( wxMouseEvent& evt );
|
||||
void OnAppKeyPressed(wxKeyEvent& evt);
|
||||
void OnNewDocLeftClick ( wxMouseEvent& evt ); // wxStaticText in m_insaneWidget.
|
||||
void OnAbout(wxMouseEvent& evt);
|
||||
};
|
||||
|
||||
#endif // XS7_H
|
||||
18
globals.h
Normal file
18
globals.h
Normal file
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* File: globals.h
|
||||
* Author: Saleem EDAH-TALLY - nmset@yandex.com
|
||||
* License : CeCILL
|
||||
* Copyright Saleem EDAH-TALLY - © 2017
|
||||
*
|
||||
* Created on 27 février 2017, 22:28
|
||||
*/
|
||||
|
||||
#ifndef GLOBALS_H
|
||||
#define GLOBALS_H
|
||||
|
||||
#define _APPNAME_ "S7"
|
||||
#define _APPVERSION_ 1
|
||||
#define _INSANEWIDGET_NAME "InsaneWidget"
|
||||
|
||||
#endif /* GLOBALS_H */
|
||||
|
||||
154
page.xpm
Normal file
154
page.xpm
Normal file
@@ -0,0 +1,154 @@
|
||||
/* XPM */
|
||||
static char * page_xpm[] = {
|
||||
"128 128 23 1",
|
||||
" c None",
|
||||
". c #5C889D",
|
||||
"+ c #5C869E",
|
||||
"@ c #5C889C",
|
||||
"# c #5E889E",
|
||||
"$ c #5E879D",
|
||||
"% c #5D889C",
|
||||
"& c #5E869D",
|
||||
"* c #5E889C",
|
||||
"= c #5E879C",
|
||||
"- c #5D879D",
|
||||
"; c #5E869C",
|
||||
"> c #5C869C",
|
||||
", c #5E889D",
|
||||
"' c #5C889E",
|
||||
") c #5E879E",
|
||||
"! c #5D869C",
|
||||
"~ c #5E869E",
|
||||
"{ c #5D889D",
|
||||
"] c #5D889E",
|
||||
"^ c #5D869E",
|
||||
"/ c #5D879E",
|
||||
"( c #5C879C",
|
||||
" .+@+ ",
|
||||
" #######. ",
|
||||
" #########+ ",
|
||||
" #### $### ",
|
||||
" %##& *##$ ",
|
||||
" =## ##% ",
|
||||
" -@############ ############; ",
|
||||
" ##############> ;############## ",
|
||||
" #################*,'###############* ",
|
||||
" #################################### ",
|
||||
" ##################) #################################### @################## ",
|
||||
" ####################) #################################### @###################! ",
|
||||
" #####################) #################################### @####################@ ",
|
||||
" ######################) #################################### @#####################~ ",
|
||||
" ######################) #################################### @###################### ",
|
||||
" ;######################) #################################### @######################{ ",
|
||||
" '######################) #################################### @####################### ",
|
||||
" #######################) #################################### @####################### ",
|
||||
" #########; #################################### ~######### ",
|
||||
" ########+ ;##################################+ '######## ",
|
||||
" ########) '######## ",
|
||||
" ########) {######## ",
|
||||
" ########) {######## ",
|
||||
" ########) {######## ",
|
||||
" ########) {######## ",
|
||||
" ########) {######## ",
|
||||
" ########) {######## ",
|
||||
" ########) {######## ",
|
||||
" ########) {######## ",
|
||||
" ########) {######## ",
|
||||
" ########) {######## ",
|
||||
" ########) {######## ",
|
||||
" ########) )$$$$$$$$$$$$$$$$$$ $$$$$$$$$$$$$$$$$$$$$$$$$$$, {######## ",
|
||||
" ########) #################### #############################* {######## ",
|
||||
" ########) #################### #############################] {######## ",
|
||||
" ########) #################### {######## ",
|
||||
" ########) #################### {######## ",
|
||||
" ########) #################### {######## ",
|
||||
" ########) #################### {######## ",
|
||||
" ########) #################### {######## ",
|
||||
" ########) #################### {######## ",
|
||||
" ########) #################### *~~~~~~~~~~~~~~~~~~~~~~~~~~~# {######## ",
|
||||
" ########) #################### #############################& {######## ",
|
||||
" ########) #################### '############################# {######## ",
|
||||
" ########) #################### {######## ",
|
||||
" ########) #################### {######## ",
|
||||
" ########) #################### {######## ",
|
||||
" ########) #################### {######## ",
|
||||
" ########) #################### {######## ",
|
||||
" ########) #################### {######## ",
|
||||
" ########) #################### ^############################# {######## ",
|
||||
" ########) #################### ############################## {######## ",
|
||||
" ########) ,##################! ~###########################; {######## ",
|
||||
" ########) {######## ",
|
||||
" ########) {######## ",
|
||||
" ########) {######## ",
|
||||
" ########) {######## ",
|
||||
" ########) {######## ",
|
||||
" ########) ######################################################) {######## ",
|
||||
" ########) ########################################################, {######## ",
|
||||
" ########) ########################################################* {######## ",
|
||||
" ########) ))))))))))))))))))))))))))))))))))))))))))))))))))))))- {######## ",
|
||||
" ########) {######## ",
|
||||
" ########) {######## ",
|
||||
" ########) {######## ",
|
||||
" ########) {######## ",
|
||||
" ########) {######## ",
|
||||
" ########) {######################################################; {######## ",
|
||||
" ########) ########################################################' {######## ",
|
||||
" ########) ########################################################/ {######## ",
|
||||
" ########) {######## ",
|
||||
" ########) {######## ",
|
||||
" ########) {######## ",
|
||||
" ########) {######## ",
|
||||
" ########) {######## ",
|
||||
" ########) {######## ",
|
||||
" ########) (######################################################' {######## ",
|
||||
" ########) ######################################################### {######## ",
|
||||
" ########) ;####################################################### {######## ",
|
||||
" ########) {######## ",
|
||||
" ########) {######## ",
|
||||
" ########) {######## ",
|
||||
" ########) {######## ",
|
||||
" ########) {######## ",
|
||||
" ########) {######## ",
|
||||
" ########) ############################ {######## ",
|
||||
" ########) ############################ {######## ",
|
||||
" ########) ;~~~~~~~~~~~~~~~~~~~~~~~~~~, {######## ",
|
||||
" ########) {######## ",
|
||||
" ########) {######## ",
|
||||
" ########) {######## ",
|
||||
" ########) {######## ",
|
||||
" ########) {######## ",
|
||||
" ########) {######## ",
|
||||
" ########) {######## ",
|
||||
" ########) )######## ",
|
||||
" ########) /'###############^ (######## ",
|
||||
" ########) $################^ (######### ",
|
||||
" ########) ,###############^ (########## ",
|
||||
" ########) )##############^ (########### ",
|
||||
" ########) )#############^ (############ ",
|
||||
" ########) )############^ (############# ",
|
||||
" ########) )###########^ (############## ",
|
||||
" ########) )##########^ (############### ",
|
||||
" ########) )#########^ (################ ",
|
||||
" ########) )########^ (################# ",
|
||||
" ########) )#######^ (################## ",
|
||||
" ########) )######^ (################### ",
|
||||
" ########) )#####^ (#################### ",
|
||||
" ########) )####^ (##################### ",
|
||||
" ########) )###^ (###################### ",
|
||||
" ########) )##^ (####################### ",
|
||||
" ########) )#^ (######################## ",
|
||||
" ########) )^ (######################### ",
|
||||
" ########) # (########################## ",
|
||||
" ########) (########################### ",
|
||||
" ########{ (############################ ",
|
||||
" ######### (############################# ",
|
||||
" #########) (############################## ",
|
||||
" ##########~;..............................................*############################### ",
|
||||
" ########################################################################################## ",
|
||||
" ~######################################################################################### ",
|
||||
" ^########################################################################################{ ",
|
||||
" +######################################################################################; ",
|
||||
" ###################################################################################### ",
|
||||
" $####################################################################################{ ",
|
||||
" +################################################################################~ ",
|
||||
" #;+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;*#& "};
|
||||
Reference in New Issue
Block a user