pax_global_header00006660000000000000000000000064134536456670014535gustar00rootroot0000000000000052 comment=357f16a1ba9f00eda4cced23a6a4711492560b27 lios-3-2.7.2/000077500000000000000000000000001345364566700126535ustar00rootroot00000000000000lios-3-2.7.2/COPYING000066400000000000000000000000101345364566700136750ustar00rootroot00000000000000COPYING lios-3-2.7.2/LICENSE000066400000000000000000001044611345364566700136660ustar00rootroot00000000000000GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. {one line to give the program's name and a brief idea of what it does.} Copyright (C) {year} {name of author} This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: {project} Copyright (C) {year} {fullname} This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . lios-3-2.7.2/NEWS000066400000000000000000000000101345364566700133410ustar00rootroot00000000000000COPYING lios-3-2.7.2/README.md000066400000000000000000000075271345364566700141450ustar00rootroot00000000000000Linux-intelligent-ocr-solution ====== Lios is a free and open source software for converting print in to text using either scanner or a camera, It can also produce text out of scanned images from other sources such as Pdf, Image, Folder containing Images or screenshot. Program is given total accessibility for visually impaired. Lios is written in python3, and we release it under GPL-3 license. There are great many possibilities for this program, Feedback is the key to it, Expecting your feedback. Features ====== 1. Import images from Scanner, PDFs, Folder, or Webcam, 2. Take and Recognize Screenshot, 3. Recognize Selected Areas(Rectangle selection), 4. Support two OCR Engines (Cuneiform,Tesseract), 5. Tesseract Trainer GUI - Train your Tesseract to improve accuracy, 6. Text-Cleaner - Post process your output with match-replace dialog, 7. Tesseract-Trainer - Train your tesseract ocr engine to improve the accuracy, 8. Full Auto Rotation for any Language(If aspell installed for the language, Eg : "sudo apt-get install aspell-hi" for Hindi, 9. Side by side view of image and output 10. Advanced Scanner Brightness optimizer, 11. Text Reader for low vision with Highlighting, With user selected Color, Font, and Background Color, 12. Audio converter(espeak), 13. Spell-checker(aspell), 14. Export as pdf (text/images), 15. Dictionary Support for English(Artha) 16. Options for save, load and reset settings, 17. Other options - Find, Find-and-Replace, Go-To-Page, Go-To-Line, Append file, Punch File, Selection of starting page number, page numbering mode and number of pages to scan, Selection of Scan area, brightness, resolution and time between repeated scanning, Output Insert position, image rotation and zoom options, etc Installing ====== Dependecy list : python3, python3-imaging-sane|python3-sane, python3-speechd, tesseract-ocr, imagemagick, cuneiform, espeak,poppler-utils, python3-enchant,aspell-en, gir1.2-gst-plugins-base-1.0, gir1.2-gstreamer-1.0 git clone https://gitlab.com/Nalin-x-Linux/lios-3.git cd lios-3 python3 setup.py install --install-data=/usr Links ====== Forum : https://groups.google.com/forum/#!forum/lios Home Page : http://sourceforge.net/projects/lios/?source=navbar Video Tutorials : https://www.youtube.com/playlist?list=PLn29o8rxtRe1zS1r2-yGm1DNMOZCgdU0i Disclaimer ====== Copyright (c) 2011-2015 Lios Development Team All rights reserved . Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the below copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the below copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of the nor the Lios team names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." FREE SOFTWARE FREE SOCIETY lios-3-2.7.2/bin/000077500000000000000000000000001345364566700134235ustar00rootroot00000000000000lios-3-2.7.2/bin/lios000077500000000000000000000002771345364566700143250ustar00rootroot00000000000000#!/usr/bin/env python3 from lios.main import * if __name__ == '__main__': if (len(sys.argv) >= 2): linux_intelligent_ocr_solution(sys.argv) else: linux_intelligent_ocr_solution() lios-3-2.7.2/bin/train-tesseract000077500000000000000000000003331345364566700164600ustar00rootroot00000000000000#! /usr/bin/python3 import sys from lios import train_tesseract if __name__ == '__main__': if (len(sys.argv) >= 2): train_tesseract.TesseractTrainerGUI(sys.argv[1:]) else: train_tesseract.TesseractTrainerGUI([]) lios-3-2.7.2/control000066400000000000000000000023111345364566700142530ustar00rootroot00000000000000Package: lios Priority: optional Section: graphics Installed-Size: 380 Architecture: all Version: 2.7.1 Depends: python3,python3-imaging-sane|python3-sane,python3-speechd,tesseract-ocr,imagemagick,espeak,poppler-utils,python3-enchant,aspell-en,gir1.2-gst-plugins-base-1.0,gir1.2-gstreamer-1.0 Maintainer: Nalin.x.Linux Homepage: http://sourceforge.net/projects/lios/ Description: Easy ocr solution for gnu/linux Lios is a free and open source software for converting print in to text using either scanner, camera, or screenshot, It can also produce text out of scanned images from other sources such as Pdf, Image or Folder containing Images. Program is given total accessibility for visually impaired. Lios is written in python3, and we release it under GPL-3 license. key fetures of lios 1 Continues Scan and OCR with reading 2 Optimize scanner brightness 3 Tesseract Trainer GUI 4 Full auto rotation (for visually impaired) 5 A better rectangle selector 6 Text Reader for low vision with Highlighting, With user selected Color, Font, and Background Color, 7 Audio converter(espeak), 8 Capture image directly from webcam 9 Fully accessible for person with visually impairment lios-3-2.7.2/lios.spec000066400000000000000000000044501345364566700145000ustar00rootroot00000000000000########################################################################### # Lios - Linux-Intelligent-Ocr-Solution # Copyright (C) 2011-2018 Nalin.x.Linux GPL-3 # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ########################################################################### lios-3-2.7.2/lios/cam.py000066400000000000000000000077011345364566700147400ustar00rootroot00000000000000#!/usr/bin/env python3 ########################################################################### # Lios - Linux-Intelligent-Ocr-Solution # Copyright (C) 2011-2015 Nalin.x.Linux GPL-3 # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ########################################################################### from gi.repository import GdkX11, GstVideo from gi.repository import Gtk from gi.repository import Gst from gi.repository import Gdk from gi.repository import GObject import datetime import os.path class Cam(Gtk.Window): __gsignals__ = { 'image_captured' : (GObject.SIGNAL_RUN_LAST, GObject.TYPE_NONE, (str,)) } def __init__(self,device,x,y,directory="/tmp/"): Gtk.Window.__init__(self,title=_("Press take/close button at the right side")) Gst.init(None) self.resize(x, y) self.connect("destroy",self.cam_close) self.directory = directory box = Gtk.VBox() self.drawingarea = Gtk.DrawingArea() button1 = Gtk.Button(_("Take")) button1.connect("clicked",self.cam_take) button2 = Gtk.Button(_("Close")) button2.connect("clicked",self.cam_close) box.pack_end(self.drawingarea,True,True,0) box.pack_end(button2,False,False,0) box.pack_end(button1,False,False,0) self.add(box) box.show_all() # Create GStreamer pipeline self.pipeline = Gst.Pipeline() # Create bus to get events from GStreamer pipeline self.bus = self.pipeline.get_bus() self.bus.add_signal_watch() self.bus.connect('message::error', self.cam_on_error) # This is needed to make the video output in our DrawingArea: self.bus.enable_sync_message_emission() self.bus.connect('sync-message::element', self.cam_on_sync_message) self.src = Gst.ElementFactory.make('v4l2src', None) self.src.set_property("device", device) self.pipeline.add(self.src) self.sink = Gst.ElementFactory.make('autovideosink', None) self.pipeline.add(self.sink) self.src.link(self.sink) self.drawingarea.set_size_request(x,y) self.drawingarea.realize() self.pipeline.set_state(Gst.State.PLAYING) self.xid = self.drawingarea.get_property('window').get_xid() self.show_all() def start(self): Gtk.main() def cam_close(self, window): self.pipeline.set_state(Gst.State.NULL) self.pipeline.remove(self.src) self.pipeline.remove(self.sink) self.destroy() def cam_take(self,widget): window = self.drawingarea.get_window() x = window.get_width() y = window.get_height() pixbuf = Gdk.pixbuf_get_from_window(window, 0, 0,x, y) filename = "{}{}.png".format(self.directory,datetime.datetime.now().time()) pixbuf.savev(filename, 'png', [], []) self.emit("image_captured",filename) def connect_image_captured(self,function): self.connect("image_captured",function) def cam_on_error(self, bus, msg): print('on_error():', msg.parse_error()) def cam_on_sync_message(self, bus, msg): if msg.get_structure().get_name() == 'prepare-window-handle': msg.src.set_property('force-aspect-ratio', True) msg.src.set_window_handle(self.xid) def get_available_devices(): list = [] for i in range(0,4): device = "/dev/video{}".format(i) if(os.path.exists(device)): list.append(device) return list if __name__ == "__main__": devices = Cam.get_available_devices() print(devices) a = Cam(devices[0],1024,768) a.start() lios-3-2.7.2/lios/capture_screen.py000066400000000000000000000021551345364566700172000ustar00rootroot00000000000000#!/usr/bin/env python3 ########################################################################### # Lios - Linux-Intelligent-Ocr-Solution # Copyright (C) 2014-2015 Nalin.x.Linux GPL-3 # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ########################################################################### import os def capture_entire_screen(filename): os.system("import -window root {} -delay 2".format(filename)) def capture_rectangle_selection(filename): os.system("import {}".format(filename)) lios-3-2.7.2/lios/dictionary.py000066400000000000000000000045771345364566700163550ustar00rootroot00000000000000#!/usr/bin/env python3 ########################################################################### # Lios - Linux-Intelligent-Ocr-Solution # Copyright (C) 2014-2015 Nalin.x.Linux GPL-3 # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ########################################################################### import enchant dictionary_language_dict = {"eng" : "en","afr" : "af","am" : "am", "ara" : "ar","ara" : "ar","aze":"az","bel":"be","bul" : "bg", #Recently added "ben" : "bn","br" : "br","cat" : "ca","ces" : "cs","cy" : "cy", "dan" : "da","ger" : "de","deu":"du","deu-frak":"du","ell":"el", "epo":"eo","eq":"en","eus":"eu-es","frk":"fk","frm":"fr-classical", "grc":"el","ind":"id","isl":"is","ita-old" : "it","jpn":"jn", "kan":"kn","kor":"ko","mkd":"md","mlt":"mt","msa":"ma","nld":"nl", "nor":"no","spa-old":"es","sqi":"si","srp":"sh","swa":"sw","tha":"th", "tur":"tr","vie":"vi","glg" : "gl", "ger" : "de","ell" : "el","eo" : "eo","spa" : "es","est" : "et", "eu" : "eu","fa" : "fa","fin" : "fi","fo" : "fo","fra" : "fr", "ga" : "ga","gl" : "gl","gu" : "gu","heb" : "he","hin" : "hi", "hrv" : "hr","hsb" : "hsb","hun" : "hu","hy" : "hy","id" : "id", "is" : "is","ita" : "it","kk" : "kk","kn" : "kn","ku" : "ku", "lit" : "lt","lav" : "lv","mal" : "ml ","mr" : "mr ","dut" : "nl", "no" : "no","nr" : "nr","ns" : "ns ","or" : "or ","pa" : "pa ", "pol" : "pl ","por" : "pt","por" : "pt","por" : "pt","ron" : "ro", "rus" : "ru ","slk" : "sk","slv" : "sl","ss" : "ss","st" : "st", "swe" : "sv","tam" : "ta","tel" : "te","tl" : "tl","tn" : "tn", "ts" : "ts","ukr" : "uk","uz" : "uz","xh" : "xh","zu" : "zu" } class Dict(enchant.Dict): def __init__(self,language="en"): super(Dict,self).__init__(language) #list_languages() #suggest(word) #check(word) lios-3-2.7.2/lios/editor.py000066400000000000000000000700071345364566700154650ustar00rootroot00000000000000#!/usr/bin/env python3 ########################################################################### # Lios - Linux-Intelligent-Ocr-Solution # Copyright (C) 2011-2015 Nalin.x.Linux GPL-3 # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ########################################################################### from lios.ui.gtk import text_view, tree_view, widget, dialog, file_chooser, containers, window from lios.text_to_audio import text_to_audio_converter from lios import macros from lios import dictionary from lios import localization from lios.ui.gtk import print_dialog import queue import os from encodings.aliases import aliases _ = localization._ def read_text_from_file(filename,enc='utf8'): try: text = open(filename,encoding=enc).read() return text except UnicodeDecodeError: list = sorted(aliases.keys()) combobox = widget.ComboBox() for item in macros.major_character_encodings_list: if(item in list): combobox.add_item(item) for item in list: combobox.add_item(item) combobox.set_active(0) dlg = dialog.Dialog(_("{} Decode error Select Other Character Encoding".format(enc)),(_("Select"), dialog.Dialog.BUTTON_ID_1)) dlg.add_widget_with_label(combobox,_("Character Encoding : ")) combobox.grab_focus() dlg.show_all() response = dlg.run() if response == dialog.Dialog.BUTTON_ID_1: index = combobox.get_active() dlg.destroy() text = read_text_from_file(filename,enc=list[index]) return text else: dlg.destroy() return "" class BasicTextView(text_view.TextView): def __init__(self): super(BasicTextView,self).__init__() self.q = queue.LifoQueue() self.q2 = queue.LifoQueue() self.connect_insert(self.push) self.connect_delete(self.push) self.bookmark_list = [] self.text_cleaner_list = [] #This variable is to avoid the reverse event #while pressing undo or redo that again trigger # insert or delete signals - Nalin.x.GNU self.push_change_to_undobuffer = True; def set_dictionary(self,dict): self.dict = dict def undo(self,arg=None): if( not self.q.empty()): text = self.q.get() self.push_change_to_undobuffer = False self.set_text(text) self.q2.put(text) def redo(self,arg=None): if( not self.q2.empty()): text = self.q2.get() self.push_change_to_undobuffer = False self.set_text(text) self.q.put(text) def push(self): text = self.get_text() if(text and self.push_change_to_undobuffer): self.q.put(text) else: self.push_change_to_undobuffer = True def new(self,*data): if (self.get_modified() == True): dlg = dialog.Dialog(_("Start new without saving ?"), (_("Cancel"), dialog.Dialog.BUTTON_ID_1,_("Start-New!"), dialog.Dialog.BUTTON_ID_2)) label = widget.Label(_("Start new without saving ?")) dlg.add_widget(label) label.show() response = dlg.run() dlg.destroy() if response == dialog.Dialog.BUTTON_ID_1: self.grab_focus(); return 0; else: self.delete_all_text() del self.save_file_name self.bookmark_list = [] self.grab_focus(); return 1; else: self.delete_all_text() del self.save_file_name self.bookmark_list = [] return 1; def open(self): open_file = file_chooser.FileChooserDialog(_("Select the file to open"), file_chooser.FileChooserDialog.OPEN, macros.supported_text_formats,macros.user_home_path) response = open_file.run() if response == file_chooser.FileChooserDialog.ACCEPT: to_open = read_text_from_file(open_file.get_filename()) try: self.set_text(to_open) except FileNotFoundError: pass else: self.save_file_name = open_file.get_filename() self.import_bookmarks_using_filename() #self.textbuffer.place_cursor(self.textbuffer.get_end_iter()) open_file.destroy() def save(self,*data): text = self.get_text() try: self.save_file_name except AttributeError: save_file = file_chooser.FileChooserDialog(_("Save "), file_chooser.FileChooserDialog.SAVE, macros.supported_text_formats,None) save_file.set_current_name(text[0:10]+".text"); save_file.set_do_overwrite_confirmation(True); response = save_file.run() if response == file_chooser.FileChooserDialog.ACCEPT: self.save_file_name = save_file.get_filename() if(self.save_file_name.split(".")[-1] not in macros.supported_text_formats): self.save_file_name = self.save_file_name + ".text" open(self.save_file_name,'w').write(text) self.save_bookmark_table() self.set_modified(False) save_file.destroy() return True else: save_file.destroy() return False else: open(self.save_file_name,'w').write(text) self.save_bookmark_table() self.set_modified(False) return True def save_as(self,*data): try: del self.save_file_name except: pass self.save(); def append(self,*data): append_file_dialog = file_chooser.FileChooserDialog(_("Select the file to append"), file_chooser.FileChooserDialog.OPEN,macros.supported_text_formats) append_file_dialog.set_current_folder("~/") append_file_dialog.run() text_to_append = read_text_from_file(append_file_dialog.get_filename()) self.insert_text(text_to_append,2,True) append_file_dialog.destroy() def punch(self,*data): insert_at_cursor_dialog = file_chooser.FileChooserDialog(_("Select the file to insert at cursor"), file_chooser.FileChooserDialog.OPEN,macros.supported_text_formats) insert_at_cursor_dialog.set_current_folder("~/") insert_at_cursor_dialog.run() text_to_insert_at_cursor = read_text_from_file(insert_at_cursor_dialog.get_filename()) self.insert_text(text_to_insert_at_cursor,1,True) insert_at_cursor_dialog.destroy() def set_text_cleaner_list_from_file(self,filename): self.text_cleaner_list = [] try: with open(filename) as file: for line in file: self.text_cleaner_list.append((line.split("==")[0],line.split("==")[1][:-1])) except: return False return True def save_text_cleaner_list_to_file(self,filename): try: file = open(filename,"w") for item in self.text_cleaner_list: file.write(item[0]+"=="+item[1]+"\n") except: pass def export_text_cleaner_list(self,*data): open_file = file_chooser.FileChooserDialog(_("Filename please"), file_chooser.FileChooserDialog.SAVE, macros.supported_text_formats,macros.user_home_path) open_file.set_current_name(".txt") response = open_file.run() if response == file_chooser.FileChooserDialog.ACCEPT: self.save_text_cleaner_list_to_file(open_file.get_filename()) open_file.destroy() def import_text_cleaner_list(self,*data): open_file = file_chooser.FileChooserDialog(_("Select the file to import"), file_chooser.FileChooserDialog.OPEN, "*",macros.user_home_path) response = open_file.run() if response == file_chooser.FileChooserDialog.ACCEPT: self.set_text_cleaner_list_from_file(open_file.get_filename()) self.save_text_cleaner_list_to_file(macros.local_text_cleaner_list_file_path); open_file.destroy() def open_text_cleaner(self,*data): window_text_cleaner = window.Window(_("Text Cleaner")) scroll_box = containers.ScrollBox() treeview = tree_view.TreeView([(_("Match"),str,True),(_("Replace"),str,True)],None) scroll_box.add(treeview) treeview.set_list(self.text_cleaner_list) def add_clicked(*data): entry_match = widget.Entry() entry_replace = widget.Entry() dlg = dialog.Dialog(_("Give match and replace"),(_("Ok"), dialog.Dialog.BUTTON_ID_1,_("Close!"), dialog.Dialog.BUTTON_ID_2)) dlg.add_widget_with_label(entry_match,_("Match : ")) dlg.add_widget_with_label(entry_replace,_("Replace : ")) entry_match.grab_focus() dlg.show_all() response = dlg.run() if (response == dialog.Dialog.BUTTON_ID_1): treeview.append((entry_match.get_text(),entry_replace.get_text())) self.text_cleaner_list = treeview.get_list() self.save_text_cleaner_list_to_file(macros.local_text_cleaner_list_file_path); dlg.destroy() def remove_clicked(*data): index = treeview.get_selected_row_index() treeview.remove(index) self.text_cleaner_list = treeview.get_list() self.save_text_cleaner_list_to_file(macros.local_text_cleaner_list_file_path); def export_list(*data): self.export_text_cleaner_list() def import_list(*data): self.import_text_cleaner_list() treeview.set_list(self.text_cleaner_list) self.save_text_cleaner_list_to_file(macros.local_text_cleaner_list_file_path); def restore(*data): self.set_text_cleaner_list_from_file(macros.default_text_cleaner_list_file_path) treeview.set_list(self.text_cleaner_list) self.save_text_cleaner_list_to_file(macros.local_text_cleaner_list_file_path); def clear(*data): self.text_cleaner_list = [] treeview.set_list(self.text_cleaner_list) self.save_text_cleaner_list_to_file(macros.local_text_cleaner_list_file_path); def list_updated(*data): self.text_cleaner_list = treeview.get_list() self.save_text_cleaner_list_to_file(macros.local_text_cleaner_list_file_path); def close(*data): window_text_cleaner.close() treeview.connect_update_callback(list_updated) button_add = widget.Button(_("Add")) button_add.connect_function(add_clicked); button_remove = widget.Button(_("Remove")) button_remove.connect_function(remove_clicked) button_import = widget.Button(_("Import")) button_import.connect_function(import_list); button_export = widget.Button(_("Export")) button_export.connect_function(export_list) button_clear = widget.Button(_("Clear")) button_clear.connect_function(clear); button_restore = widget.Button(_("Restore")) button_restore.connect_function(restore) button_apply_from_cursor = widget.Button(_("Apply from cursor")) button_apply_from_cursor.connect_function(self.apply_text_cleaner_from_cursor) button_apply = widget.Button(_("Apply on entire text")) button_apply.connect_function(self.apply_text_cleaner_entire_text) button_close = widget.Button(_("Close")) button_close.connect_function(close) grid = containers.Grid() grid.add_widgets([(scroll_box,3,1),containers.Grid.NEW_ROW, (button_add,1,1,False,False),(button_remove,1,1,False,False),(button_clear,1,1,False,False),containers.Grid.NEW_ROW, (button_restore,1,1,False,False),(button_apply_from_cursor,1,1,False,False),(button_apply,1,1,False,False),containers.Grid.NEW_ROW, (button_import,1,1,False,False),(button_export,1,1,False,False),(button_close,1,1,False,False)]) window_text_cleaner.add(grid); window_text_cleaner.set_default_size(400,500) window_text_cleaner.show_all(); def apply_text_cleaner_from_cursor(self,*data): text = self.get_text_from_cursor_to_end() text = self.get_text_cleaner_out(text) self.delete_text_from_cursor_to_end() self.insert_text(text,text_view.TextView.AT_END) def apply_text_cleaner_entire_text(self,*data): text = self.get_text() text = self.get_text_cleaner_out(text) self.set_text(text) def get_text_cleaner_out(self,text): for item in self.text_cleaner_list: text = text.replace(item[0],item[1]); return text def open_bookmark_table(self,*data): window_bookmark = window.Window(_("Bookmark Table")) list_view = widget.ListView(_("Select the bookmark")) for item in self.bookmark_list: name = item[0] list_view.add_item(name) def jump(*data): index = list_view.get_selected_item_index() self.move_cursor_to_mark(self.bookmark_list[index][1]) self.highlights_cursor_line() window_bookmark.destroy() def scroll_to_position(*data): index = list_view.get_selected_item_index() self.move_cursor_to_mark(self.bookmark_list[index][1]) self.highlights_cursor_line() def delete(*data): index = list_view.get_selected_item_index() self.bookmark_list.pop(index) list_view.remove_selected_item() self.save_bookmark_table("None") def close(*data): window_bookmark.destroy() scroll_box_bookmark = containers.ScrollBox() scroll_box_bookmark.add(list_view) button_jump = widget.Button(_("Jump")) button_jump.connect_function(jump) button_scroll_to_position = widget.Button(_("Scroll Text to position")) button_scroll_to_position.connect_function(scroll_to_position) button_delete = widget.Button(_("Delete")) button_delete.connect_function(delete) button_close = widget.Button(_("Close")) button_close.connect_function(close) list_view.connect_on_select_callback(jump) grid_bookmark = containers.Grid() grid_bookmark.add_widgets([(scroll_box_bookmark,4,1),containers.Grid.NEW_ROW, (button_jump,1,1,False,False),(button_scroll_to_position,1,1,False,False), (button_delete,1,1,False,False),(button_close,1,1,False,False)]) window_bookmark.add(grid_bookmark) window_bookmark.set_default_size(500,200) window_bookmark.show_all() def import_bookmarks_using_filename(self): try: self.bookmark_list = [] name = self.save_file_name name = name.replace("/","|") name = name.replace(" ","#") with open(macros.bookmarks_dir+name) as file: for line in file: mark = self.get_mark_at_line(int(line.split()[0])) name = line.split()[1:] self.bookmark_list.append((" ".join(name),mark)) except: pass def open_all_bookmark_table(self,*data): all_bookmark_list = [] window_bookmark = window.Window(_("Bookmark Table")) list_view = widget.ListView(_("Select the bookmark")) for bookmark_file in os.listdir(macros.bookmarks_dir): with open(macros.bookmarks_dir+bookmark_file) as file: for line in file: all_bookmark_list.append(bookmark_file+"~"+line) list_view.add_item(bookmark_file.split("|")[-1]+" : "+line) def jump(*data): index = list_view.get_selected_item_index() item = all_bookmark_list[index] filename = item.split("~")[0].replace("|","/").replace("#"," ") line_number = item.split("~")[1].split()[0] text = open(filename).read() self.set_text(text) self.save_file_name = filename self.import_bookmarks_using_filename() mark = self.get_mark_at_line(int(line_number)) self.move_cursor_to_mark(mark) self.highlights_cursor_line() window_bookmark.destroy() def close(*data): window_bookmark.destroy() scroll_box_bookmark = containers.ScrollBox() scroll_box_bookmark.add(list_view) button_jump = widget.Button(_("Jump")) button_jump.connect_function(jump) button_close = widget.Button(_("Close")) button_close.connect_function(close) list_view.connect_on_select_callback(jump) grid_bookmark = containers.Grid() grid_bookmark.add_widgets([(scroll_box_bookmark,2,1),containers.Grid.NEW_ROW, (button_jump,1,1,False,False),(button_close,1,1,False,False)]) window_bookmark.add(grid_bookmark) window_bookmark.set_default_size(500,200) window_bookmark.show_all() def save_bookmark_table(self,*data): #name = re.sub('[^.-/#0-9a-zA-Z]+', '#', self.save_file_name) name = self.save_file_name name = name.replace("/","|") name = name.replace(" ","#") file = open(macros.bookmarks_dir+name,"w+") for item in self.bookmark_list: line_number = self.get_line_number_of_mark(item[1]) file.write("{0} {1} \n".format(line_number,item[0])) file.close() def import_bookmarks_from_file(self,*data): open_file = file_chooser.FileChooserDialog(_("Select the bookmark file to import"), file_chooser.FileChooserDialog.OPEN, macros.supported_text_formats,macros.user_home_path) response = open_file.run() if response == file_chooser.FileChooserDialog.ACCEPT: with open(open_file.get_filename()) as file: for line in file: mark = self.get_mark_at_line(int(line.split()[0])) name = line.split()[1:] self.bookmark_list.append((" ".join(name),mark)) open_file.destroy() def create_bookmark(self,*data): try: self.save_file_name except: dlg = dialog.Dialog(_("Warning!"),(_("Close!"), dialog.Dialog.BUTTON_ID_2)) label = widget.Label(_("File must be saved inorder to bookmark the text!")) dlg.add_widget(label) dlg.show_all() response = dlg.run() dlg.destroy() return entry_sentence = widget.Entry() text = self.get_current_line_text() entry_sentence.set_text(text) dlg = dialog.Dialog(_("Create new Bookmark"),(_("Bookmark"), dialog.Dialog.BUTTON_ID_1,_("Close!"), dialog.Dialog.BUTTON_ID_2)) dlg.add_widget_with_label(entry_sentence,_("Name : ")) entry_sentence.grab_focus() dlg.show_all() response = dlg.run() if response == dialog.Dialog.BUTTON_ID_1: # Note that this ### string will be deleted automatically # Because it's considered as line number sentence = entry_sentence.get_text() # Note that this mark can't be used directly # Because it will always hold cursor position mark = self.get_cursor_mark() line_number = self.get_line_number_of_mark(mark) real_mark = self.get_mark_at_line(line_number) self.bookmark_list.append((sentence,real_mark)) self.save_bookmark_table("None") dlg.destroy() else: dlg.destroy() def open_find_dialog(self,*data): entry = widget.Entry() statusbar_context = widget.Statusbar() statusbar_context.set_text(_("Context label")) def find_next(*data): word = entry.get_text() if(not self.is_cursor_at_end()): if(self.move_forward_to_word(word)): statusbar_context.set_text(self.get_context_text()) def find_previous(*data): word = entry.get_text() if(not self.is_cursor_at_start()): if(self.move_backward_to_word(word)): statusbar_context.set_text(self.get_context_text()) label = widget.Label(_(" Find word : ")) label.set_use_markup(True) label.set_mnemonic_widget(entry) entry.connect_activate_function(find_next) next_button = widget.Button(_("Next")) next_button.connect_function(find_next) previous_button = widget.Button(_("Previous")) previous_button.connect_function(find_previous) grid = containers.Grid() grid.add_widgets([(label,1,1),(entry,1,1),containers.Grid.NEW_ROW, (statusbar_context,2,1),containers.Grid.NEW_ROW,(next_button,1,1,False,False), (previous_button,1,1,False,False)]) window_find = window.Window(_("Find Dialog")) window_find.add(grid) window_find.show_all() def open_find_and_replace_dialog(self,*data): entry_word = widget.Entry() entry_replace_word = widget.Entry() statusbar_context = widget.Statusbar() statusbar_context.set_text(_("Context label")) def find_next(*data): word = entry_word.get_text() if(not self.is_cursor_at_end()): if(self.move_forward_to_word(word)): statusbar_context.set_text(self.get_context_text()) def find_previous(*data): word = entry_word.get_text() if(not self.is_cursor_at_start()): if(self.move_backward_to_word(word)): statusbar_context.set_text(self.get_context_text()) else: dialog.Dialog(_("No match found")).run() def replace(*data): word_replace = entry_replace_word.get_text() self.replace_last_word(word_replace) def replace_all(*data): word = entry_word.get_text() word_replace = entry_replace_word.get_text() while(not self.is_cursor_at_end()): if(self.move_forward_to_word(word)): self.replace_last_word(word_replace) else: break label_word = widget.Label(_(" Word: ")) label_word.set_use_markup(True) label_word.set_mnemonic_widget(entry_word) label_replace_word = widget.Label(_(" Replace word: ")) label_replace_word.set_use_markup(True) label_replace_word.set_mnemonic_widget(entry_replace_word) entry_word.connect_activate_function(find_next) entry_replace_word.connect_activate_function(find_next) button_next = widget.Button(_("Next")) button_next.connect_function(find_next) button_previous = widget.Button(_("Previous")) button_previous.connect_function(find_previous) button_replace = widget.Button(_("Replace")) button_replace.connect_function(replace) button_replace_all = widget.Button(_("Replace All")) button_replace_all.connect_function(replace_all) grid = containers.Grid() grid.add_widgets([(label_word,2,1),(entry_word,4,1),containers.Grid.NEW_ROW, (label_replace_word,2,1),(entry_replace_word,4,1),containers.Grid.NEW_ROW, (button_next,3,1,False,False),(button_previous,3,1,False,False), containers.Grid.NEW_ROW,(statusbar_context,6,1),containers.Grid.NEW_ROW, (button_replace,3,1,False,False),(button_replace_all,3,1,False,False)]) window_find = window.Window(_("Find Dialog")) window_find.add(grid) window_find.show_all() def open_spell_check(self,*data): entry = widget.Entry() list_view = widget.ListView(_("Suggestions")) statusbar_context = widget.Statusbar() statusbar_context.set_text(_("Context label")) statusbar_context.set_line_wrap(True) change_all_dict = {} self.word = "" def find_next_mispeleed_word(*data): while (not self.is_cursor_at_end()): self.word = self.get_next_word() if self.word in change_all_dict.keys(): self.replace_last_word(change_all_dict[self.word]) continue if (not self.dict.check(self.word)): entry.set_text(self.word) statusbar_context.set_text(self.get_context_text()) list_view.clear() for item in self.dict.suggest(self.word): list_view.add_item(item) break if(self.is_cursor_at_end()): entry.set_text("") statusbar_context.set_text(_("Spell Check finished")) def ignore_all(*data): word = entry.get_text() self.dict.add_to_session(word) find_next_mispeleed_word() def change(*data): replace_word = entry.get_text() self.replace_last_word(replace_word) find_next_mispeleed_word() def change_all(*data): replace_word = entry.get_text() change_all_dict[self.word] = replace_word self.replace_last_word(replace_word) find_next_mispeleed_word() def delete(*data): self.delete_last_word() find_next_mispeleed_word() def on_suggestion_selected(*data): item = list_view.get_selected_item() entry.set_text(item) def close(*data): window1.destroy() grid = containers.Grid() label = widget.Label(_(" Misspelled word : ")) label.set_use_markup(True) label.set_mnemonic_widget(entry) scroll_box = containers.ScrollBox() scroll_box.add(list_view) change_button = widget.Button(_("Change")) change_button.connect_function(change) change_all_button = widget.Button(_("Change All")) change_all_button.connect_function(change_all) delete_button = widget.Button(_("Delete")) delete_button.connect_function(delete) ignore_button = widget.Button(_("Ignore")) ignore_button.connect_function(find_next_mispeleed_word) ignore_all_button = widget.Button(_("Ignore All")) ignore_all_button.connect_function(ignore_all) add_to_dict_button = widget.Button(_("Add to user dict")) close_button = widget.Button(_("Close")) close_button.connect_function(close) list_view.connect_on_select_callback(on_suggestion_selected) entry.connect_activate_function(change) grid.add_widgets([(label,1,1,False,False), (entry,6,1,False,False),containers.Grid.NEW_ROW, (scroll_box,1,3,False,False),(change_button,1,1,False,False),(change_all_button,1,1,False,False),(delete_button,1,1,False,False),containers.Grid.NEW_ROW, (ignore_button,1,1,False,False),(ignore_all_button,1,1,False,False),(add_to_dict_button,1,1,False,False),containers.Grid.NEW_ROW, (statusbar_context,1,1),containers.Grid.NEW_ROW, (close_button,4,1,False,False)]) find_next_mispeleed_word() window1 = window.Window(_("Spell-Check")) window1.add(grid) window1.set_default_size(500,200) window1.show_all() def go_to_line(self,*data): current_line = self.get_cursor_line_number() maximum_line = self.get_line_count() spinbutton_line = widget.SpinButton(current_line,0,maximum_line,1,5,0) dlg = dialog.Dialog(_("Go to line"),(_("Go"), dialog.Dialog.BUTTON_ID_1,_("Close!"), dialog.Dialog.BUTTON_ID_2)) #spinbutton_line.connect("activate",lambda x : dialog.response(Gtk.ResponseType.ACCEPT)) dlg.add_widget_with_label(spinbutton_line,_("Line Number : ")) spinbutton_line.grab_focus() dlg.show_all() response = dlg.run() if response == dialog.Dialog.BUTTON_ID_1: to = spinbutton_line.get_value() self.move_cursor_to_line(to) self.highlights_cursor_line() dlg.destroy() else: dlg.destroy() def audio_converter(self,data=None,voice=None): if (self.has_selection()): text = self.get_selected_text() else: text = self.get_text() dialog_ac = dialog.Dialog(_("Audio converter "),(_("Convert"), dialog.Dialog.BUTTON_ID_1,_("Close!"), dialog.Dialog.BUTTON_ID_2)) grid = containers.Grid() spinbutton_speed = widget.SpinButton(50,0,100,1,5,0) label_speed = widget.Label(_("Speed : ")) label_speed.set_mnemonic_widget(spinbutton_speed) spinbutton_volume = widget.SpinButton(100,0,100,1,5,0) label_volume = widget.Label(_("Volume : ")) label_volume.set_mnemonic_widget(spinbutton_volume) spinbutton_pitch = widget.SpinButton(50,0,100,1,5,0) label_pitch = widget.Label(_("Pitch : ")) label_pitch.set_mnemonic_widget(spinbutton_pitch) spinbutton_split = widget.SpinButton(5,0,100,1,5,0) label_split_time = widget.Label(_("Split Time : ")) label_split_time.set_mnemonic_widget(spinbutton_split) combobox = widget.ComboBox() for item in text_to_audio_converter.list_voices(): combobox.append_text(item) if voice is not None: combobox.set_active(voice) label_voice = widget.Label(_("Voice : ")) label_voice.set_mnemonic_widget(combobox) combobox_format = widget.ComboBox() combobox_format.append_text(_("MP3 (liblame required)")) combobox_format.append_text(_("WAV")) combobox_format.set_active(0) label_format = widget.Label(_("Format : ")) label_format.set_mnemonic_widget(combobox_format) grid.add_widgets([ (label_speed,1,1),(spinbutton_speed,1,1),containers.Grid.NEW_ROW, (label_volume,1,1),(spinbutton_volume,1,1),containers.Grid.NEW_ROW, (label_pitch,1,1),(spinbutton_pitch,1,1),containers.Grid.NEW_ROW, (label_split_time,1,1),(spinbutton_split,1,1),containers.Grid.NEW_ROW, (label_voice,1,1),(combobox,1,1),containers.Grid.NEW_ROW, (label_format,1,1),(combobox_format,1,1)]) dialog_ac.add_widget(grid) grid.show_all() if (dialog_ac.run() == dialog.Dialog.BUTTON_ID_1): speed = spinbutton_speed.get_value() pitch = spinbutton_pitch.get_value() volume = spinbutton_volume.get_value() split = spinbutton_split.get_value() voice = combobox.get_active_text() output_format = combobox_format.get_active() save_file = file_chooser.FileChooserDialog(_("Save"),file_chooser.FileChooserDialog.SAVE,["wav","mp3"],macros.user_home_path) response = save_file.run() if response == file_chooser.FileChooserDialog.ACCEPT: converter = text_to_audio_converter(text,volume,voice,split,pitch,speed) if (output_format == 0 ): converter.record_to_mp3(save_file.get_filename()) else: converter.record_to_wave(save_file.get_filename()) save_file.destroy() dialog_ac.destroy() def print_preview(self,*data): if (self.has_selection()): text = self.get_selected_text() else: text = self.get_text() print_dialog.print_with_action(text,print_dialog.print_with_action.PREVIEW) def open_print_dialog(self,*data): if (self.has_selection()): text = self.get_selected_text() else: text = self.get_text() print_dialog.print_with_action(text,print_dialog.print_with_action.PRINT_DIALOG) def print_to_pdf(self,*data): save_file = file_chooser.FileChooserDialog(_("Enter the file name"), file_chooser.FileChooserDialog.SAVE,macros.supported_pdf_formats,macros.user_home_path) response = save_file.run() if response == file_chooser.FileChooserDialog.ACCEPT: if (self.has_selection()): text = self.get_selected_text() else: text = self.get_text() print_dialog.print_with_action(text,print_dialog.print_with_action.EXPORT, save_file.get_filename()) save_file.destroy() lios-3-2.7.2/lios/image_logics.py000077500000000000000000000137401345364566700166250ustar00rootroot00000000000000#!/usr/bin/python3 ########################################################################### # Lios - Linux-Intelligent-Ocr-Solution # Copyright (C) 2015-2016 Nalin.x.Linux GPL-3 # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ########################################################################### def detect_overlap(list,new_start_x,new_start_y,new_end_x,new_end_y): for item in list: start_x = item[0] start_y = item[1] finish_x = item[2]+item[0] finish_y = item[3]+item[1] if (((start_x <= new_start_x <= finish_x or start_x <= new_end_x <= finish_x) and (start_y <= new_start_y <= finish_y or start_y <= new_end_y <= finish_y)) or # The rectangle maybe inside the new rectangle ((new_start_x <= start_x <= new_end_x and new_start_y <= start_y <= new_end_y) or ( new_start_x <= finish_x <= new_end_x and new_start_y <= finish_y <= new_end_y))): return (start_x,start_y,finish_x,finish_y) return False def detect_out_of_range(x,y,max_width,max_height): if (x >= max_width or y >= max_height or x <= 0 or y<=0 ): return True else: return False def order_rectangle(start_x,start_y,finish_x,finish_y): #Swap coordinate if selected in reverse direction if(start_x >= finish_x): start_x,finish_x = finish_x,start_x if(start_y >= finish_y): start_y,finish_y = finish_y,start_y return start_x,start_y,finish_x,finish_y def is_overlapping(rs,index,a,b,c,d): nrs = []; for i in range(0,len(rs)): if(index != i): nrs.append(rs[i]); if(detect_overlap(nrs,a,b,a+c,b+d)): return True else: return False def get_point_type(x,y,area_x_start, area_y_start,width,height,rs): # If pointer is at the edge of drawing area then mouse pointer must become normal if (x < area_x_start+10 or (area_x_start+width-20) <= x <= area_x_start+width or y < area_y_start+10 or (area_y_start+height-20) <= y <= area_y_start+height): return (1,-1,0) for i in range(0,len(rs)): scope_scale_y = (rs[i][3])/10 scope_scale_x = (rs[i][2])/10 #Left if(rs[i][0] <= x+scope_scale_x and rs[i][0] >= x-scope_scale_x and rs[i][1] <= y and rs[i][3]+rs[i][1] >= y ): return (2,i,4) #Right if(rs[i][0]+rs[i][2] <= x+scope_scale_x and rs[i][0]+rs[i][2] >= x-scope_scale_x and rs[i][1] <= y and rs[i][3]+rs[i][1] >= y ): return (2,i,6) #Top if(rs[i][1] <= y+scope_scale_y and rs[i][1] >= y-scope_scale_y and rs[i][0] <= x and rs[i][2]+rs[i][0] >= x ): return (2,i,2) #Bottom if(rs[i][3]+rs[i][1] <= y+scope_scale_y and rs[i][3]+rs[i][1] >= y-scope_scale_y and rs[i][0] <= x and rs[i][2]+rs[i][0] >= x ): return (2,i,8) #Top Left if(rs[i][0] <= x+scope_scale_x and rs[i][0] >= x-scope_scale_x and rs[i][1] <= y+scope_scale_y and rs[i][1] >= y-scope_scale_y ): return (2,i,1) #Bottom Left if(rs[i][0] <= x+scope_scale_x and rs[i][0] >= x-scope_scale_x and rs[i][3]+rs[i][1] <= y+scope_scale_y and rs[i][3]+rs[i][1] >= y-scope_scale_y): return (2,i,7) #Top Right if(rs[i][0]+rs[i][2] <= x+scope_scale_x and rs[i][0]+rs[i][2] >= x-scope_scale_x and rs[i][1] <= y+scope_scale_y and rs[i][1] >= y-scope_scale_y ): return (2,i,3) #Bottom Right if(rs[i][0]+rs[i][2] <= x+scope_scale_x and rs[i][0]+rs[i][2] >= x-scope_scale_x and rs[i][3]+rs[i][1] <= y+scope_scale_y and rs[i][3]+rs[i][1] >= y-scope_scale_y): return (2,i,9) #Moving if(x >= rs[i][0]+scope_scale_x and y >= rs[i][1]+scope_scale_y and x <= rs[i][0]+rs[i][2]-scope_scale_x and y <= rs[i][1]+rs[i][3]-scope_scale_y): return (3,i,5) return (1,-1,0) # Used to find the index of new box inside the box list # The box list is arranged in top-left to bottom-right order def find_index_for_new_box(new_s_x,new_s_y,new_e_x,new_e_y,rl): length = len(rl); index = length-1; min_x_dist = 99999; min_y_dist = 99999; for i in range (0,length): cur_s_x = rl[i][0] cur_s_y = rl[i][1] cur_e_x = cur_s_x+rl[i][2] cur_e_y = cur_s_y+rl[i][3] # Checking it's on the right side or not if(cur_s_x < new_s_x): # Checking new top and new bottom are inside the current one's y axis if(cur_s_y <= new_s_y <= cur_e_y or new_s_y <= cur_s_y <= new_e_y or cur_s_y <= new_e_y <= cur_e_y or new_s_y <= cur_e_y <= new_e_y): dist = new_s_x - cur_s_x; # The new box is residing on right side so # if cur box having minimum x distance to new then it's more close if ( dist < min_x_dist): min_x_dist = dist; index = i+1; #if nothing in parallel to the right then new box will be drawed in first from left if (min_x_dist == 99999): if(cur_e_y <= new_s_y): # Checking the vertical distance bitween new box and cur box # if it's very low then find the right most parallel one dist1 = new_s_y - cur_s_y; dist2 = new_s_y - cur_e_y; dist = (dist1+dist2)/2; if (dist < min_y_dist): min_y_dist = dist # Checking if any box in parallel to right side j = i+1; index = i+1; #cur_e_y >= rl[j][1] is used to skip symbols like single quotes while(j < length and cur_s_x < rl[j][0] and (cur_s_y <= rl[j][1] <= cur_e_y or rl[j][1] <= cur_s_y <= (rl[j][1]+rl[j][3]) or cur_s_y <= (rl[j][1]+rl[j][3]) <= cur_e_y or rl[j][1] <= cur_e_y <= (rl[j][1]+rl[j][3]) or cur_e_y >= rl[j][1] )): j = j + 1; index = j; # Stop if end reached if(j == length): break; return index; lios-3-2.7.2/lios/imageview.py000077500000000000000000000507051345364566700161620ustar00rootroot00000000000000#!/usr/bin/python3 ########################################################################### # Lios - Linux-Intelligent-Ocr-Solution # Copyright (C) 2015-2016 Nalin.x.Linux GPL-3 # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ########################################################################### from gi.repository import GObject from lios.ui.gtk import loop, dialog, widget, drawing_area, tree_view, containers, window from lios import image_logics, localization _ = localization._ class ImageViewer(containers.Paned): ZOOM_FIT = 4 __gsignals__ = { 'list_updated' : (GObject.SIGNAL_RUN_LAST, GObject.TYPE_NONE, ()) } def __init__(self): super(ImageViewer,self).__init__(containers.Paned.HORIZONTAL) self.set_border_width(5) #Drawing Area self.drawingarea = drawing_area.DrawingArea() self.scrolled = containers.ScrollBox() self.scrolled.add_with_viewport(self.drawingarea); self.drawingarea.connect_button_press_event(self.__drawingarea_button_press_event) self.drawingarea.connect_button_release_event(self.__drawingarea_button_release_event) self.drawingarea.connect_motion_notify_event(self.__drawingarea_motion_notify_event) self.add(self.scrolled) #Drawing List Tree View self.treeview = tree_view.TreeView([(_("Selected"),bool,False), (_("X"),float,True),(_("Y"),float,True), (_("Width"),float,True),(_("Height"),float,True), (_("Letter"),str,True)],self.edited_callback) self.treeview.connect_cursor_change_function(self.treeview_cursor_changed) self.treeview.connect_rows_reordered_function(self.treeview_rows_reordered) self.treeview.set_column_visible(0,False); self.treeview.set_reorderable(True) scrolled_treeview = containers.ScrollBox() scrolled_treeview.add(self.treeview) self.rs = [] self.start_row_index = -1 self.previus_row_index = -1 button1 = widget.Button(_("_Delete")) button1.set_use_underline(True) button1.set_tooltip_text(_("Shortcut Alt+D")) button1.connect_function(self.__delete_selection) button2 = widget.Button(_("Clear")) button2.connect_function(self.clear_selection) grid = containers.Grid() grid.add_widgets([(scrolled_treeview,2,1,containers.Grid.HEXPAND,containers.Grid.VEXPAND), containers.Grid.NEW_ROW,(button1,1,1,containers.Grid.HEXPAND,containers.Grid.NO_VEXPAND), (button2,1,1,containers.Grid.HEXPAND,containers.Grid.NO_VEXPAND)]) self.add(grid) #Inetial Values self.on_select = False self.on_resize = False self.zoom_list = [0.20,0.40,0.60,0.80,1,1.20,1.40,1.60,1.80,2] self.zoom_level = self.ZOOM_FIT self.drawingarea.show() self.set_position(400) self.show() #set_position() def scroll_image_view(self,h_value,v_value): self.scrolled.scroll(h_value,v_value) def get_image_view_size_on_screen(self): return self.scrolled.get_size_on_screen() def get_image_view_scrolled_start_points(self): return self.scrolled.get_current_start_points() def edited_callback(self,row): # Reset the new rectangle list rs = self.treeview.get_list() if(not image_logics.is_overlapping( [ [row[1],row[2],row[3],row[4] ] for row in self.rs ], row,rs[row][1],rs[row][2],rs[row][3],rs[row][4])): self.rs = rs; #applay new rectangle list on drawing area self.drawingarea.set_rectangle_list([[ row[0], row[1],row[2],row[3],row[4] ] for row in self.rs ]) self.drawingarea.redraw() self.emit('list_updated') else: self.treeview.set_list(self.rs) def treeview_cursor_changed(self): selected_row = self.treeview.get_selected_row_index() self.set_selected_item(selected_row) self.drawingarea.set_rectangle_list([[ row[0],row[1],row[2],row[3],row[4] ] for row in self.rs ]) self.drawingarea.redraw() #Scroll image view to new position width,height = self.get_image_view_size_on_screen() cur_rec_x = self.rs[selected_row][1]#+self.rs[selected_row][3] cur_rec_y = self.rs[selected_row][2]#+self.rs[selected_row][4] x = (cur_rec_x - (width*50/100)); y = (cur_rec_y - (height*50/100)); self.scroll_image_view(x,y); # Note : The set list function should not again - # trigger cursor-change function #self.treeview.set_list(self.rs) def treeview_rows_reordered(self): self.rs = self.treeview.get_list() self.drawingarea.set_rectangle_list([[ row[0],row[1],row[2],row[3],row[4] ] for row in self.rs ]) self.emit('list_updated') def load_image(self,filename,list,zoom_level): if(0 <= zoom_level <= 9): self.start_type = 0; self.filename = filename self.old_zoom_level = self.zoom_level diff = self.zoom_level - zoom_level self.zoom_level = zoom_level parameter = self.zoom_list[self.zoom_level] self.set_list(list,diff) self.drawingarea.load_image(filename,list,parameter); def set_list(self,list_,diff): if (list_ == None): old_factor = self.old_zoom_level - 4 new_factor = self.zoom_level - 4 list_ = [] # Here we have to revert to the original because we always # zoom in/out on the original image with factors to keep the quality # ie zoom the image from original instead of zooming the zoomed image for item in self.rs: x_orig = item[1]*100/((old_factor*20)+100) x = x_orig+((x_orig*20*new_factor)/100) y_orig = item[2]*100/((old_factor*20)+100) y = y_orig+((y_orig*20*new_factor)/100) width_orig = item[3]*100/((old_factor*20)+100) width = width_orig+((width_orig*20*new_factor)/100) height_orig = item[4]*100/((old_factor*20)+100) height = height_orig+((height_orig*20*new_factor)/100) list_.append([0,x,y,width,height,item[5]]) self.rs = list(list(x) for x in list_) self.treeview.set_list(self.rs) self.drawingarea.set_rectangle_list([[ row[0],row[1],row[2],row[3],row[4] ] for row in self.rs ]) self.drawingarea.redraw() def get_list(self): old_factor = self.zoom_level - 4 list_ = [] # Here we have to return the original because we always # zoom in/out on the original image with factors to keep the quality # ie zoom the image from original instead of zooming the zoomed image for item in self.rs: x_orig = item[1]*100/((old_factor*20)+100) y_orig = item[2]*100/((old_factor*20)+100) width_orig = item[3]*100/((old_factor*20)+100) height_orig = item[4]*100/((old_factor*20)+100) list_.append([0,x_orig,y_orig,width_orig,height_orig,item[5]]) return list(list(x) for x in list_) def get_height(self): return self.drawingarea.get_height(); def get_original_height(self): return self.drawingarea.get_original_height() def get_filename(self): return self.filename def set_label_entry_visible(self,value): self.treeview.set_column_visible(5,False); def redraw(self): loop.acquire_lock() self.load_image(self.filename,[],self.ZOOM_FIT) loop.release_lock() def get_selection_list(self): # return with the pattern x, y , width, height, letter return([[ row[1],row[2],row[3],row[4], row[5] ] for row in self.rs ]) # inorder to maintain the qulity the sub-image should be created from # original image so the rectangle coordinates should be in original points def save_sub_image(self,filename,x,y,width,height): factor = self.zoom_level - 4 x = x*100/((factor*20)+100) y = y*100/((factor*20)+100) width = width*100/((factor*20)+100) height = height*100/((factor*20)+100) self.drawingarea.save_image_rectangle(filename,x,y,width,height) def get_pixbuf(self): return self.pixbuf def zoom_in(self,data=None): self.load_image(self.filename,None, self.zoom_level + 1) self.treeview.set_list(self.rs) self.drawingarea.set_rectangle_list([[ row[0],row[1],row[2],row[3],row[4] ] for row in self.rs ]) self.emit('list_updated') def zoom_out(self,data=None): self.load_image(self.filename,None, self.zoom_level - 1) self.treeview.set_list(self.rs) self.drawingarea.set_rectangle_list([[ row[0],row[1],row[2],row[3],row[4] ] for row in self.rs ]) self.emit('list_updated') def zoom_fit(self,data=None): self.load_image(self.filename,None,self.ZOOM_FIT) self.drawingarea.set_rectangle_list([[ row[0],row[1],row[2],row[3],row[4] ] for row in self.rs ]) self.emit('list_updated') def get_zoom_level(self): return self.zoom_level def __drawingarea_button_press_event(self, point, button_type): if(button_type == 1): self.start_x,self.start_y=point width,height = self.get_image_view_size_on_screen() area_x_start, area_y_start = self.get_image_view_scrolled_start_points() self.start_type, self.start_row_index, self.start_position_type = image_logics.get_point_type(self.start_x,self.start_y, area_x_start, area_y_start, width, height,[ [row[1],row[2],row[3],row[4],row[0] ] for row in self.rs ]) return True def __drawingarea_motion_notify_event(self, point): x,y = point; max_width = self.drawingarea.get_width() max_height = self.drawingarea.get_height() # 1 - Select if (self.start_type == 1): if(image_logics.detect_out_of_range(x,y,max_width,max_height)): return start_x,start_y,end_x,end_y = image_logics.order_rectangle(self.start_x,self.start_y,x,y); if(image_logics.detect_overlap([ [row[1],row[2],row[3],row[4] ] for row in self.rs ],start_x,start_y,end_x,end_y)): return self.tmp_finish_x,self.tmp_finish_y = point self.drawingarea.set_drawing_rectangle((self.start_x,self.start_y, self.tmp_finish_x-self.start_x,self.tmp_finish_y-self.start_y)) self.drawingarea.redraw() # 2 - Resize if (self.start_type == 2): if(image_logics.detect_out_of_range(x,y,max_width,max_height)): return if(self.start_position_type == 1): if( not image_logics.is_overlapping([ [row[1],row[2],row[3],row[4] ] for row in self.rs ],self.start_row_index, x,y,self.rs[self.start_row_index][3]+(self.rs[self.start_row_index][1] - x), self.rs[self.start_row_index][4]+(self.rs[self.start_row_index][2] - y))): self.rs[self.start_row_index][4] = self.rs[self.start_row_index][4]+(self.rs[self.start_row_index][2] - y) self.rs[self.start_row_index][2] = y self.rs[self.start_row_index][3] = self.rs[self.start_row_index][3]+(self.rs[self.start_row_index][1] - x) self.rs[self.start_row_index][1] = x elif(self.start_position_type == 2): if( not image_logics.is_overlapping([ [row[1],row[2],row[3],row[4] ] for row in self.rs ],self.start_row_index, self.rs[self.start_row_index][1],y,self.rs[self.start_row_index][3],y+self.rs[self.start_row_index][4] -y)): self.rs[self.start_row_index][4] = self.rs[self.start_row_index][4]+(self.rs[self.start_row_index][2] - y) self.rs[self.start_row_index][2] = y elif(self.start_position_type == 3): if(not image_logics.is_overlapping([ [row[1],row[2],row[3],row[4] ] for row in self.rs ],self.start_row_index, self.rs[self.start_row_index][1],y, x - self.rs[self.start_row_index][1], self.rs[self.start_row_index][4]+(self.rs[self.start_row_index][2] - y))): self.rs[self.start_row_index][4] = self.rs[self.start_row_index][4]+(self.rs[self.start_row_index][2] - y) self.rs[self.start_row_index][2] = y self.rs[self.start_row_index][3] = x - self.rs[self.start_row_index][1] elif(self.start_position_type == 4): if( not image_logics.is_overlapping([ [row[1],row[2],row[3],row[4] ] for row in self.rs ],self.start_row_index, x,self.rs[self.start_row_index][2], self.rs[self.start_row_index][3]+(self.rs[self.start_row_index][1] - x), self.rs[self.start_row_index][4])): self.rs[self.start_row_index][3] = self.rs[self.start_row_index][3]+(self.rs[self.start_row_index][1] - x) self.rs[self.start_row_index][1] = x elif(self.start_position_type == 6): if( not image_logics.is_overlapping([ [row[1],row[2],row[3],row[4] ] for row in self.rs ],self.start_row_index, self.rs[self.start_row_index][1],self.rs[self.start_row_index][2], x - self.rs[self.start_row_index][1],self.rs[self.start_row_index][4])): self.rs[self.start_row_index][3] = x - self.rs[self.start_row_index][1] elif(self.start_position_type == 7): if( not image_logics.is_overlapping([ [row[1],row[2],row[3],row[4] ] for row in self.rs ],self.start_row_index, x,self.rs[self.start_row_index][2], self.rs[self.start_row_index][3]+(self.rs[self.start_row_index][1] - x), y - self.rs[self.start_row_index][2])): self.rs[self.start_row_index][4] = y - self.rs[self.start_row_index][2] self.rs[self.start_row_index][3] = self.rs[self.start_row_index][3]+(self.rs[self.start_row_index][1] - x) self.rs[self.start_row_index][1] = x elif(self.start_position_type == 8): if( not image_logics.is_overlapping([ [row[1],row[2],row[3],row[4] ] for row in self.rs ],self.start_row_index, self.rs[self.start_row_index][1],self.rs[self.start_row_index][2], self.rs[self.start_row_index][3],y - self.rs[self.start_row_index][2])): self.rs[self.start_row_index][4] = y - self.rs[self.start_row_index][2] elif(self.start_position_type == 9): if( not image_logics.is_overlapping([ [row[1],row[2],row[3],row[4] ] for row in self.rs ],self.start_row_index, self.rs[self.start_row_index][1],self.rs[self.start_row_index][2], x - self.rs[self.start_row_index][1],y - self.rs[self.start_row_index][2])): self.rs[self.start_row_index][4] = y - self.rs[self.start_row_index][2] self.rs[self.start_row_index][3] = x - self.rs[self.start_row_index][1] self.treeview.set_list(self.rs) self.drawingarea.set_rectangle_list([[ row[0],row[1],row[2],row[3],row[4] ] for row in self.rs ]) # 3 - Moving if (self.start_type == 3): #Detect if anyof the new rectangle porsion is not feesible if(image_logics.detect_out_of_range(x - self.rs[self.start_row_index][3]/2,y - self.rs[self.start_row_index][4]/2,max_width,max_height) or image_logics.detect_out_of_range(x + self.rs[self.start_row_index][3]/2,y + self.rs[self.start_row_index][4]/2,max_width,max_height)): return if(image_logics.is_overlapping([ [row[1],row[2],row[3],row[4] ] for row in self.rs ],self.start_row_index,x - self.rs[self.start_row_index][3]/2, y - self.rs[self.start_row_index][4]/2,self.rs[self.start_row_index][3],self.rs[self.start_row_index][4])): return self.rs[self.start_row_index][1] = x - self.rs[self.start_row_index][3]/2; self.rs[self.start_row_index][2] = y - self.rs[self.start_row_index][4]/2; self.treeview.set_list(self.rs) self.drawingarea.set_rectangle_list([[ row[0],row[1],row[2],row[3],row[4] ] for row in self.rs ]) # 0 - Simply hovering if (self.start_type == 0): area_x_start, area_y_start = self.get_image_view_scrolled_start_points() width,height = self.get_image_view_size_on_screen() _type, row_index, position_type = image_logics.get_point_type(x,y,area_x_start, area_y_start, width, height,[[row[1],row[2],row[3],row[4] ] for row in self.rs ]) self.drawingarea.set_mouse_pointer_type(position_type); # if self.previus_row_index not equll to row_index then the # mouse pointer moved from current box so we draw it if (self.previus_row_index != row_index): # While hovering over boxes the treeview cursor change handler function should not be called # because it simply scroll drawing area for each boxes which leads to flicker self.treeview.block_cursor_change_signal() if ( row_index != -1 ): # The mouse is over the box at row_index self.set_selected_item(row_index) self.treeview.set_list(self.rs); self.drawingarea.set_rectangle_list([[ row[0],row[0],row[1],row[2],row[3] ] for row in self.rs ]) self.treeview.set_cursor(row_index) elif( self.start_row_index != -1 ): # If user made a selection then it should be preserved even after hovering other boxes self.set_selected_item(self.start_row_index) self.treeview.set_list(self.rs); self.drawingarea.set_rectangle_list([[ row[0],row[0],row[1],row[2],row[3] ] for row in self.rs ]) self.treeview.set_cursor(self.start_row_index) self.drawingarea.set_rectangle_list([[ row[0],row[1],row[2],row[3],row[4] ] for row in self.rs ]) self.treeview.unblock_cursor_change_signal() self.previus_row_index = row_index; self.drawingarea.redraw() def __drawingarea_button_release_event(self, point, button_type): if(self.start_type == 1): self.finish_x,self.finish_y=point self.drawingarea.set_drawing_rectangle(None) #Swap coordinate if selected in reverse direction self.start_x,self.start_y,self.tmp_finish_x,self.tmp_finish_y = image_logics.order_rectangle(self.start_x,self.start_y,self.tmp_finish_x,self.tmp_finish_y) # finding the index of new box inside the box list index = image_logics.find_index_for_new_box(self.start_x,self.start_y,self.tmp_finish_x,self.tmp_finish_y, [[ row[1],row[2],row[3],row[4] ] for row in self.rs ]); # Inserting the new box to the list self.rs.insert(index,[0,self.start_x,self.start_y,self.tmp_finish_x-self.start_x,self.tmp_finish_y-self.start_y,""]) self.set_selected_item(len([ [row[1],row[2],row[3],row[4],row[0] ] for row in self.rs ])-1) self.treeview.set_list(self.rs) self.drawingarea.set_rectangle_list([[ row[0],row[1],row[2],row[3],row[4] ] for row in self.rs ]); self.drawingarea.redraw() self.emit('list_updated') # 2 - Resize or 3 - Moving if(self.start_type == 2 or self.start_type == 3): self.set_selected_item(self.start_row_index) self.treeview.set_list(self.rs); self.emit('list_updated') self.start_type = 0; def set_selected_item(self,row): self.selected_item = row; for i in range(0,len(self.rs)): if (i == row): self.rs[i][0] = 1; else: self.rs[i][0] = 0; def get_selected_item_index(self): return self.selected_item; def __delete_selection(self,widget): list = [] for item in self.rs: if (item[0] == 0): list.append(item) self.rs = list; # Set first element as selected self.set_selected_item(0) # reset selection index self.start_row_index = -1; self.treeview.set_list(self.rs) self.drawingarea.set_rectangle_list([[ row[0],row[1],row[2],row[3],row[4] ] for row in self.rs ]) self.drawingarea.redraw() self.emit('list_updated') def clear_selection(self,widget): self.rs = [] self.treeview.clear() # reset selection index self.start_row_index = -1; self.drawingarea.set_rectangle_list([[ row[0],row[1],row[2],row[3],row[4] ] for row in self.rs ]); self.drawingarea.redraw() self.emit('list_updated') def connect_context_menu_button_callback(self,function): self.drawingarea.connect_context_menu_button_callback(function) class TestWindow(window.Window): def __init__(self): window.Window.__init__(self, title="Hello World") self.iv = ImageViewer() li = [(0,10,10,10,10,"a"),(0,30,30,10,10,"b"),(0,50,50,10,10,"c")] self.iv.load_image("/usr/share/lios/lios.png",li,ImageViewer.ZOOM_FIT) button1 = widget.Button("Get List") button1.connect_function(self.on_button1_clicked) button2 = widget.Button(label="Set List") button2.connect_function(self.on_button2_clicked) button3 = widget.Button(label="Zoom-In") button3.connect_function(self.on_button3_clicked) button4 = widget.Button(label="Zoom-Out") button4.connect_function(self.on_button4_clicked) grid = containers.Grid() grid.add_widgets([(self.iv,2,1,True,True),containers.Grid.NEW_ROW, (button1,1,1,True,False),(button2,1,1,True,False),containers.Grid.NEW_ROW, (button3,1,1,True,False),(button4,1,1,True,False)]) self.add(grid) grid.show() self.set_default_size(700,600); def on_button1_clicked(self, widget): print(self.iv.get_selection_list()) def on_button2_clicked(self, widget): self.iv.set_selection_list([(25,10,45,60)]) def on_button3_clicked(self, widget): self.iv.zoom_in() def on_button4_clicked(self, widget): self.iv.zoom_out() if __name__ == "__main__": win = TestWindow() win.connect("delete-event", lambda x,y : loop.stop_main_loop()) win.show_all() loop.start_main_loop() lios-3-2.7.2/lios/localization.py000066400000000000000000000002631345364566700166640ustar00rootroot00000000000000#!/usr/bin/env python3 import gettext from lios import macros gettext.bindtextdomain(macros.app_name, '/usr/share/locale') gettext.textdomain(macros.app_name) _ = gettext.gettext lios-3-2.7.2/lios/macros.py000066400000000000000000000051621345364566700154630ustar00rootroot00000000000000#!/usr/bin/env python3 ########################################################################### # Lios - Linux-Intelligent-Ocr-Solution # Copyright (C) 2011-2015 Nalin.x.Linux GPL-3 # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ########################################################################### import os import itertools def get_list_of_mixed_case_combinations(list_items): return list(itertools.chain.from_iterable([[''.join(a) for a in itertools.product(*zip(s.upper(), s.lower()))] for s in list_items])) user_home_path = os.environ['HOME'] config_dir = user_home_path+"/.lios" tmp_dir = "/tmp/Lios/" bookmarks_dir = config_dir+"/bookmarks/" local_text_cleaner_list_file_path = config_dir+"/text_cleaner_list.text" default_text_cleaner_list_file_path = "/usr/share/lios/text_cleaner_list.text" preferences_file_path = config_dir+"/preferences.cfg" recent_file_path = config_dir+"/recent.text" supported_image_formats = get_list_of_mixed_case_combinations(["png","pnm","jpg","jpeg","tif","tiff","bmp","pbm","ppm"]) supported_text_formats = get_list_of_mixed_case_combinations(["txt","text"]) supported_pdf_formats = get_list_of_mixed_case_combinations(["pdf"]) version = "2.7.1" logo_file = "/usr/share/lios/lios.png" icon_dir = "/usr/share/lios/icons/" readme_file = "/usr/share/lios/readme.text" default_text_cleaner_list_file_path = "/usr/share/lios/text_cleaner_list.text" app_name = "Linux-intelligent-ocr-solution" source_link = "https://gitlab.com/Nalin-x-Linux/lios-3" home_page_link = "http://sourceforge.net/projects/lios/" video_tutorials_link = "https://www.youtube.com/playlist?list=PLn29o8rxtRe1zS1r2-yGm1DNMOZCgdU0i" major_character_encodings_list = [ 'us_ascii', 'utf-8', 'iso_8859_1','latin1', 'iso_8859_2', 'iso_8859_7', 'iso_8859_9', 'iso_8859_15', 'eucjp', 'euckr', 'gb2312_80', 'gb2312_1980', 'windows_1251', 'windows_1252', 'windows_1253', 'windows_1254', 'windows_1255', 'windows_1256', 'windows_1257', 'windows_1258', 'shiftjis', 'windows_1256', 'big5_hkscs', 'big5_tw', 'tis620'] lios-3-2.7.2/lios/main.py000077500000000000000000001645651345364566700151430ustar00rootroot00000000000000#!/usr/bin/env python3 ########################################################################### # Lios - Linux-Intelligent-Ocr-Solution # Copyright (C) 2011-2015 Nalin.x.Linux GPL-3 # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ########################################################################### import os import subprocess import sys import time import shutil import re from functools import wraps from lios import scanner, editor, imageview, cam, ocr, preferences, speech, train_tesseract from lios.ui.gtk import widget, containers, loop, menu, \ window, icon_view, dialog, about from lios.ui.gtk.file_chooser import FileChooserDialog from lios import macros from lios import preferences from lios import capture_screen from lios import dictionary from lios import localization _ = localization._ import multiprocessing import threading import webbrowser def on_thread(function): @wraps(function) def inner(*args): print(function.__name__+" Started") #function(*args); threading.Thread(target=function,args=args).start() return inner class linux_intelligent_ocr_solution(): def __init__ (self,file_list=[]): try: os.mkdir(macros.tmp_dir) except: pass try: os.mkdir(macros.config_dir) except: pass try: os.mkdir(macros.bookmarks_dir) except: pass #Icon View scroll_box_iconview = containers.ScrollBox() self.iconview = icon_view.IconView() self.iconview.set_vexpand(True) scroll_box_iconview.add(self.iconview) box_iconview = containers.Box(containers.Box.VERTICAL) toolbar_iconview = containers.Toolbar(containers.Toolbar.HORIZONTAL, [(_('Open'),self.open_files),(_("Take-Screenshot"),self.take_rectangle_screenshot), (_("Scan-Using-Webcam"),self.scan_using_cam),(_("Recognize"),self.ocr_selected_images), (_("Clear"),self.iconview_remove_all_images),]) #Context menu self.context_menu_iconview = menu.ContextMenu([ (_("Recognize"),self.ocr_selected_images), (_("Recognize-With-Rotation"),self.ocr_selected_images_with_rotation), menu.SEPARATOR, (_("Rotate-Left"),self.rotate_selected_images_to_left), (_("Rotate-Twice"),self.rotate_selected_images_to_twice), (_("Rotate-Right"),self.rotate_selected_images_to_right), menu.SEPARATOR, (_("Invert-List"),self.iconview.invert_list), menu.SEPARATOR, (_("Save"),self.save_selected_images), (_("Export-As-Pdf"),self.save_selected_images_as_pdf), menu.SEPARATOR, (_("Delete"),self.iconview_remove_selected_images)]) self.iconview.connect_on_selected_callback(self.on_iconview_item_selected) self.iconview.connect_context_menu_button_callback(self.iconview_popup_context_menu) box_iconview.add(toolbar_iconview) box_iconview.add(scroll_box_iconview) #Image View self.imageview = imageview.ImageViewer() self.imageview.set_label_entry_visible(False) self.imageview.connect("list_updated",self.list_updated_event_handler); self.imageview.set_vexpand(True) self.imageview.set_hexpand(True) box_imageview = containers.Box(containers.Box.HORIZONTAL) toolbar_imageview = containers.Toolbar(containers.Toolbar.VERTICAL, [(_("Rotate-Right"),self.rotate_current_images_to_right), (_("Rotate-Twice"),self.rotate_current_images_to_twice), (_("Rotate-Left"),self.rotate_current_images_to_left),containers.Toolbar.SEPARATOR, (_("Zoom-In"),self.imageview.zoom_in),(_("Zoom-Fit"),self.imageview.zoom_fit), (_("Zoom-Out"),self.imageview.zoom_out),containers.Toolbar.SEPARATOR, (_("Recognize-Selected-Areas"),self.ocr_selected_areas), (_("Recognize-Current-Image"),self.ocr_current_image), (_("Recognize-Current-Image-With-Rotation"),self.ocr_current_image_with_rotation)]); box_imageview.add(toolbar_imageview) box_imageview.add(self.imageview) self.imageview.load_image(macros.logo_file,[],imageview.ImageViewer.ZOOM_FIT) #Context menu self.context_menu_imageview = menu.ContextMenu( [(_("Recognize-Current-Image"),self.ocr_current_image), (_("Recognize-Selected-Areas"),self.ocr_selected_areas), (_("Recognize-Current-Image-With-Rotation"),self.ocr_current_image_with_rotation),menu.SEPARATOR, (_("Rotate-Right"),self.rotate_current_images_to_right), (_("Rotate-Twice"),self.rotate_current_images_to_twice), (_("Rotate-Left"),self.rotate_current_images_to_left),menu.SEPARATOR, (_("Zoom-In"),self.imageview.zoom_in),(_("Zoom-Fit"),self.imageview.zoom_fit), (_("Zoom-Out"),self.imageview.zoom_out), menu.SEPARATOR, (_("Train-Selected-Areas"),self.train_selected_areas), (_("Save-Selected-Areas"),self.save_selected_areas), ]); self.imageview.connect_context_menu_button_callback(self.imageview_popup_context_menu) #Editor self.textview = editor.BasicTextView() self.textview.set_vexpand(True) self.textview.set_hexpand(True) self.textview.set_accepts_tab(False) box_editor = containers.Box(containers.Box.HORIZONTAL) toolbar_editor = containers.Toolbar(containers.Toolbar.VERTICAL, [(_("New"),self.new),(_('Open'),self.open_files), (_("Save"),self.textview.save),containers.Toolbar.SEPARATOR, (_("Spell-Check"),self.textview.open_spell_check),containers.Toolbar.SEPARATOR, (_("Undo"),self.textview.undo),(_("Redo"),self.textview.redo), containers.Toolbar.SEPARATOR, (_("Find"),self.textview.open_find_dialog), (_("Find-Replace"),self.textview.open_find_and_replace_dialog), containers.Toolbar.SEPARATOR, (_("Start-Reader"),self.start_reader), (_("Stop-Reader"),self.stop_reader), containers.Toolbar.SEPARATOR, (_("Go-To-Line"),self.textview.go_to_line), (_("Go-To-Page"),self.go_to_page), ]) box_editor.add(toolbar_editor) scroll_box_editor = containers.ScrollBox() scroll_box_editor.add(self.textview) box_editor.add(scroll_box_editor) #Load TextCleaner List if(not self.textview.set_text_cleaner_list_from_file(macros.local_text_cleaner_list_file_path)): self.textview.set_text_cleaner_list_from_file(macros.default_text_cleaner_list_file_path) self.textview.save_text_cleaner_list_to_file(macros.local_text_cleaner_list_file_path) #OCR Engine self.available_ocr_engine_list = ocr.get_available_engines() #Scanner Drivers self.available_scanner_driver_list = scanner.get_available_drivers() self.scanner_objects = [] self.is_updating_scanner_list = False # Initialize locking mechanism loop.threads_init() #Load Preferences self.preferences = preferences.lios_preferences() self.preferences.set_from_file(macros.preferences_file_path) self.preferences.set_avalable_scanner_drivers([ item.name for item in self.available_scanner_driver_list]) self.preferences.set_avalable_ocr_engines([ (item.name,item.get_available_languages()) for item in self.available_ocr_engine_list ]) menubar = menu.MenuBar( [[_("_File"),(_("New"),self.textview.new,"N"),menu.SEPARATOR, (_("Open"),self.open_files,"O"), (_("Save"),self.textview.save,"S"),(_("Save-As"),self.textview.save_as,"N"), (_("Export-Text-As-Pdf"),self.textview.print_to_pdf,"E"),(_("Print"),self.textview.open_print_dialog,"None"), (_("Print-Preview"),self.textview.print_preview,"None"),menu.SEPARATOR, (_("Quit"),self.quit,"Q")], [_("_Edit"),(_("Undo"),self.textview.undo,"Z"),(_("Redo"),self.textview.redo,"Y"), menu.SEPARATOR, (_("Punch-Text"),self.textview.punch,"None"),(_("Append-Text"),self.textview.append,"None"), menu.SEPARATOR,(_("Find"),self.textview.open_find_dialog,"F"), (_("Find-Replace"),self.textview.open_find_and_replace_dialog,"R") ,menu.SEPARATOR, (_("Spell-Check"),self.textview.open_spell_check,"F7"), menu.SEPARATOR, (_("Go-To-Line"),self.textview.go_to_line,"L"),(_("Go-To-Page"),self.go_to_page,"G"), menu.SEPARATOR,(_("Preferences"),self.open_preferences_general_page,"P")], [_("_Image"),[_("Rotate-Left"),(_("Current"),self.rotate_current_images_to_left,"None"), (_("Selected"),self.rotate_selected_images_to_left,"None"), (_("All"),self.rotate_all_images_to_left,"None")], [_("Rotate-Twice"),(_("Current"),self.rotate_current_images_to_twice,"None"), (_("Selected"),self.rotate_selected_images_to_twice,"None"), (_("All"),self.rotate_all_images_to_twice,"None")], [_("Rotate-Right"),(_("Current"),self.rotate_current_images_to_right,"None"), (_("Selected"),self.rotate_selected_images_to_right,"None"), (_("All"),self.rotate_all_images_to_right,"None")], menu.SEPARATOR, (_("Invert-List"),self.iconview.invert_list,"None"), menu.SEPARATOR, [_("Save"),(_("Selected-Images"),self.save_selected_images,"None"), (_("All-Images"),self.save_all_images,"None")], [_("Export-As-Pdf"),(_("Selected-Images"),self.save_selected_images_as_pdf,"None"), (_("All-Images"),self.save_all_images_as_pdf,"None")], menu.SEPARATOR, [_("Delete"),(_("Selected-Images"),self.iconview_remove_selected_images,"None"), (_("All-Images"),self.iconview_remove_all_images,"None")],], [_("_Scan"),(_("Update-Scanner-List"),self.update_scanner_list,"None"), (_("Scan-Image"),self.scan_single_image,"F8"), (_("Scan-Image-Repeatedly"),self.scan_image_repeatedly,"F8"), (_("Scan-and-Ocr"),self.scan_and_ocr,"F9"), (_("Scan-and-Ocr-Repeatedly"),self.scan_and_ocr_repeatedly,"F9"), (_("Optimise-Scanner-Brightness"),self.optimize_brightness,"None"),menu.SEPARATOR, (_("Scan-Using-Webcam"),self.scan_using_cam,"F6"),menu.SEPARATOR, [_("Take-Screenshot"), (_("Selection"),self.take_rectangle_screenshot,"F2"), (_("Full"),self.take_full_screenshot,"F2")], [_("Take-and-Recognize-Screenshot"), (_("Selection"),self.take_and_recognize_rectangle_screenshot,"F3"), (_("Full"),self.take_and_recognize_full_screenshot,"F3")]], [_("_Recognize"), (_("Recognize-Current-Image"),self.ocr_current_image,"None"), (_("Recognize-Current-Image-With-Rotation"),self.ocr_current_image_with_rotation,"None"), (_("Recognize-Selected-Areas"),self.ocr_selected_areas,"None"), (_("Recognize-Selected-Images"),self.ocr_selected_images,"None"), (_("Recognize-All-Images"),self.ocr_all_images,"None"), (_("Recognize-Selected-with-rotation"),self.ocr_selected_images_with_rotation,"None"), (_("Recognize-All-with-rotation"),self.ocr_all_images_with_rotation,"None")], [_("_Tools"),(_("Spell-Check"),self.textview.open_spell_check,"F7"), (_("Train-Tesseract"),self.start_train_tesseract,"None"), [_("Text-Cleaner"), (_("Text-Cleaner"),self.textview.open_text_cleaner,"None"), (_("Import"),self.textview.import_text_cleaner_list,"None"), (_("Export"),self.textview.export_text_cleaner_list,"None"), (_("Apply-From-Cursor"),self.textview.apply_text_cleaner_from_cursor,"None"), (_("Apply-Entire"),self.textview.apply_text_cleaner_entire_text,"None")], (_("Audio-Converter"),self.audio_converter,"None"), (_("Dictionary"),self.artha,"W"), (_("Bookmark"),self.textview.create_bookmark,"B"), (_("Bookmark-Table"),self.textview.open_bookmark_table,"B"), (_("Import-Bookmarks"),self.textview.import_bookmarks_from_file,"None"), (_("Bookmark-Table-Complete"),self.textview.open_all_bookmark_table,"B"), (_("Start-Reader"),self.start_reader,"F5"), (_("Stop-Reader"),self.stop_reader,"F5"), (_("Increase-Reader-Speed"),self.increase_reader_speed,"Prior"), (_("Decrease-Reader-Speed"),self.decrease_reader_speed,"Next"), (_("Stop-All-Process"),self.stop_all_process,"F4")], [_("_Preferences"),(_("Preferences-General"),self.open_preferences_general_page,"None"), (_("Preferences-Recognition"),self.open_preferences_recognition_page,"None"), (_("Preferences-Scanning"),self.open_preferences_scanning_page,"None"), menu.SEPARATOR, (_("Save"),self.save_preferences,"None"), (_("Load"),self.load_preferences,"None"), (_("Restore"),self.restore_preferences,"None")], [_("Help"),(_("Open-Readme"),self.open_readme,"None"), (_("Video-Tutorials"),self.open_video_tutorials,"None"), (_("Open-Home-Page"),self.open_home_page,"None"), (_("Get-Source-Code"),self.get_source_code,"None"), menu.SEPARATOR,(_("About"),self.about,"None")]]) menubar.show() self.combobox_scanners = widget.ComboBox() button_update_scanner_list = widget.Button(_("Update-Scanner-List")) button_update_scanner_list.connect_function(self.update_scanner_list) button_scan = widget.Button(_("Scan")) button_scan.connect_function(self.scan_single_image) toolbar_main = containers.Toolbar(containers.Toolbar.HORIZONTAL, [(_("Preferences"),self.open_preferences_general_page), (_("Video-Tutorials"),self.open_video_tutorials), (_("About"),self.about), (_("Quit"),self.quit)]) #Slide Panes self.paned_image_text = containers.Paned(containers.Paned.VERTICAL) self.paned_image_text.add1(box_imageview) self.paned_image_text.add2(box_editor) self.paned_main = containers.Paned(containers.Paned.HORIZONTAL) self.paned_main.add1(box_iconview) self.paned_main.add2(self.paned_image_text) self.statusbar = widget.Statusbar() self.progressbar = widget.ProgressBar() self.window = window.Window(macros.app_name) self.window.set_taskbar_icon(macros.logo_file) grid_main = containers.Grid() grid_main.add_widgets([ (menubar,5,1,containers.Grid.HEXPAND,containers.Grid.NO_VEXPAND),containers.Grid.NEW_ROW, (self.combobox_scanners,1,1,containers.Grid.HEXPAND,containers.Grid.NO_VEXPAND), (button_update_scanner_list,1,1,containers.Grid.HEXPAND,containers.Grid.NO_VEXPAND), (button_scan,1,1,containers.Grid.HEXPAND,containers.Grid.NO_VEXPAND), (toolbar_main,2,1,containers.Grid.HEXPAND,containers.Grid.NO_VEXPAND,containers.Grid.ALIGN_END), containers.Grid.NEW_ROW, (self.paned_main,5,1), containers.Grid.NEW_ROW, (self.statusbar,4,1,containers.Grid.HEXPAND,containers.Grid.NO_VEXPAND), (self.progressbar,1,1,containers.Grid.HEXPAND,containers.Grid.NO_VEXPAND),]) # Set focus chain to increase accessibility via skipping toolbars grid_main.set_focus_chain([self.combobox_scanners,button_update_scanner_list,button_scan, self.paned_main ]) self.paned_main.set_focus_chain([box_iconview, self.paned_image_text]) self.paned_image_text.set_focus_chain([self.textview]) box_iconview.set_focus_chain([self.iconview]) if(len(file_list) > 1 ): self.open_list_of_files(file_list[1:]) try: self.textview.save_file_name except: try: file = open(macros.recent_file_path,encoding="utf-8") self.textview.set_text(file.read()) except: pass else: try: file = open(macros.recent_file_path,encoding="utf-8") self.textview.set_text(file.read()) except: pass self.old_language = -1 self.old_scan_driver = -1 self.old_scanner_mode_switching = -1 #This will clear scanner combobox #so scanner combobox should be inetialised self.make_preferences_effective() # Text TTS reading switch self.is_reading = False self.reader_stop_pressed = False self.notify_information(_("Welcome to {} Version {}").format(macros.app_name,macros.version),0) #For connecting menubar accell group Gtk self.window.connect_menubar(menubar) self.window.connect_configure_event_handler(self.window_reconfigure) self.window.connect_close_function(self.quit) grid_main.show_all() self.window.add(grid_main) self.window.maximize() self.textview.grab_focus() self.window.show() loop.start_main_loop() def notify_information(self,text,percentage = -1): self.statusbar.set_text(text) if(percentage == -1): self.progressbar.set_pulse_mode(True) self.progressbar.set_pulse_step(0.030) else: self.progressbar.set_pulse_mode(False) self.progressbar.set_fraction(percentage) def start_train_tesseract(self,*data): list_ = [] if (len(self.imageview.get_selection_list()) > 0): # User alrady selected some areas i = 0; for item in self.imageview.get_selection_list(): self.imageview.save_sub_image("{0}train_area{1}.png".format(macros.tmp_dir,i),item[0],item[1],item[2],item[3]) list_.append("{0}train_area{1}.png".format(macros.tmp_dir,i)) i = i + 1; else: # No area selected so seeking for selected images list_ = self.iconview.get_selected_item_names() if(list_ == []): # No images selected so selecting all self.iconview.select_all() list_ = self.iconview.get_selected_item_names() train_window = train_tesseract.TesseractTrainer(list_) train_window.show() train_window.connect_close_function(self.reload_language_list) def reload_language_list(self,*data): languages_available = self.available_ocr_engine_list[self.preferences.ocr_engine].get_available_languages() self.preferences.set_avalable_ocr_engines([ (item.name,item.get_available_languages()) for item in self.available_ocr_engine_list ]) def train_selected_areas(self,*data): if (len(self.imageview.get_selection_list()) > 0): area_list = [] i = 0; for item in self.imageview.get_selection_list(): self.imageview.save_sub_image("{0}train_area{1}.png".format(macros.tmp_dir,i),item[0],item[1],item[2],item[3]) area_list.append("{0}train_area{1}.png".format(macros.tmp_dir,i)) i = i + 1; train_window = train_tesseract.TesseractTrainer(area_list) train_window.show() train_window.connect_close_function(self.reload_language_list) def list_updated_event_handler(self,*data): filename = self.imageview.get_filename() if(filename == macros.logo_file): self.imageview.clear_selection(None) else: file = open(filename+".box","w") for item in self.imageview.get_list(): file.write("{0} {1} {2} {3} {4} 0\n".format(str(item[0]), str(int(item[1])),str(int(item[2])), str(int(item[3])),str(int(item[4])))) @on_thread def save_selected_areas(self,*data): for item in self.imageview.get_selection_list(): destination = self.get_feesible_filename_from_filename("{}{}.png".format(macros.tmp_dir,self.preferences.starting_page_number)) self.imageview.save_sub_image(destination,item[0],item[1],item[2],item[3]) loop.acquire_lock() self.iconview.add_item(destination) loop.release_lock() self.preferences.update_page_number() def new(self,*data): if(self.textview.new()): self.preferences.starting_page_number = 1 with open(macros.recent_file_path,"w") as file: file.write("") def audio_converter(self,*data): self.textview.audio_converter(voice=self.preferences.speech_language) def go_to_page(self,*data): spinbutton_page = widget.SpinButton(0,0,self.preferences.starting_page_number,1,5,0) dlg = dialog.Dialog(_("Go to page"),(_("Go"), dialog.Dialog.BUTTON_ID_1,_("Close!"), dialog.Dialog.BUTTON_ID_2)) dlg.add_widget_with_label(spinbutton_page,_("Page Number : ")) spinbutton_page.grab_focus() dlg.show_all() response = dlg.run() if response == dialog.Dialog.BUTTON_ID_1: to_go = spinbutton_page.get_value() # Start search from begining to match properly self.textview.move_cursor_to_line(1) if (self.preferences.page_numbering_type == 0): word = "Page-{0}".format(to_go) else: if (to_go % 2 == 0): word = "Page-{0}-{1}".format(to_go-1,to_go) else: word = "Page-{0}-{1}".format(to_go,to_go+1) if(not self.textview.move_forward_to_word(word)): self.textview.move_backward_to_word(word) dlg.destroy() else: dlg.destroy() def open_video_tutorials(self,*data): webbrowser.open(macros.video_tutorials_link) def open_home_page(self,*data): webbrowser.open(macros.home_page_link) def get_source_code(self,*data): webbrowser.open(macros.source_link) def iconview_popup_context_menu(self,*data): if (self.iconview.get_selected_item_names() == []): self.iconview.select_all() if (self.iconview.get_selected_item_names() != []): self.context_menu_iconview.pop_up() def imageview_popup_context_menu(self,*data): self.context_menu_imageview.pop_up() def window_reconfigure(self,*arg): width,height = self.window.get_size() self.paned_image_text.set_position(height/2) self.paned_main.set_position(200) self.imageview.set_position(width-500) def get_feesible_filename_from_filename(self,filename): if (os.path.exists(re.sub('[^.-/#0-9a-zA-Z]+', '#', filename))): return self.get_feesible_filename_from_filename(filename.replace('.','#.')) else: return re.sub('[^.-/#0-9a-zA-Z]+', '#', filename) def add_image_to_list(self,file_name_with_directory,destination,move,lock=False): if (move): shutil.move(file_name_with_directory,destination) else: shutil.copyfile(file_name_with_directory,destination) self.iconview.add_item(destination) @on_thread def import_images_from_pdf(self,pdf_filename_full): # self.make_image_widgets_inactive(lock=True) pdf_filename = pdf_filename_full.split("/")[-1:][0] filename = pdf_filename.split(".")[0] pdf_filename = re.sub('[^.-/#0-9a-zA-Z]+', '#', pdf_filename) destination = "{0}{1}".format(macros.tmp_dir,pdf_filename) shutil.copyfile(pdf_filename_full,destination) os.makedirs(destination.split(".")[0],exist_ok=True) self.notify_information(_("Extracting images from Pdf")) p = multiprocessing.Process(target=lambda : os.system("pdftoppm {} {}/{} -png" .format(destination,destination.split(".")[0],pdf_filename.split(".")[0])) , args=()) p.start() while(p.is_alive()): pass os.remove(destination) file_list = os.listdir(destination.split(".")[0]) file_list = sorted(file_list) for image in file_list: if(len(image.split("."))>1): if (image.split(".")[1] in macros.supported_image_formats): filename = "{}{}".format(macros.tmp_dir,image) filename = self.get_feesible_filename_from_filename(filename) loop.acquire_lock() self.add_image_to_list("{}/{}".format(destination.split(".")[0],image),filename,True) loop.release_lock() os.rmdir(destination.split(".")[0]) self.notify_information(_("Completed!"),0) # self.make_image_widgets_active(lock=True) @on_thread #should continue the loop to get window minimize def take_full_screenshot(self,data): destination = self.get_feesible_filename_from_filename("{}{}.png".format(macros.tmp_dir,self.preferences.starting_page_number)) self.window.iconify() #minimize os.system("sleep 1") #Time to minimize lios window capture_screen.capture_entire_screen(destination) loop.acquire_lock() self.iconview.add_item(destination) loop.release_lock() self.preferences.update_page_number() @on_thread def take_rectangle_screenshot(self,data): destination = self.get_feesible_filename_from_filename("{}{}.png".format(macros.tmp_dir,self.preferences.starting_page_number)) self.window.iconify() #minimize capture_screen.capture_rectangle_selection(destination) loop.acquire_lock() self.iconview.add_item(destination) loop.release_lock() self.preferences.update_page_number() @on_thread def take_and_recognize_full_screenshot(self,data): destination = self.get_feesible_filename_from_filename("{}{}.png".format(macros.tmp_dir,self.preferences.starting_page_number)) self.window.iconify() #minimize os.system("sleep 1") #Time to minimize lios window capture_screen.capture_entire_screen(destination) loop.acquire_lock() self.iconview.add_item(destination) loop.release_lock() text,angle = self.ocr(destination,2,00) self.insert_text_to_textview(text,self.preferences.insert_position) self.preferences.update_page_number() @on_thread def take_and_recognize_rectangle_screenshot(self,data): destination = self.get_feesible_filename_from_filename("{}{}.png".format(macros.tmp_dir,self.preferences.starting_page_number)) self.window.iconify() #minimize capture_screen.capture_rectangle_selection(destination) loop.acquire_lock() self.iconview.add_item(destination) loop.release_lock() text,angle = self.ocr(destination,2,00) self.insert_text_to_textview(text,self.preferences.insert_position) self.preferences.update_page_number() def on_iconview_item_selected(self,data): name = self.iconview.get_selected_item_names() if(name): self.imageview.load_image(name[0],[],imageview.ImageViewer.ZOOM_FIT) list_ = [] if (not os.path.exists(name[0]+".box")): return for line in open(name[0]+".box"): spl = line.split(" ") try: list_.append((int(spl[0]),float(spl[1]),float(spl[2]),float(spl[3]),float(spl[4]),str(spl[5]))) except: pass self.imageview.set_list(list_,0) else: self.imageview.load_image(macros.logo_file,[],imageview.ImageViewer.ZOOM_FIT) @on_thread def update_scanner_list(self,*data): # Variable to check before quit process self.is_updating_scanner_list = True try: self.combobox_scanners.clear() for item in self.scanner_objects: item.close() #scanner.scanner.exit() #scanner_store = Gtk.ListStore(str) self.scanner_objects = [] #self.make_preferences_widgets_inactive(lock=True) #self.make_scanner_widgets_inactive(lock=True) loop.acquire_lock() self.notify_information(_("Getting devices")) loop.release_lock() #Tuple - List Convertion is used to get all items in devices list parent_conn, child_conn = multiprocessing.Pipe() p = multiprocessing.Process(target=(lambda parent_conn, child_conn : child_conn.send(tuple(self.available_scanner_driver_list[self.preferences.scan_driver].get_available_devices()))), args=(parent_conn, child_conn)) p.start() while(p.is_alive()): pass driver = self.available_scanner_driver_list[self.preferences.scan_driver] list_ = list(parent_conn.recv()) for device in list_: self.notify_information(_("Setting Scanner {}").format(device)) scanner = driver(device,self.preferences.scanner_mode_switching, self.preferences.scan_resolution,self.preferences.scan_brightness, self.preferences.scan_area) self.scanner_objects.append(scanner) self.combobox_scanners.add_item(scanner.device_name) print(self.scanner_objects) loop.acquire_lock() #self.combobox_scanner.set_model(scanner_store) if (len(self.scanner_objects) != 0): self.combobox_scanners.set_active(0) #self.make_scanner_widgets_active(lock=True) self.notify_information(_("Completed!"),0) else: #self.button_refresh.set_sensitive(True) #self.spinner.set_state(False) #self.spinner.hide() self.notify_information(_("No Scanner Detected!"),0) pass #self.make_preferences_widgets_active(lock=True) loop.release_lock() except Exception as ex: loop.acquire_lock() self.notify_information("Scanner list update error : "+str(ex),0) loop.release_lock() finally: self.is_updating_scanner_list = False @on_thread def scan_single_image(self,widget): #self.make_scanner_widgets_inactive(lock=True) #self.make_preferences_widgets_inactive(lock=True) destination = "{0}{1}.jpg".format(macros.tmp_dir,self.preferences.get_page_number_as_string()) destination = self.get_feesible_filename_from_filename(destination) t = threading.Thread(target=self.scan,args=(destination,)) t.start() while(t.is_alive()): pass self.preferences.update_page_number() #self.make_scanner_widgets_active(lock=True) #self.make_preferences_widgets_active(lock=True) @on_thread def scan_image_repeatedly(self,widget): #self.make_scanner_widgets_inactive(lock=True) #self.make_preferences_widgets_inactive(lock=True) self.process_breaker = False for i in range(0,self.preferences.number_of_pages_to_scan): destination = "{0}{1}.jpg".format(macros.tmp_dir,self.preferences.get_page_number_as_string()) destination = self.get_feesible_filename_from_filename(destination) t = threading.Thread(target=self.scan,args=(destination,)) t.start() while(t.is_alive()): pass self.preferences.update_page_number() if(self.process_breaker): break time.sleep(self.preferences.time_between_repeated_scanning) if(self.process_breaker): break self.notify_information(_("completed!"),0) #self.make_scanner_widgets_active(lock=True) #self.make_preferences_widgets_active(lock=True) def scan(self,filename): self.process_breaker = False selected_scanner = self.combobox_scanners.get_active() #No scanner added to list if(selected_scanner == -1): self.notify_information(_("No Scanner Detected!. Please update scanner list and try again"),0) return; self.notify_information(_("Scanning {}, resolution {}, brightness {}"). format(filename.split("/")[-1],self.preferences.scan_resolution,self.preferences.scan_brightness)) p = multiprocessing.Process(target=(self.scanner_objects[selected_scanner].scan), args=(filename,self.preferences.scan_resolution, self.preferences.scan_brightness,self.preferences.scan_area)) p.start() while(p.is_alive()): pass self.notify_information(_("Scan Completed!"),0) if(self.process_breaker): return loop.acquire_lock() self.iconview.add_item(filename) loop.release_lock() if(self.process_breaker): return ############## OCR ################################ def ocr(self,file_name,mode,angle): self.process_breaker = False ocr_engine_object = self.available_ocr_engine_list[self.preferences.ocr_engine]() languages_available = self.available_ocr_engine_list[self.preferences.ocr_engine].get_available_languages() language = languages_available[self.preferences.language] ocr_engine_object.set_language(language) print(language) rotation_list = [00,90,180,270] if mode == 2: #Manual if(angle not in rotation_list): os.system("convert -rotate {0} {1} {1}".format(rotation_list[angle],file_name)) else: os.system("convert -rotate {0} {1} {1}".format(angle,file_name)) text = ocr_engine_object.ocr_image_to_text_with_multiprocessing(file_name) return (text,angle) else: #Full_Automatic or Partial_Automatic list_ = [] for angle in rotation_list: os.system("convert -rotate {0} {1} {1}_test".format(angle,file_name)) text = ocr_engine_object.ocr_image_to_text_with_multiprocessing(file_name+"_test") count = self.count_dict_words(text) list_.append((text,count,angle)) if(self.process_breaker): return True; list_ = sorted(list_, key=lambda item: item[1],reverse=True) os.system("convert -rotate {0} {1} {1}".format(list_[0][2],file_name)) return (list_[0][0],list_[0][2]) def count_dict_words(self,text): count = 0 for word in text.split(" "): if (len(word) > 1): if (self.dict.check(word) == True): count += 1 return count ############## OCR END ################################ def insert_text_to_textview(self,text,place_cursor = False,give_page_number = False): if(self.preferences.run_text_cleaner): text = self.textview.get_text_cleaner_out(text) loop.acquire_lock() if (give_page_number): text = "\nPage-{}\n{}".format(self.preferences.get_page_number_as_string(),text) self.textview.insert_text(text,self.preferences.insert_position) text = self.textview.get_text() loop.release_lock() with open(macros.recent_file_path,"w",encoding="utf-8") as file: file.write(text) @on_thread def scan_and_ocr(self,widget): #self.make_scanner_widgets_inactive(lock=True) #self.make_preferences_widgets_inactive(lock=True) #self.make_ocr_widgets_inactive(lock=True) self.process_breaker = False destination = "{0}{1}.jpg".format(macros.tmp_dir,self.preferences.get_page_number_as_string()) destination = self.get_feesible_filename_from_filename(destination) t = threading.Thread(target=self.scan,args=(destination,)) t.start() while(t.is_alive()): pass if(self.process_breaker): #self.make_scanner_widgets_active(lock=True) #self.make_ocr_widgets_active(lock=True) #self.make_preferences_widgets_active(lock=True) return self.notify_information(_("Recognizing {}").format(destination)) text,angle = self.ocr(destination,self.preferences.mode_of_rotation,self.preferences.rotation_angle) self.insert_text_to_textview(text,self.preferences.insert_position) self.imageview.redraw() loop.acquire_lock() self.iconview.reload_preview(destination) loop.release_lock() self.notify_information(_("Page {}").format(self.preferences.get_page_number_as_string()),0) self.preferences.update_page_number() #self.make_scanner_widgets_active(lock=True) #self.make_ocr_widgets_active(lock=True) #self.make_preferences_widgets_active(lock=True) @on_thread def scan_and_ocr_repeatedly(self,widget): #self.make_scanner_widgets_inactive(lock=True) #self.make_preferences_widgets_inactive(lock=True) #self.make_ocr_widgets_inactive(lock=True) mode = self.preferences.mode_of_rotation angle = self.preferences.rotation_angle self.process_breaker = False for i in range(0,self.preferences.number_of_pages_to_scan): destination = "{0}{1}.jpg".format(macros.tmp_dir,self.preferences.get_page_number_as_string()) destination = self.get_feesible_filename_from_filename(destination) t = threading.Thread(target=self.scan,args=(destination,)) t.start() while(t.is_alive()): pass if(self.process_breaker): break time.sleep(self.preferences.time_between_repeated_scanning) if(self.process_breaker): break self.notify_information(_("Recognizing {}").format(destination)) text,angle = self.ocr(destination,mode,angle) if (i == 0): self.insert_text_to_textview(text,True,self.preferences.give_page_number) else: self.insert_text_to_textview(text,False,self.preferences.give_page_number) self.imageview.redraw() loop.acquire_lock() self.iconview.reload_preview(destination) self.notify_information(_("Page {}").format(self.preferences.get_page_number_as_string()),0) loop.release_lock() self.preferences.update_page_number() if mode == 1: #Change the mode partial automatic to Manual mode = 2 #self.announce(_("Angle to be rotated = {}").format(angle)) if(self.process_breaker): break self.notify_information(_("Compleated"),0) #self.announce(_("Job completed!") #self.make_scanner_widgets_active(lock=True) #self.make_ocr_widgets_active(lock=True) #self.make_preferences_widgets_active(lock=True) @on_thread def optimize_brightness(self,wedget): #self.make_scanner_widgets_inactive(lock=True) #self.make_ocr_widgets_inactive(lock=True) #self.make_preferences_widgets_inactive(lock=True) selected_scanner = self.combobox_scanners.get_active() if (selected_scanner == -1): self.notify_information(_("No Scanner Detected!. Please update scanner list and try again"),0) return self.process_breaker = False mode = self.preferences.mode_of_rotation if (mode == 0 or mode == 1): self.notify_information(_("Scanning with resolution {}, brightness {}, for detecting angle of rotation.") .format(self.preferences.scan_resolution,self.preferences.scan_brightness)) p = multiprocessing.Process(target=(self.scanner_objects[selected_scanner].scan), args=("{0}rotate.pnm".format(macros.tmp_dir),self.preferences.scan_resolution, self.preferences.scan_brightness,self.preferences.scan_area)) p.start() while(p.is_alive()): pass text,angle = self.ocr("{0}rotate.pnm".format(macros.tmp_dir),mode,00) self.notify_information("Image at {} angle.".format(angle),0) else: angle = self.preferences.rotation_angle value = self.preferences.scan_brightness; distance = 10; start = 10; end = 90; count = None result_text = _("Click 'Optimize' to start optimisation ") while(1): loop.acquire_lock() dlg = dialog.Dialog(_("Optimize Scanner-Brightness"), (_("Optimize"), dialog.Dialog.BUTTON_ID_3, _("Apply"), dialog.Dialog.BUTTON_ID_2, _("Cancel"), dialog.Dialog.BUTTON_ID_1)) label_rotation = widget.Label(_("Angle to be rotated : ")) spinbutton_rotation = widget.SpinButton(angle,00,360,90,90,90) label_rotation.set_mnemonic_widget(spinbutton_rotation) try: spinbutton_rotation.set_value([00,90,180,270][angle]) except: spinbutton_rotation.set_value(angle) label_value = widget.Label(_("Current-Value")) spinbutton_value = widget.SpinButton(value,0,200,1,5,0) label_value.set_mnemonic_widget(spinbutton_value) label_start = widget.Label(_("Start")) spinbutton_start = widget.SpinButton(start,0,100,10,5,0) label_start.set_mnemonic_widget(spinbutton_start) label_distance = widget.Label(_("Distance")) spinbutton_distance = widget.SpinButton(distance,0,40,5,5,0) label_distance.set_mnemonic_widget(spinbutton_distance) label_end = widget.Label(_("End")) spinbutton_end = widget.SpinButton(end,0,100,10,5,0) label_end.set_mnemonic_widget(spinbutton_end) label_result = widget.Label(_("Result")) label_result.set_use_markup(True) label_result.set_label(result_text) grid = containers.Grid() grid.add_widgets([(label_rotation,1,1),(spinbutton_rotation,1,1), containers.Grid.NEW_ROW, (label_value,1,1),(spinbutton_value,1,1),containers.Grid.NEW_ROW, (label_start,1,1),(spinbutton_start,1,1),containers.Grid.NEW_ROW, (label_distance,1,1),(spinbutton_distance,1,1),containers.Grid.NEW_ROW, (label_end,1,1),(spinbutton_end,1,1),containers.Grid.NEW_ROW, (label_result,2,1)]); dlg.add_widget(grid) grid.show_all() response = dlg.run() dlg.destroy() loop.release_lock() if (response == dialog.Dialog.BUTTON_ID_2): self.preferences.scan_brightness = spinbutton_value.get_value() angle = spinbutton_rotation.get_value() loop.acquire_lock() dlg_set_mode = dialog.Dialog(_("Set Mode of rotation"), (_("Yes set this rotation"), dialog.Dialog.BUTTON_ID_1, _("No continue with existing mode"), dialog.Dialog.BUTTON_ID_2)) label = widget.Label(_("Do you want to fix the angle at {}\ \ndegree manual rotation ?").format(angle)) dlg_set_mode.add_widget(label) label.show() response = dlg_set_mode.run() if(response == dialog.Dialog.BUTTON_ID_1): self.preferences.mode_of_rotation = 2 self.preferences.rotation_angle = [00,90,180,270].index(angle) self.notify_information(_("Rotation mode changed to manual at angle {} degree"). format(self.preferences.rotation_angle),0) dlg_set_mode.destroy() loop.release_lock() #self.make_scanner_widgets_active(lock=True) #self.make_ocr_widgets_active(lock=True) #self.make_preferences_widgets_active(lock=True) return True elif (response == dialog.Dialog.BUTTON_ID_3): value = spinbutton_value.get_value() start = spinbutton_start.get_value() distance = spinbutton_distance.get_value() end = spinbutton_end.get_value() angle = spinbutton_rotation.get_value() self.preferences.scan_brightness = value else: #self.make_scanner_widgets_active(lock=True) #elf.make_ocr_widgets_active(lock=True) #self.make_preferences_widgets_active(lock=True) return True list = self.optimize_with_model(value,start,distance,end,angle,count) if (not list): #self.make_scanner_widgets_active(lock=True) #self.make_ocr_widgets_active(lock=True) #self.make_preferences_widgets_active(lock=True) return True count, value = list[0][0],list[0][1]; result_text = _("Optimisation Result ") for item in list: result_text += _("\nGot {} Words at brightness {}").format(item[0], item[1]) result_text += "" start = value-distance; end = value+distance; distance = distance / 2; def optimize_with_model(self,value,start,distance,end,angle,previous_optimised_count=None): selected_scanner = self.combobox_scanners.get_active() list = [] count = -1 pos = start while(pos <= end): if (pos == value and previous_optimised_count != None): list.append((previous_optimised_count,value)) #self.announce(_("Got {} words at brightness {}.").format(previous_optimised_count,mid_value)) else: if (count != -1): self.notify_information(_("Got {} words at brightness {}. Scanning with resolution {}, brightness {}.") .format(count,pos-distance,self.preferences.scan_resolution,pos)) else: self.notify_information(_("Scanning with resolution {}, brightness {}.") .format(self.preferences.scan_resolution,pos)) p = multiprocessing.Process(target=(self.scanner_objects[selected_scanner].scan), args=("{0}test.pnm".format(macros.tmp_dir,self.preferences.get_page_number_as_string()), self.preferences.scan_resolution,pos,self.preferences.scan_area)) p.start() while(p.is_alive()): pass if(self.process_breaker): list = sorted(list, key=lambda item: item[0],reverse=True) return (list) self.notify_information(_("Recognizing {0}test.pnm").format(macros.tmp_dir)) text,angle = self.ocr("{0}test.pnm".format(macros.tmp_dir),2,angle) count = self.count_dict_words(text) list.append((count,pos)) #self.announce(_("Got {} words at brightness {}.".format(count,pos))) pos = pos + distance self.notify_information(_("completed!"),0) list = sorted(list, key=lambda item: item[0],reverse=True) return (list) def stop_all_process(self,widget): self.process_breaker = True #selected_scanner = self.combobox_scanners.get_active() #self.scanner_objects[selected_scanner].cancel() os.system("pkill convert") self.available_ocr_engine_list[self.preferences.ocr_engine].cancel() self.notify_information(_("Terminated"),0) def open_readme(self,*data): if(self.textview.get_modified()): dlg = dialog.Dialog(_("Warning!"), (_("No"),dialog.Dialog.BUTTON_ID_1,_("Yes"),dialog.Dialog.BUTTON_ID_2)) label = widget.Label(_("Current text not saved! do you want to load readme without saving ? ")) label.show() dlg.add_widget(label) response = dlg.run() if response == dialog.Dialog.BUTTON_ID_2: with open(macros.readme_file) as file: self.textview.set_text(file.read()) dlg.destroy() else: with open(macros.readme_file) as file: self.textview.set_text(file.read()) @on_thread def ocr_selected_images_with_rotation(self,widget): #self.make_ocr_widgets_inactive(lock=True) #self.make_preferences_widgets_inactive(lock=True) #self.make_image_widgets_inactive(lock=True) items = self.iconview.get_selected_item_names(); length = len(items) if (length > 0): progress_step = 1/len(self.iconview.get_selected_item_names()) progress = 0; mode = self.preferences.mode_of_rotation angle = self.preferences.rotation_angle for item in self.iconview.get_selected_item_names(): self.notify_information(_("Running OCR on selected image {}") .format(item)) #self.announce(_("Recognising {}").format(self.liststore_images[item[0]][1])) progress = progress + progress_step; text,angle = self.ocr(item,mode,angle) self.insert_text_to_textview(text,self.preferences.insert_position,self.preferences.give_page_number) self.preferences.update_page_number() loop.acquire_lock() self.iconview.reload_preview(item) loop.release_lock() if mode == 1:#Changing partial automatic to Manual mode = 2 #self.announce(_("Angle to be rotated = {}").format(angle)) if(self.process_breaker): break self.imageview.redraw() #self.make_ocr_widgets_active(lock=True) #self.make_preferences_widgets_active(lock=True) #self.make_image_widgets_active(lock=True) self.notify_information(_("completed!"),0) else: self.notify_information(_("No item selected!"),0) def ocr_all_images_with_rotation(self,widget): self.iconview.select_all() self.ocr_selected_images(None) @on_thread def ocr_selected_images(self,widget): #self.make_ocr_widgets_inactive(lock=True) #self.make_preferences_widgets_inactive(lock=True) #self.make_image_widgets_inactive(lock=True) items = self.iconview.get_selected_item_names(); length = len(items) if (length > 0): progress_step = 1/length progress = 0; for item in items: self.notify_information(_("Running OCR on selected image {} (without rotating)") .format(item)) #self.announce(_("Recognising {} without rotating").format(self.liststore_images[item[0]][1])) progress = progress + progress_step; text,angle = self.ocr(item,2,00) self.insert_text_to_textview(text,self.preferences.insert_position,self.preferences.give_page_number) self.preferences.update_page_number() if(self.process_breaker): break self.notify_information(_("completed!"),0) else: self.notify_information(_("No item selected!"),0) #self.announce(_("Completed!")) #self.make_ocr_widgets_active(lock=True) #self.make_preferences_widgets_active(lock=True) #self.make_image_widgets_active(lock=True) def ocr_all_images(self,widget): self.iconview.select_all() self.ocr_selected_images(self) def iconview_remove_all_images(self,widget): self.iconview.select_all_items() self.iconview_remove_selected_images() def iconview_remove_selected_images(self,*data): if (len(self.iconview.get_selected_item_names()) >= 1): dlg = dialog.Dialog(_("Deleting !"),(_("Cancel"),dialog.Dialog.BUTTON_ID_1,_("Yes Delete"), dialog.Dialog.BUTTON_ID_2)) label = widget.Label(_("Are you sure you want to delete selected images ?")) dlg.add_widget(label) label.show() response = dlg.run() dlg.destroy() if (response == dialog.Dialog.BUTTON_ID_2): self.iconview.remove_selected_items() #self.drawingarea_load_image("{0}/ui/lios".format(macros.data_dir)) @on_thread def rotate_selected_images_to_angle(self,angle): if(len(self.iconview.get_selected_item_names()) == 0): self.notify_information(_("Nothing selected"),0) return progress_step = 1/len(self.iconview.get_selected_item_names()) progress = 0; for item in reversed(self.iconview.get_selected_item_names()): os.system("convert -rotate {0} {1} {1}".format(angle,item)) loop.acquire_lock() self.iconview.reload_preview(item) loop.release_lock() self.notify_information(_("Rotating selected image {} to {}") .format(item,angle),progress) progress = progress + progress_step; self.imageview.redraw() self.notify_information(_("completed!"),0) def rotate_selected_images_to_right(self,widget): self.rotate_selected_images_to_angle(90) def rotate_selected_images_to_left(self,widget): self.rotate_selected_images_to_angle(270) def rotate_selected_images_to_twice(self,widget): self.rotate_selected_images_to_angle(180) def rotate_all_images_to_right(self,widget): self.iconview.select_all() self.rotate_selected_images_to_right(None) def rotate_all_images_to_left(self,widget): self.iconview.select_all() self.rotate_selected_images_to_left(None) def rotate_all_images_to_twice(self,widget): self.iconview.select_all() self.rotate_selected_images_to_twice(None) def rotate_current_images_to_right(self,widget): filename = self.imageview.get_filename() self.iconview.select_item(filename) self.rotate_selected_images_to_right(None) def rotate_current_images_to_left(self,widget): filename = self.imageview.get_filename() self.iconview.select_item(filename) self.rotate_selected_images_to_left(None) def rotate_current_images_to_twice(self,widget): filename = self.imageview.get_filename() self.iconview.select_item(filename) self.rotate_selected_images_to_twice(None) def save_selected_images(self,widget): item_list = self.iconview.get_selected_item_names() if (len(item_list) == 0): pass elif (len(item_list) == 1): dlg = FileChooserDialog(_("Filename please"), FileChooserDialog.SAVE,macros.supported_image_formats, macros.user_home_path); response = dlg.run() if response == FileChooserDialog.ACCEPT: shutil.copy(item_list[0],dlg.get_filename()) dlg.destroy() else: dlg = FileChooserDialog(_("Select Folder to save images"), FileChooserDialog.OPEN_FOLDER,macros.supported_image_formats, macros.user_home_path); response = dlg.run() if response == FileChooserDialog.ACCEPT: directory = dlg.get_current_folder() for item in reversed(item_list): shutil.copy(item,directory) dlg.destroy() def save_all_images(self,widget): self.iconview.select_all() self.save_selected_images(None) def save_selected_images_as_pdf(self,widget): dlg = FileChooserDialog(_("Give pdf filename(with extention) to save images"), FileChooserDialog.SAVE,macros.supported_pdf_formats,macros.user_home_path) response = dlg.run() if response == FileChooserDialog.ACCEPT: file_name = dlg.get_filename() command = "convert " for item in self.iconview.get_selected_item_names(): command += item + " " command += '"'+file_name+'"' os.system(command) dlg.destroy() def save_all_images_as_pdf(self,widget): self.iconview.select_all() self.save_selected_images_as_pdf(None) @on_thread def ocr_current_image(self,widget): filename = self.imageview.get_filename() self.iconview.select_item(filename) self.ocr_selected_images(None) @on_thread def ocr_current_image_with_rotation(self,widget): filename = self.imageview.get_filename() self.iconview.select_item(filename) self.ocr_selected_images_with_rotation(None) @on_thread def ocr_selected_areas(self,widget): self.process_breaker = False #self.make_preferences_widgets_inactive(lock=True) #self.make_ocr_widgets_inactive(lock=True) #self.make_image_widgets_inactive(lock=True) progress_step = 1/len(self.imageview.get_selection_list()); progress = 0; for item in self.imageview.get_selection_list(): self.notify_information(_("Running OCR on selected Area [ X={} Y={} Width={} Height={} ]") .format(item[0],item[1],item[2],item[3])) progress = progress + progress_step; self.imageview.save_sub_image("{0}tmp".format(macros.tmp_dir), item[0],item[1],item[2],item[3]) #Will always be Manual with no rotation text,angle = self.ocr("{0}tmp".format(macros.tmp_dir),2,00) self.insert_text_to_textview(text,False,False) if(self.process_breaker): break; self.notify_information(_("completed!"),0) #self.make_preferences_widgets_active(lock=True) #self.make_ocr_widgets_active(lock=True) #self.make_image_widgets_active(lock=True) def make_preferences_effective(self,*data): if (self.old_language != self.preferences.language): languages = self.available_ocr_engine_list[self.preferences.ocr_engine].get_available_languages() self.old_language = self.preferences.language if (self.preferences.language >= len(languages)): self.old_language = 0; self.preferences.language = 0; try: self.dict = dictionary.Dict(dictionary.dictionary_language_dict[languages[self.preferences.language]]) except: self.dict = dictionary.Dict("en") dlg = dialog.Dialog(_("Dictionary not found!"), (_("Ok"),dialog.Dialog.BUTTON_ID_1)) label = widget.Label(_( """Please install aspell, ispell, hunspell, myspell, or uspell dictionary for your language and restart Lios! Otherwise spellchecker and auto-rotation will work with english(fallback). For example on debian based system one can install aspell or hunspell french dictionary using following commands apt-get install aspell-fr apt-get install hunspell-fr or ispell dict using apt-get install ifrench On rpm based system use yum install aspell-fr On arch based system use pacman -S aspell-fr""")) dlg.add_widget(label) label.show() dlg.run() dlg.destroy() if (self.old_scan_driver != self.preferences.scan_driver or self.old_scanner_mode_switching != self.preferences.scanner_mode_switching ): self.old_scan_driver = self.preferences.scan_driver self.old_scanner_mode_switching = self.preferences.scanner_mode_switching self.update_scanner_list() self.textview.set_dictionary(self.dict) self.textview.set_font_color(self.preferences.font_color) self.textview.set_background_color(self.preferences.background_color) self.textview.set_font(self.preferences.font) self.textview.set_highlight_font(self.preferences.highlight_font) self.textview.set_highlight_color(self.preferences.highlight_color) self.textview.set_highlight_background(self.preferences.background_highlight_color) def save_preferences(self,*data): save_preferences_dlg = FileChooserDialog(_("Save preferences as "), FileChooserDialog.SAVE,["cfg"],macros.user_home_path) response = save_preferences_dlg.run() if response == FileChooserDialog.ACCEPT: self.preferences.save_to_file(save_preferences_dlg.get_filename()+".cfg") self.notify_information(_("Preferences saved to ")+save_preferences_dlg.get_filename()+".cfg",0) save_preferences_dlg.destroy() def load_preferences(self,*data): load_preferences_dlg = FileChooserDialog(_("Select the image"), FileChooserDialog.OPEN,["cfg"],macros.user_home_path) response = load_preferences_dlg.run() if response == FileChooserDialog.ACCEPT: self.preferences.set_from_file(load_preferences_dlg.get_filename()) self.make_preferences_effective() self.notify_information(_("Preferences loaded from ")+load_preferences_dlg.get_filename(),0) load_preferences_dlg.destroy() def restore_preferences(self,*data): self.preferences.__init__() self.make_preferences_effective() self.notify_information(_("Preferences Restored"),0) def open_preferences_general_page(self,*data): if(self.preferences.open_configure_dialog(0)): self.make_preferences_effective() self.preferences.save_to_file(macros.preferences_file_path) def open_preferences_recognition_page(self,*data): if(self.preferences.open_configure_dialog(1)): self.make_preferences_effective() self.preferences.save_to_file(macros.preferences_file_path) def open_preferences_scanning_page(self,*data): if(self.preferences.open_configure_dialog(2)): self.make_preferences_effective() self.preferences.save_to_file(macros.preferences_file_path) def open_files(self,widget,data=None): file_chooser_open_files = FileChooserDialog(_("Select files to open"), FileChooserDialog.OPEN,macros.supported_image_formats+ macros.supported_text_formats+macros.supported_pdf_formats, macros.user_home_path) file_chooser_open_files.set_current_folder(macros.user_home_path) file_chooser_open_files.set_select_multiple(True) response = file_chooser_open_files.run() if response == FileChooserDialog.ACCEPT: file_list = file_chooser_open_files.get_filenames() file_chooser_open_files.destroy() self.open_list_of_files(file_list) else: file_chooser_open_files.destroy() def open_list_of_files(self,file_list): for item in file_list: if item.split('.')[-1] in macros.supported_image_formats: filename = item.split("/")[-1:][0] destination = "{0}{1}".format(macros.tmp_dir,filename.replace(' ','-')) destination = self.get_feesible_filename_from_filename(destination) self.add_image_to_list(item,destination,False) if item.split('.')[-1] in ["pdf","Pdf"]: self.import_images_from_pdf(item) # import_images_from_pdf is a threaded function # so stoping with one file break; if item.split('.')[-1] in macros.supported_text_formats: text = editor.read_text_from_file(item) if(len(file_list) == 1): self.textview.set_text(text) self.textview.save_file_name = file_list[0] self.textview.import_bookmarks_using_filename() else: self.textview.insert_text(text,editor.BasicTextView.AT_END) @on_thread def start_reader(self,*data): if(self.is_reading == False and self.reader_stop_pressed == False): self.is_reading = True speaker = speech.Speech() speaker.set_output_module(speaker.list_output_modules()[self.preferences.speech_module]) if(self.preferences.speech_module != -1 and len(speaker.list_voices()) > 1): speaker.set_synthesis_voice(speaker.list_voices()[self.preferences.speech_language]) speaker.set_volume(self.preferences.speech_volume) speaker.set_pitch(self.preferences.speech_pitch) while(not self.textview.is_cursor_at_end()): loop.acquire_lock() speaker.set_rate(self.preferences.speech_rate) sentence = self.textview.get_next_sentence() speaker.say(sentence) loop.release_lock() speaker.wait() if(self.reader_stop_pressed == True): speaker.close() self.is_reading = False; self.reader_stop_pressed = False break self.is_reading = False; self.reader_stop_pressed = False def stop_reader(self, *data): if(self.is_reading): self.reader_stop_pressed = True def increase_reader_speed(self,*data): if (self.preferences.speech_rate < 100): self.preferences.speech_rate = self.preferences.speech_rate + 10; def decrease_reader_speed(self,*data): if (self.preferences.speech_rate > -100): self.preferences.speech_rate = self.preferences.speech_rate - 10; def scan_using_cam(self,widget): devices = cam.Cam.get_available_devices() if(devices): ob = cam.Cam(devices[-1],1024,768) ob.connect_image_captured(self.cam_image_captured) def cam_image_captured(self,widget,filename): self.add_image_to_list(filename,"/tmp/Lios/{}".format(filename.split("/")[2]),True,False) def about(self,*data): dlg = about.AboutDialog(_("Lios"),None) dlg.set_name(_("Linux-Intelligent-Ocr-Solution")) dlg.set_program_name(_("Linux-Intelligent-Ocr-Solution")) dlg.set_version(macros.version) dlg.set_logo_from_file(macros.logo_file) dlg.set_comments(_("Lios is a free and open source software\n \ for converting print into text using a scanner or camara.\n\ It can also produce text from other sources. Such as images,\n\ Pdf, or screenshot. Program is given total accessibility \n\ for visually impaired. Lios is written in python3 and we release \n\ it under GPL3 licence. There are great many possibilities\n\ for this program. Feedback is the key to it.")) dlg.set_copyright("Copyright (C) 2011-2015 Nalin.x.Linux") dlg.set_license("GPL-V3") dlg.set_website(macros.home_page_link) dlg.set_website_label(_("Visit Home Page")) dlg.set_authors(["Nalin"]) dlg.set_documenters(["Shalini S","Sathyaseelan K"]) dlg.set_artists(["Nahar", "Manuel Eduardo Cortez Vallejo", "C V Jawahar","Naveen t.s", "Vimal Joseph","Hakkeem IT@School", "Sreejith Mathil","James Mathew","Don Marang","Vinod-Kollam", "Rizal Muttaqin","Sunny Kallada"]) dlg.run() dlg.destroy() def artha(self,*data): os.system("artha &") def quit(self,data=None,da2=None): if (self.is_updating_scanner_list): return True try: shutil.rmtree(macros.tmp_dir) except FileNotFoundError: pass #Closing scanners for item in self.scanner_objects: item.close() loop.stop_main_loop() self.preferences.save_to_file(macros.preferences_file_path) if __name__ == "__main__": linux_intelligent_ocr_solution() lios-3-2.7.2/lios/ocr/000077500000000000000000000000001345364566700144045ustar00rootroot00000000000000lios-3-2.7.2/lios/ocr/__init__.py000077500000000000000000000034251345364566700165240ustar00rootroot00000000000000#!/usr/bin/env python3 ########################################################################### # Lios - Linux-Intelligent-Ocr-Solution # Copyright (C) 2015-2016 Nalin.x.Linux GPL-3 # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ########################################################################### from lios.ocr.ocr_engine_base import OcrEngineBase from lios.ocr.ocr_engine_cuneiform import OcrEngineCuneiform from lios.ocr.ocr_engine_tesseract import OcrEngineTesseract from lios.ocr.ocr_engine_ocrad import OcrEngineOcrad from lios.ocr.ocr_engine_gocr import OcrEngineGocr from lios.ocr.ocr_engine_abbyy_finereader11 import OcrEngineAbbyyFineReader11 from lios.ocr.ocr_engine_abbyy_finereader9 import OcrEngineAbbyyFineReader9 def get_available_engines(): list = [] # Note : The engine classes should be sorted otherwise each time this function # will return same engine list in a random order. for engine_name in ["Tesseract","Cuneiform","ABBYY FineReader9","ABBYY FineReader11", "Gocr", "Ocrad" ]: for item in OcrEngineBase.__subclasses__(): if (item.name == engine_name and item.is_available()): list.append(item) import operator return list lios-3-2.7.2/lios/ocr/ocr_engine_abbyy_finereader11.py000066400000000000000000000102011345364566700225740ustar00rootroot00000000000000#!/usr/bin/python3 ########################################################################### # Lios - Linux-Intelligent-Ocr-Solution # Copyright (C) 2015-2016 Nalin.x.Linux GPL-3 # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ########################################################################### import os import subprocess from lios.ocr.ocr_engine_base import OcrEngineBase class OcrEngineAbbyyFineReader11(OcrEngineBase): name = "ABBYY FineReader11" def __init__(self,language=None): self.set_language(language) def is_available(): if ("/bin/abbyyocr11" in subprocess.getoutput("whereis abbyyocr11")): return True else: return False def ocr_image_to_text(self,file_name): os.system("convert {} /tmp/{}_for_ocr.jpg".format(file_name,file_name.split("/")[-1])) os.system("abbyyocr11 -if /tmp/{0}_for_ocr.jpg -rl {1} -f TextUnicodeDefaults -tet UTF8 -of /tmp/{1}_output.txt ".format(file_name.split("/")[-1],self.language)) print("abbyyocr11 -if /tmp/{0}_for_ocr.jpg -rl {1} -f TextUnicodeDefaults -tet UTF8 -of /tmp/{1}_output.txt ".format(file_name.split("/")[-1],self.language)) os.remove("/tmp/{0}_for_ocr.jpg".format(file_name.split("/")[-1])) try: with open("/tmp/{0}_output.txt".format(file_name.split("/")[-1]),encoding="utf-8") as file: text = file.read().strip() os.remove("/tmp/{0}_output.txt".format(file_name.split("/")[-1])) return text except: return "" def cancel(): os.system("pkill convert") os.system("pkill abbyyocr11") def get_available_languages(): langs = ["Abkhaz","Adyghe","Afrikaans","Agul","Albanian","Altaic", "Arabic (Saudi Arabia)","Armenian (Eastern, Western, Grabar)","Avar", "Aymara","Azerbaijani (Cyrillic, Latin)","Bashkir","Basque","Belarusian", "Bemba","Blackfoot","Breton","Bugotu","Bulgarian","Buryat","Catalan", "Cebuano","Chamorro","Chechen","Chinese (Simplified, Traditional)", "Chukchee","Chuvash","Corsican","Crimean Tatar","Croatian","Crow", "Czech","Dakota","Danish","Dargwa","Dungan","Dutch (Netherlands and Belgium)", "English","Eskimo (Cyrillic, Latin)","Estonian","Even","Evenki","Faroese", "Fijian","Finnish","French","Frisian","Friulian","Gagauz","Galician","Ganda", "German (Luxemburg)","German (new and old spelling)","Greek","Guarani", "Hani","Hausa","Hawaiian","Hebrew","Hungarian","Icelandic","Indonesian", "Ingush","Irish","Italian","Japanese","Jingpo","Kabardian","Kalmyk", "Karachay-balkar","Karakalpak","Kasub","Kawa","Kazakh","Khakass", "Khanty","Kikuyu","Kirghiz","Kongo","Korean","Korean (Hangul)", "Koryak","Kpelle","Kumyk","Kurdish","Lak","Latin","Latvian","Lezgi", "Lithuanian","Luba","Macedonian","Malagasy","Malay","Malinke","Maltese", "Mansi","Maori","Mari","Maya","Miao","Minangkabau","Mohawk","Moldavian", "Mongol","Mordvin","Nahuatl","Nenets","Nivkh","Nogay", "Norwegian (Nynorsk and Bokmal)","Nyanja","Occitan","Ojibway","Ossetian", "Papiamento","Polish","Portuguese (Portugal and Brazil)","Provencal", "Quechua","Rhaeto-romanic","Romanian","Romany","Rundi","Russian", "Russian (old spelling)","Rwanda","Sami (Lappish)","Samoan","Scottish Gaelic", "Selkup","Serbian (Cyrillic, Latin)","Shona","Slovak","Slovenian", "Somali","Sorbian","Sotho","Spanish","Sunda","Swahili","Swazi","Swedish", "Tabasaran","Tagalog","Tahitian","Tajik","Tatar","Thai","Tok Pisin", "Tongan","Tswana","Tun","Turkish","Turkmen (Cyrillic, Latin)","Tuvinian", "Udmurt","Uighur (Cyrillic, Latin)","Ukrainian","Uzbek (Cyrillic, Latin)", "Vietnamese","Welsh","Wolof","Xhosa","Yakut","Yiddish","Zapotec","Zulu"] return langs lios-3-2.7.2/lios/ocr/ocr_engine_abbyy_finereader9.py000066400000000000000000000101721345364566700225320ustar00rootroot00000000000000#!/usr/bin/python3 ########################################################################### # Lios - Linux-Intelligent-Ocr-Solution # Copyright (C) 2015-2016 Nalin.x.Linux GPL-3 # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ########################################################################### import os import subprocess from lios.ocr.ocr_engine_base import OcrEngineBase class OcrEngineAbbyyFineReader9(OcrEngineBase): name = "ABBYY FineReader9" def __init__(self,language=None): self.set_language(language) def is_available(): if ("/bin/abbyyocr9" in subprocess.getoutput("whereis abbyyocr9")): return True else: return False def ocr_image_to_text(self,file_name): os.system("convert {} /tmp/{}_for_ocr.jpg".format(file_name,file_name.split("/")[-1])) os.system("abbyyocr9 -if /tmp/{0}_for_ocr.jpg -rl {1} -f TextUnicodeDefaults -tet UTF8 -of /tmp/{1}_output.txt ".format(file_name.split("/")[-1],self.language)) print("abbyyocr9 -if /tmp/{0}_for_ocr.jpg -rl {1} -f TextUnicodeDefaults -tet UTF8 -of /tmp/{1}_output.txt ".format(file_name.split("/")[-1],self.language)) os.remove("/tmp/{0}_for_ocr.jpg".format(file_name.split("/")[-1])) try: with open("/tmp/{0}_output.txt".format(file_name.split("/")[-1]),encoding="utf-8") as file: text = file.read().strip() os.remove("/tmp/{0}_output.txt".format(file_name.split("/")[-1])) return text except: return "" def cancel(): os.system("pkill convert") os.system("pkill abbyyocr9") def get_available_languages(): langs = ["Abkhaz","Adyghe","Afrikaans","Agul","Albanian","Altaic", "Arabic (Saudi Arabia)","Armenian (Eastern, Western, Grabar)","Avar", "Aymara","Azerbaijani (Cyrillic, Latin)","Bashkir","Basque","Belarusian", "Bemba","Blackfoot","Breton","Bugotu","Bulgarian","Buryat","Catalan", "Cebuano","Chamorro","Chechen","Chinese (Simplified, Traditional)", "Chukchee","Chuvash","Corsican","Crimean Tatar","Croatian","Crow", "Czech","Dakota","Danish","Dargwa","Dungan","Dutch (Netherlands and Belgium)", "English","Eskimo (Cyrillic, Latin)","Estonian","Even","Evenki","Faroese", "Fijian","Finnish","French","Frisian","Friulian","Gagauz","Galician","Ganda", "German (Luxemburg)","German (new and old spelling)","Greek","Guarani", "Hani","Hausa","Hawaiian","Hebrew","Hungarian","Icelandic","Indonesian", "Ingush","Irish","Italian","Japanese","Jingpo","Kabardian","Kalmyk", "Karachay-balkar","Karakalpak","Kasub","Kawa","Kazakh","Khakass", "Khanty","Kikuyu","Kirghiz","Kongo","Korean","Korean (Hangul)", "Koryak","Kpelle","Kumyk","Kurdish","Lak","Latin","Latvian","Lezgi", "Lithuanian","Luba","Macedonian","Malagasy","Malay","Malinke","Maltese", "Mansi","Maori","Mari","Maya","Miao","Minangkabau","Mohawk","Moldavian", "Mongol","Mordvin","Nahuatl","Nenets","Nivkh","Nogay", "Norwegian (Nynorsk and Bokmal)","Nyanja","Occitan","Ojibway","Ossetian", "Papiamento","Polish","Portuguese (Portugal and Brazil)","Provencal", "Quechua","Rhaeto-romanic","Romanian","Romany","Rundi","Russian", "Russian (old spelling)","Rwanda","Sami (Lappish)","Samoan","Scottish Gaelic", "Selkup","Serbian (Cyrillic, Latin)","Shona","Slovak","Slovenian", "Somali","Sorbian","Sotho","Spanish","Sunda","Swahili","Swazi","Swedish", "Tabasaran","Tagalog","Tahitian","Tajik","Tatar","Thai","Tok Pisin", "Tongan","Tswana","Tun","Turkish","Turkmen (Cyrillic, Latin)","Tuvinian", "Udmurt","Uighur (Cyrillic, Latin)","Ukrainian","Uzbek (Cyrillic, Latin)", "Vietnamese","Welsh","Wolof","Xhosa","Yakut","Yiddish","Zapotec","Zulu"] return langs lios-3-2.7.2/lios/ocr/ocr_engine_base.py000066400000000000000000000035131345364566700200620ustar00rootroot00000000000000#! /usr/bin/python3 ########################################################################### # Lios - Linux-Intelligent-Ocr-Solution # Copyright (C) 2015-2016 Nalin.x.Linux GPL-3 # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ########################################################################### import abc import multiprocessing class OcrEngineBase(metaclass=abc.ABCMeta): def __init__(self,language=None): self.language = language @staticmethod @abc.abstractmethod def get_available_languages(): return @abc.abstractmethod def ocr_image_to_text(self,image_file_name): pass def cancel(): pass def set_language(self,language): if language in self.__class__.get_available_languages(): self.language = language return True else: return False def ocr_image_to_text_with_multiprocessing(self,image_file_name): parent_conn, child_conn = multiprocessing.Pipe() p = multiprocessing.Process(target=(lambda parent_conn, child_conn, image_file_name : child_conn.send(self.ocr_image_to_text(image_file_name))), args=(parent_conn, child_conn,image_file_name)) p.start() p.join() return parent_conn.recv(); @staticmethod @abc.abstractmethod def is_available(): return lios-3-2.7.2/lios/ocr/ocr_engine_cuneiform.py000066400000000000000000000044551345364566700211450ustar00rootroot00000000000000#!/usr/bin/python3 ########################################################################### # Lios - Linux-Intelligent-Ocr-Solution # Copyright (C) 2015-2016 Nalin.x.Linux GPL-3 # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ########################################################################### import os import re import subprocess from lios.ocr.ocr_engine_base import OcrEngineBase LANGUAGES_LINE_PREFIX = "Supported languages: " LANGUAGES_SPLIT_RE = re.compile("[^a-z]") class OcrEngineCuneiform(OcrEngineBase): name = "Cuneiform" def __init__(self,language=None): self.set_language(language) def is_available(): if ("/bin/cuneiform" in subprocess.getoutput("whereis cuneiform")): return True else: return False def ocr_image_to_text(self,file_name): os.system("convert {} /tmp/{}_for_ocr.png".format(file_name,file_name.split("/")[-1])) os.system("cuneiform -f text -l {0} -o /tmp/{1}_output.txt /tmp/{1}_for_ocr.png".format(self.language,file_name.split("/")[-1])) os.remove("/tmp/{0}_for_ocr.png".format(file_name.split("/")[-1])) try: with open("/tmp/{0}_output.txt".format(file_name.split("/")[-1]),encoding="utf-8") as file: text = file.read().strip() os.remove("/tmp/{0}_output.txt".format(file_name.split("/")[-1])) return text except: return "" def cancel(): os.system("pkill convert") os.system("pkill cuneiform") def get_available_languages(): langs = [] for line in subprocess.getoutput("cuneiform -l").split("\n"): if line.startswith(LANGUAGES_LINE_PREFIX): line = line[len(LANGUAGES_LINE_PREFIX):] for language in LANGUAGES_SPLIT_RE.split(line): if language != "": langs.append(language) return langs lios-3-2.7.2/lios/ocr/ocr_engine_gocr.py000066400000000000000000000036211345364566700201020ustar00rootroot00000000000000#!/usr/bin/python3 ########################################################################### # Lios - Linux-Intelligent-Ocr-Solution # Copyright (C) 2015-2016 Nalin.x.Linux GPL-3 # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ########################################################################### import os import subprocess from lios.ocr.ocr_engine_base import OcrEngineBase class OcrEngineGocr(OcrEngineBase): name = "Gocr" def __init__(self,language=None): self.set_language(language) def is_available(): if ("/bin/gocr" in subprocess.getoutput("whereis gocr")): return True else: return False def ocr_image_to_text(self,file_name): os.system("convert {} /tmp/{}_for_ocr.pnm".format(file_name,file_name.split("/")[-1])) os.system("gocr -i /tmp/{0}_for_ocr.pnm -o /tmp/{0}_output.txt ".format(file_name.split("/")[-1])) os.remove("/tmp/{0}_for_ocr.pnm".format(file_name.split("/")[-1])) try: with open("/tmp/{0}_output.txt".format(file_name.split("/")[-1]),encoding="utf-8") as file: text = file.read().strip() os.remove("/tmp/{0}_output.txt".format(file_name.split("/")[-1])) return text except: return "" def cancel(): os.system("pkill convert") os.system("pkill gocr") def get_available_languages(): langs = ["eng"] return langs lios-3-2.7.2/lios/ocr/ocr_engine_ocrad.py000066400000000000000000000036511345364566700202430ustar00rootroot00000000000000#!/usr/bin/python3 ########################################################################### # Lios - Linux-Intelligent-Ocr-Solution # Copyright (C) 2015-2016 Nalin.x.Linux GPL-3 # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ########################################################################### import os import subprocess from lios.ocr.ocr_engine_base import OcrEngineBase class OcrEngineOcrad(OcrEngineBase): name = "Ocrad" def __init__(self,language=None): self.set_language(language) def is_available(): if ("/bin/ocrad" in subprocess.getoutput("whereis ocrad")): return True else: return False def ocr_image_to_text(self,file_name): os.system("convert {} /tmp/{}_for_ocr.pnm".format(file_name,file_name.split("/")[-1])) os.system("ocrad /tmp/{0}_for_ocr.pnm -l -c iso-8859-9 -o /tmp/{0}_output.txt".format(file_name.split("/")[-1])) os.remove("/tmp/{0}_for_ocr.pnm".format(file_name.split("/")[-1])) try: with open("/tmp/{0}_output.txt".format(file_name.split("/")[-1]),encoding="iso-8859-9") as file: text = file.read().strip() os.remove("/tmp/{0}_output.txt".format(file_name.split("/")[-1])) return text except: return "" def cancel(): os.system("pkill convert") os.system("pkill ocrad") def get_available_languages(): langs = ["eng"] return langs lios-3-2.7.2/lios/ocr/ocr_engine_tesseract.py000066400000000000000000000073201345364566700211450ustar00rootroot00000000000000#!/usr/bin/python3 ########################################################################### # Lios - Linux-Intelligent-Ocr-Solution # Copyright (C) 2015-2016 Nalin.x.Linux GPL-3 # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ########################################################################### import os import subprocess from lios.ocr.ocr_engine_base import OcrEngineBase TESSDATA_POSSIBLE_PATHS = [ "/usr/share/tesseract-ocr/tessdata", "/usr/share/tesseract/tessdata", "/usr/share/tessdata", "/usr/local/share/tesseract-ocr/tessdata", "/usr/local/share/tesseract/tessdata", "/usr/local/share/tessdata", "/usr/share/tesseract-ocr/4.00/tessdata" ] TESSDATA_EXTENSION = ".traineddata" class OcrEngineTesseract(OcrEngineBase): name = "Tesseract" def __init__(self,language=None): self.set_language(language) def is_available(): if ("/bin/tesseract" in subprocess.getoutput("whereis tesseract")): return True else: return False def is_training_executables_available(): for executable_name in ["combine_tessdata","unicharset_extractor","shapeclustering","mftraining","cntraining","text2image"]: if not ("/bin/"+executable_name in subprocess.getoutput("whereis {0}".format(executable_name))): return False return True def ocr_image_to_text(self,file_name): os.system("convert {} -background white -flatten +matte /tmp/{}_for_ocr.png".format(file_name,file_name.split("/")[-1])) os.system("tesseract /tmp/{0}_for_ocr.png /tmp/{0}_output -l {1}".format(file_name.split("/")[-1],self.language)) os.remove("/tmp/{0}_for_ocr.png".format(file_name.split("/")[-1])) try: with open("/tmp/{0}_output.txt".format(file_name.split("/")[-1]),encoding="utf-8") as file: text = file.read().strip() os.remove("/tmp/{0}_output.txt".format(file_name.split("/")[-1])) return text except: return "" def cancel(): os.system("pkill convert") os.system("pkill tesseract") def get_available_languages_in_dirpath(dirpath): langs = [] if os.access(dirpath, os.R_OK): for filename in os.listdir(dirpath): if filename.lower().endswith(TESSDATA_EXTENSION): lang = filename[:(-1 * len(TESSDATA_EXTENSION))] langs.append(lang) return langs def get_available_languages(): langs = [] for dirpath in TESSDATA_POSSIBLE_PATHS[::-1]: if (os.path.isfile(dirpath+"/configs/box.train")): for item in OcrEngineTesseract.get_available_languages_in_dirpath(dirpath): langs.append(item) return sorted(langs) return langs def get_all_available_dirs(): result = [] for root, dirs, files in os.walk("/"): if "tessdata" in dirs: dir = os.path.join(root, "tessdata") if (os.path.isfile(dir+"/configs/box.train")): result.append(dir) # Sorting according to possible list # [::-1] is used to reverse for path in TESSDATA_POSSIBLE_PATHS[::-1]: if (path in result): result.insert(0, result.pop(result.index(path))) return result def get_available_dirs(): dir_list = []; for path in TESSDATA_POSSIBLE_PATHS: if (os.path.exists(path)): if (os.path.isfile(path+"/configs/box.train")): dir_list.append(path); return dir_list; lios-3-2.7.2/lios/preferences.py000066400000000000000000000512601345364566700165000ustar00rootroot00000000000000#!/usr/bin/env python3 ########################################################################### # Lios - Linux-Intelligent-Ocr-Solution # Copyright (C) 2011-2015 Nalin.x.Linux GPL-3 # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ########################################################################### import configparser import shutil from lios.ui.gtk import widget from lios.ui.gtk import containers from lios.ui.gtk import loop from lios.ui.gtk import dialog from lios import speech from lios import localization _ = localization._ class lios_preferences: def __init__(self): #Setting Default Values self.font="Georgia 14";self.highlight_font="Georgia 14"; self.background_color="#000";self.font_color="#fff"; self.highlight_color="#1572ffff0000"; self.background_highlight_color="#00000bacffff"; self.speech_module=0;self.speech_language=10; self.speech_rate=0;self.speech_pitch=0;self.speech_volume=100; self.time_between_repeated_scanning=0;self.scan_resolution=300; self.scan_driver=1;self.scanner_cache_calibration=0; self.scan_brightness=50;self.scan_area=0;self.insert_position=2; self.ocr_engine=0;self.language=0;self.mode_of_rotation=0; self.number_of_pages_to_scan=100;self.give_page_number = 1; self.page_numbering_type=0;self.starting_page_number=1; self.scanner_mode_switching=0; self.run_text_cleaner=0;self.rotation_angle=00; def set_avalable_scanner_drivers(self,list): self.available_scanner_drivers = list def set_avalable_ocr_engines(self,list): self.available_ocr_engine_list = list # FUNCTION TO Read PREFERENCES # def set_from_file(self,filename): config = configparser.ConfigParser() if config.read(filename) != []: try: self.time_between_repeated_scanning=int(config.get('cfg',"time_between_repeated_scanning")) self.scan_resolution=int(config.get('cfg',"scan_resolution")) self.scan_brightness=int(config.get('cfg',"scan_brightness")) self.ocr_engine=int(config.get('cfg',"ocr_engine")) self.scan_area=int(config.get('cfg',"scan_area")) self.scan_driver=int(config.get('cfg',"scan_driver")) self.insert_position=int(config.get('cfg',"insert_position")) self.language=int(config.get('cfg',"language")) self.speech_module=int(config.get('cfg',"speech_module")) self.speech_language=int(config.get('cfg',"speech_language")) self.speech_rate=int(config.get('cfg',"speech_rate")) self.speech_volume=int(config.get('cfg',"speech_volume")) self.speech_pitch=int(config.get('cfg',"speech_pitch")) self.number_of_pages_to_scan=int(config.get('cfg',"number_of_pages_to_scan"))#pages self.mode_of_rotation = int(config.get('cfg',"mode_of_rotation")) self.rotation_angle = int(config.get('cfg',"rotation_angle")) self.give_page_number=int(config.get('cfg',"give_page_number")) self.page_numbering_type=int(config.get('cfg',"numbering_type")) self.scanner_mode_switching=int(config.get('cfg',"scanner_mode_switching")) self.run_text_cleaner=int(config.get('cfg',"run_text_cleaner")) self.scanner_cache_calibration=int(config.get('cfg',"scanner_cache_calibration")) self.starting_page_number=int(config.get('cfg',"starting_page_number")) self.background_color=config.get('cfg',"background_color") self.font_color=config.get('cfg',"font_color") self.highlight_color=config.get('cfg',"highlight_color") self.background_highlight_color=config.get('cfg',"highlight_background_color") self.font=config.get('cfg',"font") self.highlight_font=config.get('cfg',"highlight_font") self.require_scanner_refresh = True except: self.__init__() else: self.__init__() def save_to_file(self,filename): #Removing old configuration file try: os.remove(filename) except: pass config = configparser.ConfigParser() config.add_section('cfg') config.set('cfg',"time_between_repeated_scanning",str(self.time_between_repeated_scanning)) config.set('cfg',"scan_resolution",str(self.scan_resolution)) config.set('cfg',"scan_brightness",str(self.scan_brightness)) config.set('cfg',"ocr_engine",str(self.ocr_engine)) config.set('cfg',"insert_position",str(self.insert_position)) config.set('cfg',"scan_area",str(self.scan_area)) config.set('cfg',"scan_driver",str(self.scan_driver)) config.set('cfg',"language",str(self.language)) config.set('cfg',"speech_module",str(self.speech_module)) config.set('cfg',"speech_language",str(self.speech_language)) config.set('cfg',"speech_pitch",str(self.speech_pitch)) config.set('cfg',"speech_volume",str(self.speech_volume)) config.set('cfg',"speech_rate",str(self.speech_rate)) config.set('cfg',"number_of_pages_to_scan",str(self.number_of_pages_to_scan)) config.set('cfg',"mode_of_rotation",str(self.mode_of_rotation)) config.set('cfg',"rotation_angle",str(self.rotation_angle)) config.set('cfg',"give_page_number",str(self.give_page_number)) config.set('cfg',"numbering_type",str(self.page_numbering_type)) config.set('cfg',"scanner_mode_switching",str(self.scanner_mode_switching)) config.set('cfg',"run_text_cleaner",str(self.run_text_cleaner)) config.set('cfg',"scanner_cache_calibration",str(self.scanner_cache_calibration)) config.set('cfg',"starting_page_number",str(self.starting_page_number)) config.set('cfg',"background_color",str(self.background_color)) config.set('cfg',"font_color",str(self.font_color)) config.set('cfg',"highlight_color",str(self.highlight_color)) config.set('cfg',"highlight_background_color",str(self.background_highlight_color)) config.set('cfg',"font",str(self.font)) config.set('cfg',"highlight_font",str(self.highlight_font)) with open(filename, 'w') as configfile: config.write(configfile) def update_page_number(self): loop.acquire_lock() if (self.page_numbering_type == 0): self.starting_page_number = self.starting_page_number + 1 else: self.starting_page_number = self.starting_page_number + 2 loop.release_lock() def get_page_number_as_string(self): if (self.page_numbering_type == 0): return ("{0}".format(self.starting_page_number)) else: return ("{0}-{1}".format(self.starting_page_number,self.starting_page_number + 1)) #Function for manipulating preferences def open_configure_dialog(self,page=0): def change_engine(*data): index_engine = combobox_engine.get_active() combobox_language.clear() for item in self.available_ocr_engine_list[index_engine][1]: combobox_language.add_item(item) combobox_language.set_active(self.language) def change_speech_module(*data): index_engine = combobox_speech_module.get_active() combobox_speech_language.clear() test = speech.Speech() list = test.list_output_modules() test.set_output_module(list[index_engine]) for item in test.list_voices(): combobox_speech_language.add_item(item) combobox_speech_language.set_active(self.speech_language) def change_mode_of_rotation(*data): if(combobox_mode_of_rotation.get_active() == 2): combobox_angle.show() self.label_angle.show() else: combobox_angle.hide() self.label_angle.hide() self.require_scanner_refresh = False #Notebook notebook = containers.NoteBook() notebook.show_all() #GENERAL - PAGE ######### label_font = widget.Label(_("Font")) fontbutton_font = widget.FontButton() fontbutton_font.set_font_name(self.font) label_font.set_mnemonic_widget(fontbutton_font) label_font_color = widget.Label(_("Font Color")) colorbutton_font = widget.ColorButton() colorbutton_font.set_color_from_string(self.font_color) label_font_color.set_mnemonic_widget(colorbutton_font) label_background_color = widget.Label(_("Background Color")) colorbutton_background = widget.ColorButton() colorbutton_background.set_color_from_string(self.background_color) label_background_color.set_mnemonic_widget(colorbutton_background) label_highlight_font = widget.Label(_("Highlight Font")) fontbutton_highlight_font = widget.FontButton() fontbutton_highlight_font.set_font_name(self.highlight_font) label_highlight_font.set_mnemonic_widget(fontbutton_highlight_font) label_highlight_color = widget.Label(_("Highlight Color")) colorbutton_highlight = widget.ColorButton() colorbutton_highlight.set_color_from_string(self.highlight_color) label_highlight_color.set_mnemonic_widget(colorbutton_highlight) label_highlight_background = widget.Label(_("Highlight Background")) colorbutton_highlight_background = widget.ColorButton() colorbutton_highlight_background.set_color_from_string(self.background_highlight_color) label_highlight_background.set_mnemonic_widget(colorbutton_highlight_background) label_speech_module = widget.Label(_("Speech-Module")) combobox_speech_module = widget.ComboBox() for item in speech.Speech().list_output_modules(): combobox_speech_module.add_item(item) combobox_speech_module.connect_change_callback_function(change_speech_module) label_speech_module.set_mnemonic_widget(combobox_speech_module) label_speech_language = widget.Label(_("Speech-Language")) combobox_speech_language = widget.ComboBox() combobox_speech_module.set_active(self.speech_module) combobox_speech_language.set_active(self.speech_language) label_speech_language.set_mnemonic_widget(combobox_speech_language) label_speech_rate = widget.Label(_("Speech-Rate")) spin_speech_rate = widget.SpinButton(self.speech_rate,-100,100,1,10,0) label_speech_rate.set_mnemonic_widget(spin_speech_rate) label_speech_volume = widget.Label(_("Speech-Volume")) spin_speech_volume = widget.SpinButton(self.speech_volume,-100,100,1,10,0) label_speech_volume.set_mnemonic_widget(spin_speech_volume) label_speech_pitch = widget.Label(_("Speech-Pitch")) spin_speech_pitch = widget.SpinButton(self.speech_pitch,-100,100,1,10,0) label_speech_pitch.set_mnemonic_widget(spin_speech_pitch) grid_general = containers.Grid() grid_general.add_widgets( [(label_font,1,1),(fontbutton_font,1,1),containers.Grid.NEW_ROW, (label_font_color,1,1),(colorbutton_font,1,1),containers.Grid.NEW_ROW, (label_background_color,1,1),(colorbutton_background,1,1),containers.Grid.NEW_ROW, (label_highlight_font,1,1),(fontbutton_highlight_font,1,1),containers.Grid.NEW_ROW, (label_highlight_color,1,1),(colorbutton_highlight,1,1),containers.Grid.NEW_ROW, (label_highlight_background,1,1),(colorbutton_highlight_background,1,1),containers.Grid.NEW_ROW, (label_speech_module,1,1),(combobox_speech_module,1,1),containers.Grid.NEW_ROW, (label_speech_language,1,1),(combobox_speech_language,1,1),containers.Grid.NEW_ROW, (label_speech_rate,1,1),(spin_speech_rate,1,1),containers.Grid.NEW_ROW, (label_speech_pitch,1,1),(spin_speech_pitch,1,1),containers.Grid.NEW_ROW, (label_speech_volume,1,1),(spin_speech_volume,1,1)]) notebook.add_page(_("General"),grid_general) grid_general.show_all() #RECOGNITION - PAGE ######## #Engine label_engine = widget.Label(_("Engine")) combobox_engine = widget.ComboBox() combobox_engine.connect_change_callback_function(change_engine) label_engine.set_mnemonic_widget(combobox_engine) for item in self.available_ocr_engine_list: combobox_engine.add_item(item[0]) #Language label_language = widget.Label(_("Language")) combobox_language = widget.ComboBox() label_language.set_mnemonic_widget(combobox_language) #setting current engine - This can't be done before creating language combobox combobox_engine.set_active(self.ocr_engine) combobox_language.set_active(self.language) #Run text cleaner checkbutton_run_text_cleaner = widget.CheckButton(_("Run Text Cleaner")) checkbutton_run_text_cleaner.set_active(self.run_text_cleaner) #insert_position label_insert_position = widget.Label(_("Insert Position")) combobox_insert_position = widget.ComboBox() combobox_insert_position.add_item(_("Start")) combobox_insert_position.add_item(_("Cursor")) combobox_insert_position.add_item(_("End")) combobox_insert_position.set_active(self.insert_position) label_insert_position.set_mnemonic_widget(combobox_insert_position) #Seperator seperator_1 = widget.Separator() #Mode of Rotation label_mode_of_rotation = widget.Label(_("Mode Of Rotation")) combobox_mode_of_rotation = widget.ComboBox() combobox_mode_of_rotation.add_item(_("Full Automatic")) combobox_mode_of_rotation.add_item(_("Partial Automatic")) combobox_mode_of_rotation.add_item(_("Manual")) combobox_mode_of_rotation.connect_change_callback_function(change_mode_of_rotation) label_mode_of_rotation.set_mnemonic_widget(combobox_mode_of_rotation) #Angle self.label_angle = widget.Label(_("Angle")) combobox_angle = widget.ComboBox() combobox_angle.add_item(_("00")) combobox_angle.add_item(_("90")) combobox_angle.add_item(_("180")) combobox_angle.add_item(_("270")) self.label_angle.set_mnemonic_widget(combobox_angle) #Seperator 2 seperator_2 = widget.Separator() #Give page number checkbutton_give_page_number = widget.CheckButton(_("Give Page Number")) checkbutton_give_page_number.set_active(self.give_page_number) #Page-Numbering label_numbering_type = widget.Label(_("Page Numbering Type")) combobox_numbering_type = widget.ComboBox() combobox_numbering_type.add_item(_("Single Page")) combobox_numbering_type.add_item(_("Double Page")) combobox_numbering_type.set_active(self.page_numbering_type) label_numbering_type.set_mnemonic_widget(combobox_numbering_type) #Starting Page Number label_starting_page_number = widget.Label(_("Starting Page Number")) spin_starting_page_number = widget.SpinButton(0,0,100000,1,5,0) spin_starting_page_number.set_value(self.starting_page_number) label_starting_page_number.set_mnemonic_widget(spin_starting_page_number) grid_recognition = containers.Grid() grid_recognition.add_widgets([ (label_engine,1,1),(combobox_engine,1,1),containers.Grid.NEW_ROW, (label_language,1,1),(combobox_language,1,1),containers.Grid.NEW_ROW, (checkbutton_run_text_cleaner,1,1),containers.Grid.NEW_ROW, (label_insert_position,1,1),(combobox_insert_position,1,1),containers.Grid.NEW_ROW, (seperator_1,2,1),containers.Grid.NEW_ROW, (label_mode_of_rotation,1,1),(combobox_mode_of_rotation,1,1),containers.Grid.NEW_ROW, (self.label_angle,1,1),(combobox_angle,1,1),containers.Grid.NEW_ROW, (seperator_2,2,1),containers.Grid.NEW_ROW, (checkbutton_give_page_number,1,1),containers.Grid.NEW_ROW, (label_numbering_type,1,1), (combobox_numbering_type,1,1),containers.Grid.NEW_ROW, (label_starting_page_number,1,1), (spin_starting_page_number,1,1)]) notebook.add_page(_("Recognition"),grid_recognition) grid_recognition.show_all() #setting current mode of rotation - This can't be done before creating angle combobox #also it should be here because the show_all function of grid will make angle combobox show again combobox_mode_of_rotation.set_active(self.mode_of_rotation) combobox_angle.set_active(self.rotation_angle) #SCANNING - PAGE ############## label_resolution = widget.Label(_("Resolution")) spin_resolution = widget.SpinButton(300,100,1200,1,5,0) spin_resolution.set_value(self.scan_resolution) label_resolution.set_mnemonic_widget(spin_resolution) label_brightness = widget.Label(_("Brightness")) spin_brightness = widget.SpinButton(50,0,100,1,5,0) spin_brightness.set_value(self.scan_brightness) label_brightness.set_mnemonic_widget(spin_brightness) label_scan_area = widget.Label(_("Scan Area")) combobox_scan_area = widget.ComboBox() label_scan_area.set_mnemonic_widget(combobox_scan_area) combobox_scan_area.add_item(_("Full Scan Area")) combobox_scan_area.add_item(_("Three Quarters")) combobox_scan_area.add_item(_("Two Quarters")) combobox_scan_area.add_item(_("One Quarters")) combobox_scan_area.set_active(self.scan_area) label_scan_driver = widget.Label(_("Driver")) combobox_scan_driver = widget.ComboBox() label_scan_driver.set_mnemonic_widget(combobox_scan_driver) for item in self.available_scanner_drivers: combobox_scan_driver.add_item(item) combobox_scan_driver.set_active(self.scan_driver) sparator_3 = widget.Separator() label_number_of_pages_to_scan = widget.Label(_("Number of Pages to Scan")) spin_number_of_pages_to_scan = widget.SpinButton(10,2,100,1,5,0) spin_number_of_pages_to_scan.set_value(self.number_of_pages_to_scan) label_number_of_pages_to_scan.set_mnemonic_widget(spin_number_of_pages_to_scan) label_time_bitween_repeted_scanning = widget.Label(_("Time Bitween Repeted Scanning")) spin_time_bitween_repeted_scanning = widget.SpinButton(0,0,30,1,5,0) spin_time_bitween_repeted_scanning.set_value(self.time_between_repeated_scanning) label_time_bitween_repeted_scanning.set_mnemonic_widget(spin_time_bitween_repeted_scanning) sparator_4 = widget.Separator() checkbutton_scan_mode_switching = widget.CheckButton(_("Change to binary or lineart if possible")) checkbutton_scan_mode_switching.set_active(self.scanner_mode_switching) checkbutton_scanner_cache_calibration = widget.CheckButton(_("Cache Calibration")) checkbutton_scanner_cache_calibration.set_active(self.scanner_cache_calibration) grid_scanning = containers.Grid() grid_scanning.add_widgets([ (label_resolution,1,1),(spin_resolution,1,1),containers.Grid.NEW_ROW, (label_brightness,1,1),(spin_brightness,1,1),containers.Grid.NEW_ROW, (label_scan_area,1,1),(combobox_scan_area,1,1),containers.Grid.NEW_ROW, (label_scan_driver,1,1),(combobox_scan_driver,1,1),containers.Grid.NEW_ROW, (sparator_3,2,1),containers.Grid.NEW_ROW, (label_number_of_pages_to_scan,1,1),(spin_number_of_pages_to_scan,1,1),containers.Grid.NEW_ROW, (label_time_bitween_repeted_scanning,1,1),(spin_time_bitween_repeted_scanning,1,1),containers.Grid.NEW_ROW, (sparator_4,2,1),containers.Grid.NEW_ROW, (checkbutton_scan_mode_switching,2,1),containers.Grid.NEW_ROW, (checkbutton_scanner_cache_calibration,2,1)]) notebook.add_page(_("Scanning"),grid_scanning) grid_scanning.show_all() #Setting page notebook.set_current_page(page) dlg = dialog.Dialog(_("Lios Preferences"),(_("Apply"),dialog.Dialog.BUTTON_ID_1,_("Close"),dialog.Dialog.BUTTON_ID_2)) dlg.add_widget(notebook) if (dlg.run()==True): self.font=fontbutton_font.get_font_name(); self.font_color=colorbutton_font.get_color_as_string() self.background_color=colorbutton_background.get_color_as_string() self.highlight_font=fontbutton_highlight_font.get_font_name(); self.highlight_color=colorbutton_highlight.get_color_as_string() self.background_highlight_color=colorbutton_highlight_background.get_color_as_string() self.ocr_engine=combobox_engine.get_active() self.language=combobox_language.get_active() self.speech_module=combobox_speech_module.get_active() self.speech_language=combobox_speech_language.get_active() self.speech_rate=spin_speech_rate.get_value() self.speech_pitch=spin_speech_pitch.get_value() self.speech_volume=spin_speech_volume.get_value() self.insert_position=combobox_insert_position.get_active(); self.mode_of_rotation=combobox_mode_of_rotation.get_active() self.rotation_angle = combobox_angle.get_active() self.give_page_number=int(checkbutton_give_page_number.get_active()) self.page_numbering_type=combobox_numbering_type.get_active(); self.starting_page_number=spin_starting_page_number.get_value_as_int(); self.scan_resolution = spin_resolution.get_value_as_int(); self.scan_brightness=spin_brightness.get_value_as_int(); self.scan_area=combobox_scan_area.get_active(); self.scan_driver=combobox_scan_driver.get_active(); self.number_of_pages_to_scan=spin_number_of_pages_to_scan.get_value_as_int(); self.time_between_repeated_scanning=spin_time_bitween_repeted_scanning.get_value_as_int(); self.scanner_mode_switching=int(checkbutton_scan_mode_switching.get_active()) self.run_text_cleaner=int(checkbutton_run_text_cleaner.get_active()) self.scanner_cache_calibration=int(checkbutton_scanner_cache_calibration.get_active()) dlg.destroy() return True dlg.destroy() return False if "__main__" == __name__: a = lios_preferences() a.set_avalable_ocr_engines([]) a.set_avalable_scanner_drivers([]) a.open_configure_dialog() a.open_configure_dialog() loop.start_main_loop() lios-3-2.7.2/lios/scanner/000077500000000000000000000000001345364566700152525ustar00rootroot00000000000000lios-3-2.7.2/lios/scanner/__init__.py000066400000000000000000000023501345364566700173630ustar00rootroot00000000000000#!/usr/bin/env python3 ########################################################################### # Lios - Linux-Intelligent-Ocr-Solution # Copyright (C) 2015-2016 Nalin.x.Linux GPL-3 # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ########################################################################### #!/usr/bin/env python3 from lios.scanner.driver_base import DriverBase from lios.scanner.sane_driver import DriverSane from lios.scanner.scanimage_driver import DriverScanimage def get_available_drivers(): list = [] for item in DriverBase.__subclasses__(): if item.is_available(): list.append(item) return list lios-3-2.7.2/lios/scanner/driver_base.py000066400000000000000000000053721345364566700201200ustar00rootroot00000000000000#!/usr/bin/env python3 ########################################################################### # Lios - Linux-Intelligent-Ocr-Solution # Copyright (C) 2011-2014 Nalin.x.Linux GPL-3 # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ########################################################################### import abc class DriverBase(metaclass=abc.ABCMeta): SCAN_AREA_FULL, SCAN_AREA_THREE_QUARTER, SCAN_AREA_HALF,\ SCAN_AREA_QUARTER = range(4) @abc.abstractmethod def __init__(self,device,scanner_mode_switching,resolution=300,brightness=40,scan_area=0): self.set_resolution(resolution); self.set_brightness(brightness); self.set_scan_area(scan_area); self.brightness_multiplier = 1 self.brightness_offset = 0 if (scanner_mode_switching): modes_list = self.get_available_scan_modes() if "Binary" in modes_list: self.set_scan_mode("Binary") if "Lineart" in modes_list: self.set_scan_mode("Lineart") @abc.abstractmethod def scan(self,filename,resolution=-1,brightness=-1,scan_area=-1): if (brightness !=-1 ): brightness = (brightness*self.brightness_multiplier)+self.brightness_offset self.set_brightness(brightness) if (resolution !=-1 ): self.set_resolution(resolution); if (scan_area !=-1 ): self.set_scan_area(scan_area); @abc.abstractmethod def get_resolution(self): return @abc.abstractmethod def set_resolution(self,resolution): return @abc.abstractmethod def get_brightness(self): return @abc.abstractmethod def set_brightness(self,brightness): return @abc.abstractmethod def set_scan_area(self,scan_area): return @abc.abstractmethod def get_scan_area(self): return @abc.abstractmethod def set_scan_mode(self,scan_mode): return @abc.abstractmethod def get_scan_mode(self,scan_mode): return @abc.abstractmethod def get_available_scan_modes(self): return; @abc.abstractmethod def check_brightness_support(self): return @staticmethod @abc.abstractmethod def get_available_devices(): return @staticmethod @abc.abstractmethod def is_available(): return @abc.abstractmethod def cancel(self): return @abc.abstractmethod def close(self): return lios-3-2.7.2/lios/scanner/sane_driver.py000066400000000000000000000120161345364566700201250ustar00rootroot00000000000000#!/usr/bin/env python3 ########################################################################### # Lios - Linux-Intelligent-Ocr-Solution # Copyright (C) 2011-2014 Nalin.x.Linux GPL-3 # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ########################################################################### try: import sane available = True except: available = False from lios.scanner.driver_base import DriverBase import os class DriverSane(DriverBase): name = "Sane" def __init__(self,device,scanner_mode_switching,resolution=300,brightness=40,scan_area=0): sane_version = sane.init() self.device_name = device[2]; try: self.scanner = sane.open(device[0]) except: print("####sane error!") else: #Brightness and Threshold self.light_parameter_state = False options = self.get_scanner_option ('brightness') if options: self.light_parameter_state = True self.light_parameter = "brightness" try: self.min = options[-1][0] self.max = options[-1][1] except: self.min = -100 self.max = 100 options = self.get_scanner_option ('threshold') if options: self.light_parameter_state = True self.light_parameter = "threshold" try: self.min = options[-1][0] self.max = options[-1][1] except: self.min = 0 self.max = 255 #Calling super constructor for inetialising brightness resolution and scan area super(DriverSane, self).__init__(scanner_mode_switching,device,resolution,\ brightness,scan_area) if(not scanner_mode_switching): self.set_scan_mode("Color") self.brightness_multiplier = (self.max - self.min)/100 self.brightness_offset = self.min def get_scanner_option (self,name): options = self.scanner.get_options() for option in options: if option[1] == name: return option return False def scan(self,file_name,brightness=-1,resolution=-1,region=-1): super(DriverSane, self).scan(file_name,brightness,resolution,region) pil_image = self.scanner.scan() pil_image.save("/tmp/sane_temp.png") os.system("convert /tmp/sane_temp.png {}".format(file_name)) def check_brightness_support(self): return self.light_parameter_state def get_resolution(self): return self.scanner.resolution; def set_resolution(self,resolution): self.scanner.resolution = resolution def get_brightness(self): if (self.check_brightness_support()): if self.light_parameter == "brightness": return self.scanner.brightness if self.light_parameter == "threshold": return self.scanner.threshold else: return -1; def set_brightness(self,brightness): if (self.check_brightness_support()): print("Scanner Max = {0}, Scanner Min = {1}, Corected Value {2}". format(self.max,self.min,brightness)) if self.light_parameter == "brightness": try: self.scanner.brightness = brightness except AttributeError: print ("ooh") if self.light_parameter == "threshold": try: self.scanner.threshold = brightness except AttributeError: print ("Ohhh") def set_scan_area(self,scan_area): #X Axis for scan Area option = self.get_scanner_option('br-x') if option: self.scanner.br_x = option[8][1] #Y Axis for scan Area option = self.get_scanner_option('br-y') if option: if scan_area == self.SCAN_AREA_FULL: self.scanner.br_y = option[8][1] elif scan_area == self.SCAN_AREA_THREE_QUARTER: self.scanner.br_y = 3*(option[8][1]/4) elif scan_area == self.SCAN_AREA_HALF: self.scanner.br_y = option[8][1]/2 else: self.scanner.br_y = option[8][1]/4 return True else: return False def get_scan_area(self): return self.scanner.br_y def set_scan_mode(self,scan_mode): self.scanner.mode = scan_mode def get_scan_mode(self,scan_mode): return self.scanner.mode def get_available_scan_modes(self): option = self.get_scanner_option("mode") if option: return option[-1:][0] else: return [] #static method def get_available_devices(): sane.init() list = [] for device in sane.get_devices(): if "scanner" in device[3]: list.append(device) return list def is_available(): return available def cancel(self): self.scanner.cancel() def close(self): self.scanner.close() if __name__ == "__main__": scanners = [] scanner_list = DriverSane.get_available_devices() print(scanner_list) for device in scanner_list: scanners.append(DriverSane(device)) scanners[0].scan("Hello.png") lios-3-2.7.2/lios/scanner/scanimage_driver.py000066400000000000000000000107161345364566700211330ustar00rootroot00000000000000#!/usr/bin/env python3 ########################################################################### # Lios - Linux-Intelligent-Ocr-Solution # Copyright (C) 2011-2014 Nalin.x.Linux GPL-3 # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ########################################################################### import os import subprocess from lios.scanner.driver_base import DriverBase class DriverScanimage(DriverBase): name = "Scanimage" def __init__(self,device,scanner_mode_switching,resolution=300,brightness=40,scan_area=0): self.device = device.split()[1][1:-1] self.device_name = device; self.scanner_mode = "Color" self.light_parameter_state = False device_info = subprocess.getoutput("scanimage -d {} --all-options"\ .format(self.device)) for line in device_info.split("\n"): if ("--mode" in line): self.available_modes = line.split()[1].split("|") print(self.available_modes) if ("--brightness" in line): self.light_parameter_state = True self.light_parameter = "brightness" print("Brightness available") #if ("--threshold" in line and self.light_parameter_state == False): # self.light_parameter_state = True # self.light_parameter = "threshold" # print("Threshold available") if ("-y" in line): self.max_y = line.split()[1].split(".")[2].split("mm")[0] print(self.max_y) if ("-x" in line): self.max_x = line.split()[1].split(".")[2].split("mm")[0] print(self.max_x) super(DriverScanimage, self).__init__(device,scanner_mode_switching, resolution,brightness,scan_area) self.brightness_multiplier = 2 self.brightness_offset = -100 def scan(self,filename,brightness=-1,resolution=-1,scan_area=-1): super(DriverScanimage, self).scan(filename,brightness,resolution,scan_area) command = "scanimage --device-name='{}' --resolution {} --mode {} -x {} -y {}"\ .format(self.device,self.resolution,self.scanner_mode,self.max_x,self.y) #if (self.calibration_cache): # command += (" --calibration-cache=yes") if (self.check_brightness_support()): command += (" --{}={}".format(self.light_parameter,self.brightness)) command += (" > {}".format(filename)) print(command) os.system(command) os.system("convert -strip -quality 90 {0} {0}".format(filename)) def get_resolution(self): return self.resolution def set_resolution(self,resolution): self.resolution = resolution def get_brightness(self): return self.brightness def set_brightness(self,brightness): self.brightness = brightness def set_scan_area(self,scan_area): if scan_area == self.SCAN_AREA_FULL: self.y = int(self.max_y) elif scan_area == self.SCAN_AREA_THREE_QUARTER: self.y = 3*(int(self.max_y)/4) elif scan_area == self.SCAN_AREA_HALF: self.y = int(self.max_y)/2 else: self.y = int(self.max_y)/4 def get_scan_area(self): return self.scan_area def set_scan_mode(self,mode): self.scanner_mode = mode def get_scan_mode(self,scan_mode): return self.scanner_mode def get_available_scan_modes(self): return self.available_modes def check_brightness_support(self): return self.light_parameter_state #static method def get_available_devices(): scanner_list = [] output = subprocess.getoutput("scanimage --list") for line in output.split("\n"): if (("device" in line) and ("v4l" not in line)): try: scanner_list.append(line) except: pass return scanner_list #static method def is_available(): if ("/bin/scanimage" in subprocess.getoutput("whereis scanimage")): return True else: return False def cancel(self): os.system("pkill scanimage") def close(self): return if __name__ == "__main__": scanners = [] scanner_list = DriverScanimage.get_available_devices() print(scanner_list) for device in scanner_list: scanners.append(DriverScanimage(device)) scanners[0].scan("Hello.png") lios-3-2.7.2/lios/speech.py000066400000000000000000000025461345364566700154510ustar00rootroot00000000000000#!/usr/bin/env python3 ########################################################################### # Lios - Linux-Intelligent-Ocr-Solution # Copyright (C) 2015-2016 Nalin.x.Linux GPL-3 # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ########################################################################### import speechd class Speech(speechd.SSIPClient): def __init__(self,client_name="lios"): super(Speech,self).__init__(client_name) self.status = False def list_voices(self): return [ x[0] for x in self.list_synthesis_voices()] def say(self,text): self.status = True self.speak(text,self.end,speechd.CallbackType.END) def wait(self): while (self.status): pass def end(self,*data): self.status = False #close() lios-3-2.7.2/lios/text_to_audio.py000066400000000000000000000065151345364566700170510ustar00rootroot00000000000000#!/usr/bin/env python3 ########################################################################### # Lios - Linux-Intelligent-Ocr-Solution # Copyright (C) 2011-2015 Nalin.x.Linux GPL-3 # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ########################################################################### import os import subprocess class text_to_audio_converter: def __init__(self,text="Blank",volume=100,voice="english",split_time=5,pitch=50,speed=170): self.text = text self.set_volume(volume) self.set_voice(voice) self.set_split_time(split_time) self.set_pitch(pitch) self.set_speed(speed) def list_voices(): voice_list = [] output = subprocess.getoutput("espeak --voices") for line in output.split("\n"): if(line.split()[3] != "VoiceName"): voice_list.append(line.split()[3]) return voice_list def get_volume(self): return self.volume def get_voice(self): return self.voice def get_split_time(self): return self.split_time def get_pitch(self): return self.pitch def get_speed(self): return self.speed def set_volume(self,value): if ( 0 <= value and value <= 200): self.volume = value else: self.volume = 100 return False; def set_voice(self,value): if (value in text_to_audio_converter.list_voices()): self.voice = value return True; else: self.voice = "english" return False; def set_split_time(self,value): self.split_time = value def set_pitch(self,value): if ( 0 <= value and value <= 100): self.pitch = value return True else: self.pitch = 50 return False; def set_speed(self,value): if ( 100 <= value and value <= 450): self.speed = value return True else: self.speed = 170 return False; def record_to_wave(self,output_file_name): to_convert = open("tmp.txt",'w') to_convert.write(self.text) to_convert.close() os.system('espeak -a %s -v %s -f tmp.txt -w %s.wav --split=%s -p %s -s %s' % (self.volume,self.voice,output_file_name,self.split_time,self.pitch,self.speed)) def record_to_mp3(self,output_file_name): to_convert = open("tmp.txt",'w') to_convert.write(self.text) to_convert.close() os.system("rm -rf /tmp/lios_audio") os.system("mkdir /tmp/lios_audio") os.system('espeak -a %s -v %s -f tmp.txt -w /tmp/lios_audio/%s.wav --split=%s -p %s -s %s'%(self.volume,self.voice,output_file_name.split("/")[-1],self.split_time,self.pitch,self.speed)) cmd = 'for f in /tmp/lios_audio/*.wav; do filename=$(basename "$f");name="${filename%.*}"; echo $name; lame --vbr-new -V 3 "$f" '+"/".join(output_file_name.split("/")[:-1])+'/$name.mp3; done;' os.system(cmd) if __name__ == "__main__": ob = text_to_audio_converter("This is a sample of text in english") ob.record_to_wave("~/Hello") lios-3-2.7.2/lios/train_tesseract.py000066400000000000000000001344401345364566700173730ustar00rootroot00000000000000#!/usr/bin/env python3 ########################################################################### # Lios - Linux-Intelligent-Ocr-Solution # Copyright (C) 2011-2015 Nalin.x.Linux GPL-3 # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ########################################################################### from lios import imageview, ocr from lios.ui.gtk import widget, containers, loop, menu, \ window, icon_view, dialog, about, tree_view, text_view, terminal, file_chooser from lios.ui.gtk.file_chooser import FileChooserDialog from lios import macros from lios import localization _ = localization._ import os import subprocess import shutil import time import threading from functools import wraps def on_thread(function): @wraps(function) def inner(*args): print(function.__name__+" Started") #function(*args); threading.Thread(target=function,args=args).start() return inner DICT_LIST = ["/tmp/tesseract-train/file."+x for x in ["word-dawg","freq-dawg","punc-dawg","number-dawg","bigram-dawg"]] class TesseractTrainer(window.Window): def __init__(self,image_list=None): window.Window.__init__(self, title=_("Tesseract Trainer")) self.set_taskbar_icon(macros.logo_file) grid = containers.Grid() if( not ocr.ocr_engine_tesseract.OcrEngineTesseract.is_available()): label = widget.Label(_("Tesseract is not installed")) self.add(label) label.show() self.set_default_size(400,200) return if( not ocr.ocr_engine_tesseract.OcrEngineTesseract.is_training_executables_available()): label = widget.Label(_("""Tesseract training executable are not installed. Please make sure following exicutables are installed \ncombine_tessdata, unicharset_extractor, shapeclustering, mftraining, cntraining and text2image. \nIf you forget to build training tools then use 'make training' and 'sudo make training-install' to build it """)) self.add(label) label.show() self.set_default_size(400,200) return if(not os.path.isdir("/tmp/tesseract-train/")): os.mkdir("/tmp/tesseract-train/") self.output_terminal = terminal.Terminal("") self.output_terminal.set_scrollback_lines(10000) scroll_box_output = containers.ScrollBox() scroll_box_output.add(self.output_terminal) self.output_terminal.connect_context_menu_button_callback(self.terminal_popup_context_menu) self.context_menu_terminal = menu.ContextMenu( [(_("Copy"),self.terminal_copy_clipboard), (_("Paste"),self.terminal_paste_clipboard)]) #Notebook notebook = containers.NoteBook() notebook.show_all() paned_notebook_and_output_terminal = containers.Paned(containers.Paned.VERTICAL) paned_notebook_and_output_terminal.add(notebook) paned_notebook_and_output_terminal.add(scroll_box_output) # Train image-box pairs seperator_select_images = widget.Separator() self.icon_view_image_list = icon_view.IconView() self.icon_view_image_list.connect_on_selected_callback(self.on_iconview_item_selected) scroll_box_iconview = containers.ScrollBox() self.icon_view_image_list.set_vexpand(True) scroll_box_iconview.add(self.icon_view_image_list) for item in image_list: self.icon_view_image_list.add_item(item); self.icon_view_image_list.show() box_buttons = containers.Box(containers.Box.VERTICAL) button_add_image_box_pair = widget.Button("Add Image-Box pairs"); button_add_image_box_pair.connect_function(self.button_add_image_box_pair_clicked); box_buttons.add(button_add_image_box_pair) button_generate_image = widget.Button("Generate-Image-Using-Fonts"); button_generate_image.connect_function(self.button_generate_image_clicked); box_buttons.add(button_generate_image) button_remove_image_box_pair = widget.Button("Remove Image-Box pair"); button_remove_image_box_pair.connect_function(self.button_remove_image_box_pair_clicked); box_buttons.add(button_remove_image_box_pair) button_annotate_image = widget.Button("Annotate(Detect boxes)"); button_annotate_image.connect_function(self.button_annotate_image_clicked); box_buttons.add(button_annotate_image) button_re_annotate_image = widget.Button("Re-Annotate(Detect boxes)"); button_re_annotate_image.connect_function(self.button_annotate_image_clicked); box_buttons.add(button_re_annotate_image) button_ocr_and_view = widget.Button("OCR & View Output"); button_ocr_and_view.connect_function(self.button_ocr_and_view_clicked); box_buttons.add(button_ocr_and_view) button_train_image_box_pairs = widget.Button("Train Image-Box pairs"); button_train_image_box_pairs.connect_function(self.train_image_box_pairs_clicked); self.box_editor = BoxEditor(self.on_image_view_box_list_updated) self.font_box = FontBox() self.font_box.connect_change_handler(self.font_changed) box_font_and_box = containers.Box(containers.Box.VERTICAL) box_font_and_box.add(self.font_box) box_font_and_box.add(self.box_editor) box_font_and_box.add(button_train_image_box_pairs) box_iconview_and_buttons = containers.Box(containers.Box.VERTICAL) box_iconview_and_buttons.add(scroll_box_iconview) box_iconview_and_buttons.add(box_buttons) paned_iconview_and_image_view = containers.Paned(containers.Paned.HORIZONTAL) paned_iconview_and_image_view.add(box_iconview_and_buttons) paned_iconview_and_image_view.add(box_font_and_box) notebook.add_page(_("Train images-box"),paned_iconview_and_image_view); #Ambiguous Editor self.treeview_ambiguous = tree_view.TreeView([("match",str,True), ("Replacement",str,True),("Mandatory",int,True)],self.ambiguous_edited_callback) button_ambiguous_train = widget.Button(_("Train")); button_ambiguous_train.connect_function(self.button_ambiguous_train_clicked) button_ambiguous_add = widget.Button(_("Add")); button_ambiguous_add.connect_function(self.button_ambiguous_add_clicked) button_ambiguous_delete = widget.Button(_("Delete")); button_ambiguous_delete.connect_function(self.button_ambiguous_delete_clicked) button_ambiguous_delete_all = widget.Button(_("Delete-All")); button_ambiguous_delete_all.connect_function(self.button_ambiguous_delete_all_clicked) button_ambiguous_import = widget.Button(_("Import")); button_ambiguous_import.connect_function(self.button_ambiguous_import_clicked) button_ambiguous_export = widget.Button(_("Export")); button_ambiguous_export.connect_function(self.button_ambiguous_export_clicked) scrolled_ambiguous = containers.ScrollBox() scrolled_ambiguous.add(self.treeview_ambiguous) box_ambiguous_buttons = containers.Box(containers.Box.VERTICAL) box_ambiguous_buttons.add(button_ambiguous_add), box_ambiguous_buttons.add(button_ambiguous_delete) box_ambiguous_buttons.add(button_ambiguous_delete_all) box_ambiguous_buttons.add(button_ambiguous_import) box_ambiguous_buttons.add(button_ambiguous_export) box_ambiguous_buttons.set_homogeneous(True) self.combobox_ambiguous_write_format = widget.ComboBox() self.combobox_ambiguous_write_format.add_item("Write in V1") self.combobox_ambiguous_write_format.add_item("Write in V2") grid_set_ambiguous = containers.Grid() grid_set_ambiguous.add_widgets([ (scrolled_ambiguous,1,1,containers.Grid.HEXPAND,containers.Grid.VEXPAND), (box_ambiguous_buttons,1,1,containers.Grid.NO_HEXPAND,containers.Grid.VEXPAND), containers.Grid.NEW_ROW, (self.combobox_ambiguous_write_format,2,1,containers.Grid.NO_HEXPAND,containers.Grid.NO_VEXPAND), containers.Grid.NEW_ROW, (button_ambiguous_train,2,1,containers.Grid.HEXPAND,containers.Grid.NO_VEXPAND)]) notebook.add_page("Ambiguous",grid_set_ambiguous); #Dictionary Editor notebook_dicts = containers.NoteBook() self.dictionary_objects = [] for item in DICT_LIST+[macros.user_home_path+"/lios/user-words"]: dict_object = Dictionary(item) notebook_dicts.add_page(item.split("/")[-1],dict_object) self.dictionary_objects.append(dict_object) button_bind_dictionarys = widget.Button("Bind Dictionary's ") button_bind_dictionarys.connect_function(self.button_bind_dictionarys_clicked) grid_set_dictionary = containers.Grid() grid_set_dictionary.add_widgets([(notebook_dicts,1,1,containers.Grid.HEXPAND,containers.Grid.VEXPAND), containers.Grid.NEW_ROW, (button_bind_dictionarys,2,1,containers.Grid.HEXPAND,containers.Grid.NO_VEXPAND)]); notebook.add_page(_("Dictionary's"),grid_set_dictionary); label_language = widget.Label(_("Language ")); self.combobox_language = widget.ComboBox(); self.combobox_language.connect_change_callback_function(self.language_combobox_changed); label_tessdata_dir = widget.Label(_("Tessdata directory ")); self.combobox_tessdata_dir = widget.ComboBox(); self.combobox_tessdata_dir.connect_change_callback_function(self.tessdata_dir_combobox_changed); button_import_language = widget.Button(_("Import")) button_import_language.connect_function(self.button_import_language_clicked) button_export_language = widget.Button(_("Export")) button_export_language.connect_function(self.button_export_language_clicked) button_remove_language = widget.Button(_("Remove")) button_remove_language.connect_function(self.button_remove_language_clicked) self.progress_bar = widget.ProgressBar() self.progress_bar.set_show_text(True) button_close = widget.Button(_("Close")); button_close.connect_function(self.close_trainer); grid.add_widgets([(label_tessdata_dir,1,1,containers.Grid.HEXPAND,containers.Grid.NO_VEXPAND), (self.combobox_tessdata_dir,4,1,containers.Grid.HEXPAND,containers.Grid.NO_VEXPAND), containers.Grid.NEW_ROW, (label_language,1,1,containers.Grid.HEXPAND,containers.Grid.NO_VEXPAND), (self.combobox_language,1,1,containers.Grid.HEXPAND,containers.Grid.NO_VEXPAND), (button_import_language,1,1,containers.Grid.HEXPAND,containers.Grid.NO_VEXPAND), (button_export_language,1,1,containers.Grid.HEXPAND,containers.Grid.NO_VEXPAND), (button_remove_language,1,1,containers.Grid.HEXPAND,containers.Grid.NO_VEXPAND), containers.Grid.NEW_ROW,(paned_notebook_and_output_terminal,5,1,containers.Grid.HEXPAND,containers.Grid.VEXPAND), containers.Grid.NEW_ROW,(self.progress_bar,4,1,containers.Grid.NO_HEXPAND,containers.Grid.NO_VEXPAND), (button_close,1,1,containers.Grid.HEXPAND,containers.Grid.NO_VEXPAND)]) self.add(grid) grid.show_all() self.maximize() dlg = dialog.Dialog(_("Search entire filesystem for tessdata ?"), (_("No"), dialog.Dialog.BUTTON_ID_2,_("Yes"), dialog.Dialog.BUTTON_ID_1)) label = widget.Label(_("Do you want to search entire filesystem for tessdata ?\nThis may take awhile!")) dlg.add_widget(label) label.show() response = dlg.run() if (response == dialog.Dialog.BUTTON_ID_1): dir_list = ocr.ocr_engine_tesseract.OcrEngineTesseract.get_all_available_dirs() else: dir_list = ocr.ocr_engine_tesseract.OcrEngineTesseract.get_available_dirs() dlg.destroy() self.tessdata_dir_available_list = [] for item in dir_list: self.combobox_tessdata_dir.add_item(item) self.tessdata_dir_available_list.append(item) self.combobox_tessdata_dir.set_active(0) self.box_editor.set_image("/usr/share/lios/lios.png") def font_changed(self,text): name = self.icon_view_image_list.get_selected_item_names() if(name): font_desc = self.font_box.get_font() f = open(name[0]+".font_desc","w") f.write(font_desc) def terminal_popup_context_menu(self,*data): self.context_menu_terminal.pop_up() def terminal_copy_clipboard(self,*data): self.output_terminal.copy_clipboard() def terminal_paste_clipboard(self,*data): self.output_terminal.paste_clipboard() def show_progress_bar(self,text): self.progress_bar.set_pulse_mode(True) self.progress_bar.show() self.progress_bar.set_text(text) def hide_progress_bar(self): self.progress_bar.set_pulse_mode(False) self.progress_bar.hide() # @on_thread def button_bind_dictionarys_clicked(self,*data): self.show_progress_bar("Combining dictionarys...") # Saving all dictionarys to it's text files for dictionary in self.dictionary_objects: dictionary.save() # Copying the original in which later components will be overwrited self.output_terminal.run_command("""cp /usr/share/tesseract-ocr/tessdata/{0}.traineddata \ /tmp/tesseract-train/file.traineddata""".format(self.language)) # converting text files to DAWG for item in DICT_LIST: if os.path.isfile(item): cmd = "wordlist2dawg {0}.txt {0} /tmp/tesseract-train/file.unicharset".format(item) self.output_terminal.run_command(cmd) os.system("count=100; while [ ! -r {0} ] && [ $count -ge 0 ]; do sleep .1; count=$(($count-1)); done".format(item)) cmd = "combine_tessdata -o /tmp/tesseract-train/file.traineddata "+item self.output_terminal.run_command(cmd) self.hide_progress_bar() self.place_traineddata("/tmp/tesseract-train/file.traineddata",self.language) def import_ambiguous_list_from_file(self,filename): lines = open(filename).read().split("\n") if("V2" in lines): version = 2 self.combobox_ambiguous_write_format.set_active(1) else: version = 1 self.combobox_ambiguous_write_format.set_active(0) for line in lines[1:-1]: if(version == 1): items = line.split("\t") self.treeview_ambiguous.append((items[1],items[3],int(items[4]))) def export_ambiguous_list_to_file(self,filename): file = open(filename,"w") active = self.combobox_ambiguous_write_format.get_active() file.write(["V1","V2"][active]+"\n") if(active == 0): for line in self.treeview_ambiguous.get_list(): file.write("{0}\t{1}\t{2}\t{3}\t{4}\n".format(str(len(line[0].replace(" ",""))), line[0],str(len(line[1].replace(" ",""))),line[1],str(line[2]))) else: for line in self.treeview_ambiguous.get_list(): file.write("{0}\t{1}\t{2}\n".format(line[0],line[1],str(line[2]))) def button_ambiguous_train_clicked(self,*data): self.export_ambiguous_list_to_file("/tmp/tesseract-train/file.unicharambigs") self.output_terminal.run_command("""cp /usr/share/tesseract-ocr/tessdata/{0}.traineddata \ /tmp/tesseract-train/file.traineddata""".format(self.language)) cmd = "combine_tessdata -o /tmp/tesseract-train/file.traineddata /tmp/tesseract-train/file.unicharambigs" self.output_terminal.run_command(cmd) self.place_traineddata("/tmp/tesseract-train/file.traineddata",self.language) def button_ambiguous_add_clicked(self,*data): dlg = dialog.Dialog(_("Add new ambiguous"), (_("Close"), dialog.Dialog.BUTTON_ID_1,_("Add"), dialog.Dialog.BUTTON_ID_2)) entry_match = widget.Entry() entry_replace = widget.Entry() combobox_mandatory = widget.ComboBox() combobox_mandatory.add_item(_("No")) combobox_mandatory.add_item(_("Yes")) combobox_mandatory.set_active(0) dlg.add_widget_with_label(entry_match,_("Match ")) dlg.add_widget_with_label(entry_replace,_("Replace ")) dlg.add_widget_with_label(combobox_mandatory,_("Mandatory")) response = dlg.run() if(response == dialog.Dialog.BUTTON_ID_2): self.treeview_ambiguous.append((entry_match.get_text(), entry_replace.get_text(),combobox_mandatory.get_active())) dlg.destroy() def button_ambiguous_delete_clicked(self,*data): index = self.treeview_ambiguous.get_selected_row_index() self.treeview_ambiguous.remove(index) def button_ambiguous_delete_all_clicked(self,*data): self.treeview_ambiguous.clear() def button_ambiguous_import_clicked(self,*data): file_chooser_open_files = FileChooserDialog(_("Select files to import"), FileChooserDialog.OPEN,"*", macros.user_home_path) file_chooser_open_files.set_current_folder(macros.user_home_path) response = file_chooser_open_files.run() if response == FileChooserDialog.ACCEPT: filename = file_chooser_open_files.get_filename() self.import_ambiguous_list_from_file(filename) file_chooser_open_files.destroy() def button_ambiguous_export_clicked(self,*data): save_file = file_chooser.FileChooserDialog(_("Save filename"),file_chooser.FileChooserDialog.SAVE,"*",None); save_file.set_do_overwrite_confirmation(True); response = save_file.run() if response == file_chooser.FileChooserDialog.ACCEPT: self.export_ambiguous_list_to_file(save_file.get_filename()) save_file.destroy() def button_generate_image_clicked(self,*data): #Create image (using fonts) label_font_automatic = widget.Label(_("Font")); entry_font_automatic = widget.Entry() fontbutton_automatic = widget.FontButton(); fontbutton_automatic.set_font("FreeMono") entry_font_automatic.set_editable(False) entry_font_automatic.set_text(fontbutton_automatic.get_font_name()) button_choose_font_automatic = widget.Button(_("Choose-Font-File")); generate_and_train_text_view = text_view.TextView() scroll_box = containers.ScrollBox() scroll_box.set_size_request(-1,100); scroll_box.set_border_width(20); scroll_box.add(generate_and_train_text_view) def fontbutton_automatic_clicked(*data): fontname = fontbutton_automatic.get_font_name() entry_font_automatic.set_text(fontname) generate_and_train_text_view.set_font(fontname) spin_font_size.set_value(int(fontname.split()[-1])) def button_choose_font_automatic_clicked(*data): file_chooser = FileChooserDialog(_("Select font file"), FileChooserDialog.OPEN,"*", "/usr/share/fonts/") response = file_chooser.run() if response == FileChooserDialog.ACCEPT: font_file = file_chooser.get_filename() file_chooser.destroy() if (os.path.isfile(font_file)): entry_font_automatic.set_text(font_file) generate_and_train_text_view.set_font("FreeMono") else: file_chooser.destroy() def button_select_input_text_clicked(*data): file_chooser = FileChooserDialog(_("Select input file"), FileChooserDialog.OPEN,macros.supported_text_formats,macros.user_home_path) response = file_chooser.run() if response == FileChooserDialog.ACCEPT: input_file = file_chooser.get_filename() file_chooser.destroy() if (os.path.isfile(input_file)): entry_input_text_automatic.set_text(input_file) generate_and_train_text_view.set_text(open(input_file).read()) else: file_chooser.destroy() fontbutton_automatic.connect_function(fontbutton_automatic_clicked) button_choose_font_automatic.connect_function(button_choose_font_automatic_clicked) label_font_size = widget.Label(_("Font Size")); spin_font_size = widget.SpinButton(10,8,96) label_select_input_text = widget.Label(_("Input Text File")); entry_input_text_automatic = widget.Entry() entry_input_text_automatic.set_editable(False) button_select_input_text = widget.Button(_("Choose")); button_select_input_text.connect_function(button_select_input_text_clicked) label_writing_mode = widget.Label(_("Writing Mode")); combobox_writing_mode = widget.ComboBox(); combobox_writing_mode.add_item("horizontal") combobox_writing_mode.add_item("vertical") combobox_writing_mode.add_item("vertical-upright") combobox_writing_mode.set_active(0) label_writing_char_spacing_automatic = widget.Label(_("Inter-character space")); spinbutton_writing_char_spacing_automatic = widget.SpinButton(5,0,50) label_writing_resolution_automatic = widget.Label(_("Resolution")); spinbutton_writing_resolution_automatic = widget.SpinButton(300,100,1200) check_button_writing_degrade_image_automatic = widget.CheckButton(_("Degrade-image")) label_writing_exposure_level_automatic = widget.Label(_("Exposure-Level")); spinbutton_writing_exposure_level_automatic = widget.SpinButton(0,0,50) check_button_writing_ligature_mode_automatic = widget.CheckButton(_("Ligatur-Mode")) grid_manual_methord = containers.Grid() grid_manual_methord.add_widgets([(label_font_automatic,1,1,containers.Grid.HEXPAND,containers.Grid.VEXPAND,containers.Grid.ALIGN_START), (entry_font_automatic,1,1,containers.Grid.HEXPAND,containers.Grid.VEXPAND), (fontbutton_automatic,1,1,containers.Grid.HEXPAND,containers.Grid.VEXPAND), (button_choose_font_automatic,1,1,containers.Grid.HEXPAND,containers.Grid.VEXPAND), containers.Grid.NEW_ROW, (label_font_size,1,1,containers.Grid.HEXPAND,containers.Grid.VEXPAND,containers.Grid.ALIGN_START), (spin_font_size,3,1,containers.Grid.HEXPAND,containers.Grid.VEXPAND), containers.Grid.NEW_ROW, (label_select_input_text,1,1,containers.Grid.HEXPAND,containers.Grid.VEXPAND,containers.Grid.ALIGN_START), (entry_input_text_automatic,1,1,containers.Grid.HEXPAND,containers.Grid.VEXPAND), (button_select_input_text,2,1,containers.Grid.HEXPAND,containers.Grid.VEXPAND), containers.Grid.NEW_ROW, (scroll_box,4,1,containers.Grid.HEXPAND,containers.Grid.VEXPAND), containers.Grid.NEW_ROW, (label_writing_mode,1,1,containers.Grid.HEXPAND,containers.Grid.VEXPAND,containers.Grid.ALIGN_START), (combobox_writing_mode,3,1,containers.Grid.HEXPAND,containers.Grid.VEXPAND), containers.Grid.NEW_ROW, (label_writing_char_spacing_automatic,1,1,containers.Grid.HEXPAND,containers.Grid.VEXPAND,containers.Grid.ALIGN_START), (spinbutton_writing_char_spacing_automatic,3,1,containers.Grid.HEXPAND,containers.Grid.VEXPAND), containers.Grid.NEW_ROW, (label_writing_resolution_automatic,1,1,containers.Grid.HEXPAND,containers.Grid.VEXPAND,containers.Grid.ALIGN_START), (spinbutton_writing_resolution_automatic,3,1,containers.Grid.HEXPAND,containers.Grid.VEXPAND), containers.Grid.NEW_ROW, (label_writing_exposure_level_automatic,1,1,containers.Grid.HEXPAND,containers.Grid.VEXPAND,containers.Grid.ALIGN_START), (spinbutton_writing_exposure_level_automatic,3,1,containers.Grid.HEXPAND,containers.Grid.VEXPAND), containers.Grid.NEW_ROW, (check_button_writing_degrade_image_automatic,2,1,containers.Grid.HEXPAND,containers.Grid.VEXPAND), (check_button_writing_ligature_mode_automatic,2,1,containers.Grid.HEXPAND,containers.Grid.VEXPAND)]) dlg = dialog.Dialog(_("Generate-Image"),(_("Generate"), dialog.Dialog.BUTTON_ID_1,_("Close!"), dialog.Dialog.BUTTON_ID_2)) dlg.add_widget(grid_manual_methord) grid_manual_methord.show_all() response = dlg.run(); if(response == dialog.Dialog.BUTTON_ID_1): self.show_progress_bar("Generating image..."); #saving the text in textview to /tmp/tesseract-train/input_file.txt open("/tmp/tesseract-train/input_file.txt","w").write(generate_and_train_text_view.get_text()) font = entry_font_automatic.get_text() font = font.split(" ")[0] fonts_dir = "/usr/share/fonts" if("/" in font): fonts_dir = "/".join(font.split("/")[:-1]) font = font.split("/")[-1].split(".")[0] font_size = spin_font_size.get_value() input_file = entry_input_text_automatic.get_text() active = combobox_writing_mode.get_active() writing_mode = ["horizontal","vertical","vertical-upright"][active] char_space = spinbutton_writing_char_spacing_automatic.get_value() resolution = spinbutton_writing_resolution_automatic.get_value() exposure = spinbutton_writing_exposure_level_automatic.get_value() degrade = int(check_button_writing_degrade_image_automatic.get_active()) ligature = int(check_button_writing_ligature_mode_automatic.get_active()) self.generate_image_with_spec(font,font_size,writing_mode,char_space,resolution,exposure,degrade,ligature,fonts_dir) dlg.destroy() @on_thread def generate_image_with_spec(self,font,font_size,writing_mode,char_space,resolution,exposure,degrade,ligature,fonts_dir): # Remove previous image if (os.path.isfile("/tmp/tesseract-train/tmp_tess_image.tif")): os.remove("/tmp/tesseract-train/tmp_tess_image.tif"); #generating image name = time.strftime("%Y-%m-%d,%H:%M:%S") cmd = "text2image --text=/tmp/tesseract-train/input_file.txt --font={0} --ptsize={1} --writing_mode={2} \ --char_spacing={3} --resolution={4} --exposure={5} --degrade_image={6} --ligatures={7} \ --fonts_dir={8} --outputbase=/tmp/tesseract-train/{9}".format(font,font_size,writing_mode,char_space,resolution,exposure,degrade,ligature,fonts_dir,name) self.output_terminal.run_command(cmd) # Wait for image file os.system("while [ ! -f /tmp/tesseract-train/{0}.tif ]; do sleep 1; done".format(name)) self.icon_view_image_list.add_item("/tmp/tesseract-train/{0}.tif".format(name)) self.make_box_file_for_images(["/tmp/tesseract-train/{0}.tif".format(name)]) f = open("/tmp/tesseract-train/{0}.tif.font_desc".format(name),"w") f.write(font) f.close() self.hide_progress_bar() def on_iconview_item_selected(self,data): name = self.icon_view_image_list.get_selected_item_names() if(name): self.box_editor.set_image(name[0]) try: self.box_editor.load_boxes_from_file(".".join(name[0].split(".")[:-1])+".box") except: pass font = open(name[0]+".font_desc").read() self.font_box.set_font(font) def close_trainer(self,*data): self.destroy(); def ambiguous_edited_callback(self,*data): pass def button_import_language_clicked(self,*data): file_chooser = FileChooserDialog(_("Select language file"), FileChooserDialog.OPEN,["traineddata"]) response = file_chooser.run() if response == FileChooserDialog.ACCEPT: file = file_chooser.get_filename() file_chooser.destroy() if (os.path.isfile(file)): name = file.split("/")[-1].split(".")[0] self.place_traineddata(file,name) else: file_chooser.destroy() def button_export_language_clicked(self,*data): save_file = file_chooser.FileChooserDialog(_("Save filename"),file_chooser.FileChooserDialog.SAVE,["traineddata"]); save_file.set_do_overwrite_confirmation(True); save_file.set_current_name(self.language+".traineddata") save_file.set_current_folder(macros.user_home_path) response = save_file.run() if response == file_chooser.FileChooserDialog.ACCEPT: command = "cp {0}/{1}.traineddata {2}".format(self.tessdata_dir,self.language, save_file.get_filename()) os.system(command) save_file.destroy() def button_remove_language_clicked(self,*data): command = "rm {0}/{1}.traineddata".format(self.tessdata_dir,self.language) self.run_command_in_super_user_mode(command,self.tessdata_dir) self.update_language_list() def tessdata_dir_combobox_changed(self,*data): active = self.combobox_tessdata_dir.get_active() self.tessdata_dir = self.tessdata_dir_available_list[active]; #Resetting language combobox self.combobox_language.clear() self.languages = [] for item in ocr.ocr_engine_tesseract.OcrEngineTesseract.get_available_languages_in_dirpath(self.tessdata_dir): self.combobox_language.add_item(item) self.languages.append(item) self.combobox_language.set_active(0) @on_thread def language_combobox_changed(self,*data): active = self.combobox_language.get_active() # While resetting combobox after training the active will be -1 if ( active <= len(self.languages) and active != -1 ): self.language = self.languages[active] self.show_progress_bar("Loading components of "+self.language) #Removing all files in /tmp/tesseract-train/ shutil.rmtree("/tmp/tesseract-train/") os.mkdir("/tmp/tesseract-train/") cmd = "combine_tessdata -u {0}/{1}.traineddata /tmp/tesseract-train/file".format(self.tessdata_dir,self.language) self.output_terminal.run_command(cmd) os.system("while [ ! -r /tmp/tesseract-train/file.unicharset ]; do sleep 0.1; done") #setting ambiguous table loop.acquire_lock() self.treeview_ambiguous.clear() loop.release_lock() os.system("while [ ! -r /tmp/tesseract-train/file.unicharambigs ]; do sleep 0.1; done") self.import_ambiguous_list_from_file("/tmp/tesseract-train/file.unicharambigs") for item in DICT_LIST: if os.path.isfile(item): cmd = "dawg2wordlist /tmp/tesseract-train/file.unicharset {0} {0}.txt".format(item) self.output_terminal.run_command(cmd) os.system("while kill -0 $(pidof dawg2wordlist) 2> /dev/null; do sleep .1; done") os.system("count=100; while [ ! -r {0}.txt ] && [ $count -ge 0 ]; do sleep .1; count=$(($count-1)); done".format(item)) else: f = open(item+".txt","w") f.close() # Create user dictionary if not exist if not os.path.isfile(macros.user_home_path+"/lios/user-words.txt"): f = open(macros.user_home_path+"/lios/user-words.txt","w") f.close() # Loading each dictionarys for d_obj in self.dictionary_objects: loop.acquire_lock() d_obj.load() loop.release_lock() self.hide_progress_bar() def get_shell_filename(self,filename): for item in " [()]": filename = filename.replace(item,"\{0}".format(item)) return filename def button_add_image_box_pair_clicked(self,*data): file_chooser = FileChooserDialog(_("Select images to import"), FileChooserDialog.OPEN,["tif"], macros.user_home_path) file_chooser.set_current_folder(macros.user_home_path) file_chooser.set_select_multiple(True) response = file_chooser.run() if response == FileChooserDialog.ACCEPT: image_list = file_chooser.get_filenames() file_chooser.destroy() no_box_file_image_list = [] no_font_desc_file_image_list = [] for item in image_list: self.icon_view_image_list.add_item(item); if (not os.path.isfile(".".join(item.split(".")[:-1])+".box")): no_box_file_image_list.append(item) if (not os.path.isfile(item+".font_desc")): no_font_desc_file_image_list.append(item) if (no_box_file_image_list != []): dlg = dialog.Dialog(_("No curresponding box files found!"), (_("No"), dialog.Dialog.BUTTON_ID_2,_("Yes"), dialog.Dialog.BUTTON_ID_1)) label = widget.Label(_("Do you want to auto annotate box file with existing language ?\nThis may take awhile!")) dlg.add_widget(label) label.show() response = dlg.run() if (response == dialog.Dialog.BUTTON_ID_1): dlg.destroy() self.make_box_file_for_images(no_box_file_image_list) dlg.destroy() if (no_font_desc_file_image_list != []): dlg = dialog.Dialog(_("No curresponding font_desc files found!"), (_("No"), dialog.Dialog.BUTTON_ID_2,_("Yes"), dialog.Dialog.BUTTON_ID_1)) label = widget.Label(_("Do you want to fill it with following font ?")) fontbox = FontBox() fontbox.set_font("Sans 0 0 0 0 0") dlg.add_widget(label) dlg.add_widget(fontbox) label.show() response = dlg.run() if (response == dialog.Dialog.BUTTON_ID_1): font = fontbox.get_font() dlg.destroy() for image_file in no_font_desc_file_image_list: f = open(image_file+".font_desc","w") f.write(font) f.close() dlg.destroy() else: file_chooser.destroy() def button_remove_image_box_pair_clicked(self,*data): dlg = dialog.Dialog(_("Delete file too ?"), (_("No"), dialog.Dialog.BUTTON_ID_2,_("Yes"), dialog.Dialog.BUTTON_ID_1,_("Close"), dialog.Dialog.BUTTON_ID_3)) label = widget.Label(_("Do you want to delete files(image,box,font_desc) too ?")) dlg.add_widget(label) label.show() response = dlg.run() if (response == dialog.Dialog.BUTTON_ID_1): image_list = self.icon_view_image_list.get_selected_item_names() for image in image_list: if (os.path.exists(image.replace(".tif",".box"))): os.remove(image.replace(".tif",".box")); if (os.path.exists(image+".font_desc")): os.remove(image+".font_desc"); self.icon_view_image_list.remove_selected_items(True) elif (response == dialog.Dialog.BUTTON_ID_2): self.icon_view_image_list.remove_selected_items(False) dlg.destroy() self.box_editor.set_image("/usr/share/lios/lios.png") def button_annotate_image_clicked(self,*data): image_list = self.icon_view_image_list.get_selected_item_names() self.make_box_file_for_images(image_list) def place_traineddata(self,source,language): if (os.path.isfile(self.tessdata_dir+"/"+language+".traineddata")): dlg = dialog.Dialog(language+_(" Alrady exist! Please edit name to avoid replacing"), (_("Place it"), dialog.Dialog.BUTTON_ID_1)) entry = widget.Entry() dlg.add_widget_with_label(entry,_("File Name : ")) entry.set_text(language) response = dlg.run() language = entry.get_text() dlg.destroy() command = "cp {0} {1}/{2}.traineddata".format(source,self.tessdata_dir,language) self.run_command_in_super_user_mode(command,self.tessdata_dir) self.update_language_list() def update_language_list(self): self.languages = [] self.combobox_language.clear() for item in ocr.ocr_engine_tesseract.OcrEngineTesseract.get_available_languages_in_dirpath(self.tessdata_dir): self.combobox_language.add_item(item) self.languages.append(item) self.combobox_language.set_active(0) def run_command_in_super_user_mode(self, command, directory): if(os.access(directory, os.W_OK)): os.system(command); else: if ("/bin/pkexec" in subprocess.getoutput("whereis pkexec")): os.system("pkexec "+command); elif ("/bin/gksudo" in subprocess.getoutput("whereis gksudo")): os.system("gksudo "+command); elif ("/bin/kdesudo" in subprocess.getoutput("whereis kdesudo")): os.system("kdesudo "+command); elif ("/bin/gksu" in subprocess.getoutput("whereis gksu")): os.system("gksu "+command); else: dlg = dialog.Dialog(_("Error : running command failed"), (_("Ok"), dialog.Dialog.BUTTON_ID_1)) label = widget.Label(_("Can't run command : {0}\n Please make sure you have write access to {1}".format(command,directory))) dlg.add_widget(label) label.show() response = dlg.run() dlg.destroy() @on_thread def make_box_file_for_images(self,filenames_list): for file_ in filenames_list: filename = self.get_shell_filename(file_) self.show_progress_bar("Making box file for "+file_) # Removing previous box files if exist -- Bugs exist :( self.output_terminal.run_command("rm -f /tmp/tesseract-train/batch.nochop.box") self.output_terminal.run_command("cd /tmp/tesseract-train/") self.output_terminal.run_command("convert {0} -background white -flatten +matte file.tif".format(filename)) self.output_terminal.run_command("") self.output_terminal.run_command("tesseract file.tif --tessdata-dir {0} -l {1} batch.nochop makebox".format(self.tessdata_dir,self.language)) # Wait for box file os.system("while [ ! -f /tmp/tesseract-train/batch.nochop.box ]; do sleep .1; done") os.system("count=200; while [ ! -s /tmp/tesseract-train/batch.nochop.box ] && [ $count -ge 0 ]; do sleep .1; count=$(($count-1)); done") os.system("cp /tmp/tesseract-train/batch.nochop.box {0}.box".format(".".join(filename.split(".")[:-1]))) self.hide_progress_bar() def train_image_box_pairs_clicked(self,*data): image_list = self.icon_view_image_list.get_selected_item_names() if (image_list == []): self.icon_view_image_list.select_all_items() image_list = self.icon_view_image_list.get_selected_item_names() if (image_list == []): return dlg = dialog.Dialog(_("Training images..."), (_("Close"), dialog.Dialog.BUTTON_ID_2,_("Train"), dialog.Dialog.BUTTON_ID_1)) label = widget.Label(_("Images to be trained \n{0}\n \ \nLanguage used : {1}\nOutput tessdata directory : {2}".format("\n".join(image_list),self.language,self.tessdata_dir))) label.set_ellipsize(True) dlg.add_widget(label) label.show() response = dlg.run() if (response != dialog.Dialog.BUTTON_ID_1): dlg.destroy() return dlg.destroy() self.output_terminal.run_command("cd /tmp/tesseract-train/") self.show_progress_bar("Training images...") tr_list = "" font_set = set() image_list_shell_type = [] for img in image_list: image = self.get_shell_filename(img) image_list_shell_type.append(image) image_name_without_extension = ".".join(image.split(".")[:-1]) tr_name = ".".join((image.split("/")[-1]).split(".")[:-1])+".box.tr" self.output_terminal.run_command("tesseract --tessdata-dir {0} -l {1} {2} {3}.box nobatch box.train".format(self.tessdata_dir,self.language,image,image_name_without_extension)); self.output_terminal.run_command("mv {0}.box.tr /tmp/tesseract-train/{1}".format(image_name_without_extension,tr_name)) # getting each font desc try: font = open(image+".font_desc").read() font_set.add(font) except: pass tr_list = tr_list+tr_name+" " self.output_terminal.run_command("unicharset_extractor -D /tmp/tesseract-train/ "+(" ".join(image_list_shell_type).replace(".tif",".box"))); # Saving all font desc f = open("/tmp/tesseract-train/font_properties","w") for item in font_set: f.write(item+"\n") f.close() self.output_terminal.run_command("shapeclustering -F font_properties -U unicharset "+tr_list); self.output_terminal.run_command("mftraining -F font_properties -U unicharset -O unicharset "+tr_list); self.output_terminal.run_command("cntraining "+tr_list); self.output_terminal.run_command("mv inttemp file.inttemp"); self.output_terminal.run_command("mv normproto file.normproto"); self.output_terminal.run_command("mv pffmtable file.pffmtable"); self.output_terminal.run_command("mv shapetable file.shapetable"); self.output_terminal.run_command("mv unicharset file.unicharset") dlg = dialog.Dialog(_("Combine with dictionarys too ?"), (_("No"), dialog.Dialog.BUTTON_ID_2,_("Yes"), dialog.Dialog.BUTTON_ID_1)) label = widget.Label(_("Do you want to add dictionarys ? \ \nDo it if only all characters used in dictionarys are going to be trained!")) dlg.add_widget(label) label.show() response = dlg.run() if (response != dialog.Dialog.BUTTON_ID_1): for item in DICT_LIST: if os.path.exists(item): os.remove(item) dlg.destroy() self.output_terminal.run_command("combine_tessdata file."); self.hide_progress_bar() self.place_traineddata("/tmp/tesseract-train/file.traineddata",self.language) @on_thread def button_ocr_and_view_clicked(self,*data): name = self.icon_view_image_list.get_selected_item_names() if(name == []): return; self.show_progress_bar("Running ocr... Please wait"); image_file = self.get_shell_filename(name[0]) self.output_terminal.run_command("tesseract {0} /tmp/tesseract-train/output -l {1}".format(image_file,self.language)); # Wait for output os.system("while [ ! -f /tmp/tesseract-train/output.txt ]; do sleep .1; done") os.system("count=100; while [ ! -s /tmp/tesseract-train/output.txt ] && [ $count -ge 0 ]; do sleep .1; count=$(($count-1)); done") self.hide_progress_bar() loop.acquire_lock() window_output = window.Window(_("Recognised text from image {0} with {1}".format(image_file.split("/")[-1],self.language))) window_output.set_taskbar_icon(macros.logo_file) tv = text_view.TextView() sb = containers.ScrollBox() sb.add(tv) tv.set_vexpand(True) tv.set_hexpand(True) tv.set_text(open("/tmp/tesseract-train/output.txt").read()) os.system("rm /tmp/tesseract-train/output.txt") window_output.set_default_size(500,400) window_output.add(sb) window_output.show_all() loop.release_lock() def on_image_view_box_list_updated(self,*data): name = self.icon_view_image_list.get_selected_item_names() if(name): self.box_editor.save_boxes_to_file(".".join(name[0].split(".")[:-1])+".box") class FontBox(containers.Box): def __init__(self): containers.Box.__init__(self,containers.Box.HORIZONTAL) label = widget.Label("Font "); label.set_hexpand(True) self.entry = widget.Entry() self.entry.set_hexpand(True) self.fontbutton = widget.FontButton(); self.fontbutton.set_hexpand(True) self.fontbutton.set_font("Sans 10") self.entry.set_text("Sans") self.fontbutton.connect_function(self.font_changed) self.cb_italic = widget.CheckButton("Italic") self.cb_bold = widget.CheckButton("Bold") self.cb_fixed = widget.CheckButton("Fixed") self.cb_serif = widget.CheckButton("Serif") self.cb_fraktur = widget.CheckButton("Fraktur") self.add(label) self.add(self.entry) self.add(self.fontbutton) self.add(self.cb_italic) self.add(self.cb_bold) self.add(self.cb_fixed) self.add(self.cb_serif) self.add(self.cb_fraktur) self.show_all() def connect_change_handler(self,handler): self.fontbutton.connect_function(handler) self.entry.connect_change_handler(handler) self.cb_italic.connect_handler_function(handler) self.cb_bold.connect_handler_function(handler) self.cb_fixed.connect_handler_function(handler) self.cb_serif.connect_handler_function(handler) self.cb_fraktur.connect_handler_function(handler) def font_changed(self,*data): fontname = self.fontbutton.get_font_name() # The last token in fontname will be it's size so we trim it self.entry.set_text(' '.join(fontname.split(" ")[:-1])) if ("bold" in fontname.lower()): self.cb_bold.set_active(True) if ("italic" in fontname.lower()): self.cb_italic.set_active(True) if ("serif" in fontname.lower()): self.cb_serif.set_active(True) def set_font(self,font_desc): desc = font_desc.split(" ") self.fontbutton.set_font("".join(desc[:-5]).replace("_"," ")) self.entry.set_text("".join(desc[:-5]).replace("_"," ")) self.cb_italic.set_active(int(desc[-5])) self.cb_bold.set_active(int(desc[-4])) self.cb_fixed.set_active(int(desc[-3])) self.cb_serif.set_active(int(desc[-2])) self.cb_fraktur.set_active(int(desc[-1])) def get_font(self): text = self.entry.get_text().replace(" ","_") italic = int(self.cb_italic.get_active()) bold = int(self.cb_bold.get_active()) fixed = int(self.cb_fixed.get_active()) serif = int(self.cb_serif.get_active()) fraktur = int(self.cb_fraktur.get_active()) line = "{0} {1} {2} {3} {4} {5}".format(text,italic,bold,fixed,serif,fraktur) return line class BoxEditor(containers.Box): def __init__(self,update_handler): containers.Box.__init__(self,containers.Box.VERTICAL) self.imageview = imageview.ImageViewer() self.imageview.connect("list_updated",self.list_updated_event_handler); self.update_handler = update_handler self.image_name = "" button_zoom_in = widget.Button(_("Zoom-In")) button_zoom_in.connect_function(self.imageview.zoom_in) button_zoom_fit = widget.Button(_("Zoom-Fit")) button_zoom_fit.connect_function(self.imageview.zoom_fit) button_zoom_out = widget.Button(_("Zoom-Out")) button_zoom_out.connect_function(self.imageview.zoom_out) button_save = widget.Button(_("Export-Boxes")) button_save.connect_function(self.save_boxes_dialog) button_load = widget.Button(_("Load-Boxes")) button_load.connect_function(self.load_boxes_dialog) self.add(self.imageview) box1 = containers.Box(containers.Box.HORIZONTAL) box1.add(button_zoom_in) box1.add(button_zoom_fit) box1.add(button_zoom_out) box1.add(button_save) box1.add(button_load) box1.set_hexpand(True) button_zoom_in.set_hexpand(True) button_zoom_fit.set_hexpand(True) button_zoom_out.set_hexpand(True) button_save.set_hexpand(True) button_load.set_hexpand(True) self.add(box1) #self.connect_configure_event_handler(self.configure_event) self.imageview.show() self.show_all() def configure_event(self,*arg): width,height = self.get_size() self.imageview.set_position(width-200) def list_updated_event_handler(self,*arg): self.update_handler(); def save_boxes_to_file(self,filename): file = open(filename,"w") for item in self.get_list(): file.write("{0} {1} {2} {3} {4} 0\n".format(str(item[0]), str(int(item[1])),str(int(item[2])), str(int(item[3])),str(int(item[4])))) def load_boxes_from_file(self,filename): list_ = [] for line in open(filename): spl = line.split(" ") try: list_.append((spl[0],float(spl[1]),float(spl[2]),float(spl[3]),float(spl[4]),int(spl[5]))) except: pass self.set_list(list_) def save_boxes_dialog(self,*data): save_file = file_chooser.FileChooserDialog(_("Save "), file_chooser.FileChooserDialog.SAVE, "*",None) save_file.set_current_name(self.image_name+".box"); save_file.set_do_overwrite_confirmation(True); response = save_file.run() if response == file_chooser.FileChooserDialog.ACCEPT: self.save_boxes_to_file(save_file.get_filename()) save_file.destroy() def load_boxes_dialog(self,*data): open_file = file_chooser.FileChooserDialog(_("Select the file to open"), file_chooser.FileChooserDialog.OPEN, "*",macros.user_home_path) response = open_file.run() if response == file_chooser.FileChooserDialog.ACCEPT: self.imageview.zoom_fit() self.load_boxes_from_file(open_file.get_filename()) self.update_handler(); open_file.destroy() def set_image(self,image): self.imageview.load_image(image,[],imageview.ImageViewer.ZOOM_FIT) self.image_name = "".join(image.split(".")[:-1]) def set_list(self,list): image_height = self.imageview.get_original_height() list_ = [] for item in list: width = item[3]-item[1] height = item[4]-item[2] y = image_height-item[2]-height list_.append((0,item[1],y,width,height,item[0])) self.imageview.set_list(list_,0) def get_list(self): image_height = self.imageview.get_original_height() list_ = [] for item in self.imageview.get_list(): y = round(image_height-(item[2]+item[4])) end_y = round(y+item[4]) end_x = round(item[1]+item[3]) list_.append((item[5],round(item[1]),y,end_x,end_y)) return list_ class Dictionary(containers.Box): def __init__(self,file_path): containers.Box.__init__(self,containers.Box.VERTICAL) self.file_path = file_path box = containers.Box(containers.Box.HORIZONTAL) label = widget.Label(_("Find :")) box.add(label) self.entry = widget.Entry() self.entry.connect_activate_function(self.entry_activated) self.entry.set_hexpand(True) box.add(self.entry) self.add(box) self.textview = text_view.TextView() self.textview.set_highlight_color("#1572ffff0000") scrolled = containers.ScrollBox() scrolled.add(self.textview) scrolled.set_vexpand(True) self.add(scrolled) def load(self): with open(self.file_path+".txt") as file: text = file.read() self.textview.set_text(text) self.textview.move_cursor_to_line(1) def save(self): f = open(self.file_path+".txt","w") f.write(self.textview.get_text()) f.close() def entry_activated(self,*data): text = self.entry.get_text() if(not self.textview.move_forward_to_word(text)): dlg = dialog.Dialog(_("Not found!"),(_("Yes"), dialog.Dialog.BUTTON_ID_1,_("No"), dialog.Dialog.BUTTON_ID_2)) label = widget.Label(_("The word '{0}' not found! Search from start ?".format(text))) dlg.add_widget(label) label.show() response = dlg.run() if response == dialog.Dialog.BUTTON_ID_1: self.textview.move_cursor_to_line(1) dlg.destroy() self.entry_activated() dlg.destroy() class TesseractTrainerGUI(TesseractTrainer): def __init__(self,image_list = []): win = TesseractTrainer(image_list) win.connect_close_function(self.close) win.show() loop.threads_init() loop.start_main_loop() def close(self,*data): loop.stop_main_loop() if __name__ == "__main__": TesseractTrainerGUI([]) lios-3-2.7.2/lios/ui/000077500000000000000000000000001345364566700142365ustar00rootroot00000000000000lios-3-2.7.2/lios/ui/__init__.py000066400000000000000000000022351345364566700163510ustar00rootroot00000000000000#!/usr/bin/env python3 ########################################################################### # Lios - Linux-Intelligent-Ocr-Solution # Copyright (C) 2015-2016 Nalin.x.Linux GPL-3 # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ########################################################################### #from lios.ui.ui_base import OcrEngineBase #from lios.ui.ui_gtk import OcrEngineCuneiform #def get_available_ui_engines(): # list = [] # for item in OcrEngineBase.__subclasses__(): # if item.is_available(): # list.append(item) # return list lios-3-2.7.2/lios/ui/gtk/000077500000000000000000000000001345364566700150235ustar00rootroot00000000000000lios-3-2.7.2/lios/ui/gtk/__init__.py000066400000000000000000000022351345364566700171360ustar00rootroot00000000000000#!/usr/bin/env python3 ########################################################################### # Lios - Linux-Intelligent-Ocr-Solution # Copyright (C) 2015-2016 Nalin.x.Linux GPL-3 # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ########################################################################### #from lios.ui.ui_base import OcrEngineBase #from lios.ui.ui_gtk import OcrEngineCuneiform #def get_available_ui_engines(): # list = [] # for item in OcrEngineBase.__subclasses__(): # if item.is_available(): # list.append(item) # return list lios-3-2.7.2/lios/ui/gtk/about.py000066400000000000000000000024011345364566700165040ustar00rootroot00000000000000#!/usr/bin/python3 ########################################################################### # Lios - Linux-Intelligent-Ocr-Solution # Copyright (C) 2015-2016 Nalin.x.Linux GPL-3 # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ########################################################################### from gi.repository import Gtk from gi.repository import GdkPixbuf class AboutDialog(Gtk.AboutDialog): def __init__(self,title,buttons): super(AboutDialog,self).__init__(title,None,True,buttons) def set_logo_from_file(self,filename): pixbuff = GdkPixbuf.Pixbuf.new_from_file(filename) self.set_logo(pixbuff) #show_all() #run() lios-3-2.7.2/lios/ui/gtk/containers.py000066400000000000000000000107231345364566700175450ustar00rootroot00000000000000#!/usr/bin/python3 ########################################################################### # Lios - Linux-Intelligent-Ocr-Solution # Copyright (C) 2015-2016 Nalin.x.Linux GPL-3 # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ########################################################################### from gi.repository import Gtk from lios.ui.gtk import icon from lios import macros class Grid(Gtk.Grid): BOTTOM = Gtk.PositionType.BOTTOM RIGHT = Gtk.PositionType.RIGHT NEW_ROW = 1; VEXPAND = 1; HEXPAND = 1; NO_VEXPAND = 0; NO_HEXPAND = 0; ALIGN_END = Gtk.Align.END ALIGN_START = Gtk.Align.START def __init__(self): super(Grid,self).__init__() self.x = 0; self.y = 0; self.x_pad = 0; self.x_pad_count = 0; self.y_pad = 0; self.y_pad_count = 0; def add_widgets(self,list): for item in list: if (item == Grid.NEW_ROW): self.__add_new_row() else: self.__add_widget(*item) #attach(widget, left, top, width, height) #attach_next_to(child, sibling, side, width, height) def __add_widget(self,child, width, height,hexpand=True,vexpand=True,halign=None,valign=None): child.set_hexpand(hexpand) child.set_vexpand(vexpand) if(halign): child.set_halign(halign) if(valign): child.set_valign(valign) if (self.x_pad_count > 1 and self.x < self.x_pad): self.x = self.x_pad self.x_pad_count = self.x_pad_count - 1 self.attach(child, self.x, self.y, width, height) if (height > 1): self.x_pad = width; self.x_pad_count = height self.x = self.x + width def __add_new_row(self): self.x = 0 self.y = self.y + 1 class ScrollBox(Gtk.ScrolledWindow): def __init__(self): super(ScrollBox,self).__init__() self.set_border_width(2) def scroll(self,h_value,v_value): adj = self.get_vadjustment() adj.set_value(v_value) adj = self.get_hadjustment() adj.set_value(h_value) def get_size_on_screen(self): alc = self.get_allocation() return (alc.width,alc.height) def get_current_start_points(self): hadj = self.get_hadjustment() start_x = hadj.get_value() vadj = self.get_vadjustment() start_y = vadj.get_value() return start_x,start_y class NoteBook(Gtk.Notebook): def __init__(self): super(NoteBook,self).__init__() def add_page(self,title,widget): label = Gtk.Label(title) self.append_page(widget,label) class Frame(Gtk.Frame): def __init__(self,label_text): super(Frame,self).__init__() self.set_label(label_text) class Paned(Gtk.Paned): HORIZONTAL = Gtk.Orientation.HORIZONTAL; VERTICAL = Gtk.Orientation.VERTICAL; def __init__(self,orientation): super(Paned,self).__init__() self.set_orientation(orientation) class Box(Gtk.Box): HORIZONTAL = Gtk.Orientation.HORIZONTAL; VERTICAL = Gtk.Orientation.VERTICAL; def __init__(self,orientation): super(Box,self).__init__() self.set_orientation(orientation) def connect_configure_event_handler(self,function): self.connect("configure-event",function) class Toolbar(Gtk.Toolbar): HORIZONTAL = Gtk.Orientation.HORIZONTAL; VERTICAL = Gtk.Orientation.VERTICAL; SEPARATOR = 1; def __init__(self,orientation,specification): super(Toolbar,self).__init__() self.set_orientation(orientation) for item in specification: if item == Toolbar.SEPARATOR: toolbar_item = Gtk.SeparatorToolItem() else: toolbar_item = Gtk.ToolButton(item[0]) toolbar_item.connect("clicked",item[1]) if item[0] in icon.stock_icon_dict.keys(): image = Gtk.Image() image.set_from_file(macros.icon_dir+icon.stock_icon_dict[item[0]]+".png") toolbar_item.set_icon_widget(image) else: label = Gtk.Label(item[0]) if(orientation == Gtk.Orientation.VERTICAL): label.set_angle(90) toolbar_item.set_icon_widget(label) toolbar_item.set_tooltip_text(item[0]) self.add(toolbar_item) def set_show_nth_item(self,n,value): item = self.get_nth_item(n) item.set_sensitive(value) lios-3-2.7.2/lios/ui/gtk/dialog.py000066400000000000000000000031451345364566700166370ustar00rootroot00000000000000#!/usr/bin/python3 ########################################################################### # Lios - Linux-Intelligent-Ocr-Solution # Copyright (C) 2015-2016 Nalin.x.Linux GPL-3 # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ########################################################################### from gi.repository import Gtk class Dialog(Gtk.Dialog): BUTTON_ID_1 = 1 BUTTON_ID_2 = 2 BUTTON_ID_3 = 3 def __init__(self,title,buttons): super(Dialog,self).__init__(title,None,True,buttons) def add_widget(self,widget): box = self.get_content_area(); box.add(widget) def add_widget_with_label(self,widget,label_text): new_box = Gtk.Box() label = Gtk.Label(label_text) label.set_mnemonic_widget(widget) new_box.pack_start(label, True, True, 0) new_box.pack_start(widget, True, True, 0) box = self.get_content_area(); box.add(new_box) box.show_all() def connect_configure_event_handler(self,function): self.connect("configure-event",function) #show_all() #run() lios-3-2.7.2/lios/ui/gtk/drawing_area.py000077500000000000000000000106041345364566700200240ustar00rootroot00000000000000#!/usr/bin/python3 ########################################################################### # Lios - Linux-Intelligent-Ocr-Solution # Copyright (C) 2015-2016 Nalin.x.Linux GPL-3 # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ########################################################################### from gi.repository import Gtk from gi.repository import Gdk from gi.repository import GdkPixbuf class DrawingArea(Gtk.DrawingArea): def __init__(self): super(DrawingArea,self).__init__() self.set_events(Gdk.EventMask.ALL_EVENTS_MASK) self.connect("draw",self.__drawingarea_draw) self.rectangles = []; self.drawing_rectangle = None; def set_rectangle_list(self,list): self.rectangles = list; def set_drawing_rectangle(self,rectangle): self.drawing_rectangle = rectangle def connect_button_press_event(self,function): self.connect("button_press_event",lambda x,y: function(y.get_coords(),y.button)) def connect_button_release_event(self,function): self.connect("button_release_event",lambda x,y: function(y.get_coords(),y.button)) def connect_motion_notify_event(self,function): self.connect("motion_notify_event",lambda x,y: function(y.get_coords())) def __drawingarea_draw(self, widget, cr): Gdk.cairo_set_source_pixbuf(cr, self.pixbuf, 0, 0) cr.paint() for item in self.rectangles: #cr.move_to(10, 90) cr.rectangle(item[1], item[2], item[3], item[4]) # Red color for selected item blue for unselected items if item[0] == True: cr.set_source_rgb(0.9, 0, 0) else: cr.set_source_rgb(0, 0.1, 1) cr.set_line_width (2.0); #cr.fill() cr.stroke() if (self.drawing_rectangle): cr.rectangle(self.drawing_rectangle[0],self.drawing_rectangle[1],self.drawing_rectangle[2],self.drawing_rectangle[3]) # Green Color for currently drawing rectangle cr.set_source_rgb(0, 1.0, 0) cr.set_line_width (2.0); cr.stroke() return True def save_image_rectangle(self,filename,x,y,width,height): new_pixbuf = self.pixbuf_original.new_subpixbuf(x,y,width,height) new_pixbuf.savev(filename, "png",[],[]) def get_width(self): return self.pixbuf.get_width() def get_height(self): return self.pixbuf.get_height() def redraw(self): self.queue_draw(); def load_image(self,filename,list,parameter): self.filename = filename self.pixbuf = GdkPixbuf.Pixbuf.new_from_file(filename) self.pixbuf_file_name = filename # Keeping a original copy, later used to create sub-images self.pixbuf_original = self.pixbuf.copy(); width = self.pixbuf.get_width() height = self.pixbuf.get_height() self.orig_height = height if (parameter != 1 ): self.set_size_request(width*parameter,height*parameter) self.pixbuf = self.pixbuf.scale_simple(width*parameter,height*parameter,GdkPixbuf.InterpType.HYPER) else: self.set_size_request(width,height) self.rectangles = list; self.queue_draw() def get_original_height(self): return self.orig_height def set_mouse_pointer_type(self,_type): list = [Gdk.CursorType.ARROW, Gdk.CursorType.TOP_LEFT_CORNER,Gdk.CursorType.SB_V_DOUBLE_ARROW,Gdk.CursorType.TOP_RIGHT_CORNER, Gdk.CursorType.SB_H_DOUBLE_ARROW,Gdk.CursorType.FLEUR,Gdk.CursorType.SB_H_DOUBLE_ARROW, Gdk.CursorType.BOTTOM_LEFT_CORNER,Gdk.CursorType.SB_V_DOUBLE_ARROW,Gdk.CursorType.BOTTOM_RIGHT_CORNER] arrow = Gdk.Cursor(list[_type]) gdk_window = self.get_root_window() gdk_window.set_cursor(arrow) def connect_context_menu_button_callback(self,function): def fun(widget,event): if ((event.type == Gdk.EventType.BUTTON_RELEASE and event.button == 3) or (event.type == Gdk.EventType.KEY_PRESS and event.hardware_keycode == 135)): function() self.connect("button-release-event",fun) self.connect("key-press-event",fun) lios-3-2.7.2/lios/ui/gtk/file_chooser.py000066400000000000000000000034241345364566700200410ustar00rootroot00000000000000#!/usr/bin/python3 ########################################################################### # Lios - Linux-Intelligent-Ocr-Solution # Copyright (C) 2015-2016 Nalin.x.Linux GPL-3 # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ########################################################################### from gi.repository import Gtk class FileChooserDialog(Gtk.FileChooserDialog): OPEN = Gtk.FileChooserAction.OPEN SAVE = Gtk.FileChooserAction.SAVE OPEN_FOLDER = Gtk.FileChooserAction.SELECT_FOLDER ACCEPT = Gtk.ResponseType.OK def __init__(self,title,action,filters=None,dir=None): if(action == Gtk.FileChooserAction.OPEN or action == Gtk.FileChooserAction.SELECT_FOLDER): super(FileChooserDialog,self).__init__(title,None,action,buttons=(Gtk.STOCK_OPEN,Gtk.ResponseType.OK)) else: super(FileChooserDialog,self).__init__(title,None,action,buttons=(Gtk.STOCK_SAVE,Gtk.ResponseType.OK)) if (action != Gtk.FileChooserAction.SELECT_FOLDER): filter = Gtk.FileFilter() for item in filters: filter.add_pattern("*."+item) self.add_filter(filter) if (dir): self.set_current_folder(dir) #def run() distroy() get_filename() set_current_folder() lios-3-2.7.2/lios/ui/gtk/icon.py000066400000000000000000000102171345364566700163260ustar00rootroot00000000000000#!/usr/bin/python3 ########################################################################### # Lios - Linux-Intelligent-Ocr-Solution # Copyright (C) 2015-2016 Nalin.x.Linux GPL-3 # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ########################################################################### from lios import localization _ = localization._ stock_icon_dict = { _("_File") :"edit-copy", _("New") :"document-new", _("Open"):"document-open", _("Save"):"document-save", _("Save-As"):"document-save-as", _("Find"):"find", _("Find-Replace"):"find-replace", _("Text-Cleaner"):"find-replace", _("Import"):"document-open", _("Export"):"document-save", _("Apply-From-Cursor"):"find-replace", _("Apply-Entire"):"find-replace", _("Train-Tesseract"):"system-upgrade", _("Spell-Check"):"check-spelling", _("Start-Reader"):"media-playback-start", _("Stop-Reader"):"media-playback-stop", _("Increase-Reader-Speed"):"go-up", _("Decrease-Reader-Speed"):"go-down", _("Stop-All-Process"):"media-playback-stop", _("Go-To-Page"):"go-jump", _("Go-To-Line"):"go-jump", _("Undo"):"edit-undo", _("Redo"):"edit-redo", _("Delete"):"remove", _("Punch-Text"):"insert-text", _("Append-Text"):"insert-text", _("Zoom-In"):"zoom-in", _("Zoom-Fit"):"zoom-fit", _("Zoom-Out"):"zoom-out", _("Rotate-Left"):"rotate-left", _("Rotate-Right"):"rotate-right", _("Rotate-Twice"):"flip-vertical", _("_Image"):"image", _("Import-Pdf"):"application-pdf", _("Import-Folder"):"folder-pictures", _("Import-Image"):"image", _("Invert-List"):"sort-descending", _("Recognize"):"convert", _("_Recognize"):"convert", _("Recognize-Selected-Images"):"convert", _("Recognize-All-Images"):"convert", _("Recognize-Selected-with-rotation"):"convert", _("Recognize-All-with-rotation"):"convert", _("Recognize-Selected-Areas"):"convert", _("Recognize-Current-Image"):"convert", _("Recognize-Current-Image-With-Rotation"):"convert", _("Clear"):"clear", _("Print"):"print", _("Export-Text-As-Pdf"):"application-pdf", _("Export-As-Pdf"):"application-pdf", _("Print-Preview"):"print-preview", _("Quit"):"quit", _("_Edit"):"edit-cut", _("Cut"):"edit-cut", _("Copy"):"edit-copy", _("Paste"):"edit-paste", _("Bookmark"):"emblem-favorite", _("Bookmark-Table"):"emblem-favorite", _("Import-Bookmarks"):"emblem-favorite", _("Bookmark-Table-Complete"):"emblem-favorite", _("Update-Scanner-List"):"scanner", _("_Scan"):"scanner", _("Scan-Image"):"scanner", _("Scan-Image-Repeatedly"):"scanner", _("Scan-and-Ocr"):"scanner", _("Scan-and-Ocr-Repeatedly"):"scanner", _("Optimise-Scanner-Brightness"):"scanner", _("Scan-Using-Webcam"):"camera-web", _("Take-Screenshot"):"camera", _("Take-and-Recognize-Screenshot"):"camera", _("_Preferences"):"preferences", _("Preferences"):"preferences", _("Preferences-Scanning"):"preferences", _("Preferences-General"):"preferences", _("Preferences-Recognition"):"preferences", _("Restore"):"clear", _("Load"):"document-open", _("_Tools"):"accessories-text-editor", _("Dictionary"):"accessories-dictionary", _("Audio-Converter"):"audio-input-microphone", _("Help"):"info", _("Open-Readme"):"info", _("Video-Tutorials"):"info", _("Open-Home-Page"):"info", _("Get-Source-Code"):"info", _("About"):"about"} lios-3-2.7.2/lios/ui/gtk/icon_view.py000066400000000000000000000071351345364566700173650ustar00rootroot00000000000000#!/usr/bin/python3 ########################################################################### # Lios - Linux-Intelligent-Ocr-Solution # Copyright (C) 2015-2016 Nalin.x.Linux GPL-3 # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ########################################################################### from gi.repository import Gtk from gi.repository import Gdk from gi.repository import GdkPixbuf import os class IconView(Gtk.IconView): def __init__(self): super(IconView,self).__init__() self.set_selection_mode(Gtk.SelectionMode.MULTIPLE) self.liststore_images = Gtk.ListStore(GdkPixbuf.Pixbuf, str) self.set_pixbuf_column(0) self.set_text_column(1) self.set_columns(1) self.set_model(self.liststore_images) #methord is not thread safe def add_item(self,filename): try: pixbuff = GdkPixbuf.Pixbuf.new_from_file(filename) except: pass else: height = pixbuff.get_height() width = pixbuff.get_width() ratio = (height*50)/width buff = pixbuff.scale_simple(50,ratio,GdkPixbuf.InterpType.BILINEAR) del pixbuff self.liststore_images.append([buff, filename]) self.queue_draw() del buff def remove_selected_items(self,remove_file_too=True): for item in self.get_selected_items(): iter = self.liststore_images.get_iter_from_string(item.to_string()) if(remove_file_too): os.remove(self.liststore_images.get_value(iter, 1)) self.liststore_images.remove(iter) def select_all_items(self): self.select_all() def select_item(self,filename): model = self.get_model() #iter = model.get_iter_first() for item in self.get_selected_items(): iter = self.liststore_images.get_iter_from_string(item.to_string()) if (filename == self.liststore_images.get_value(iter, 1)): path = model.get_path(iter) self.select_path(path) break; def reload_preview(self,filename): for item in self.liststore_images: if (item[1] == filename): pixbuff = GdkPixbuf.Pixbuf.new_from_file(filename) height = pixbuff.get_height() width = pixbuff.get_width() ratio = (height*50)/width buff = pixbuff.scale_simple(50,ratio,GdkPixbuf.InterpType.BILINEAR) del pixbuff item[0] = buff del buff def get_selected_item_names(self): items = [] for item in reversed(self.get_selected_items()): items.append(self.liststore_images[item[0]][1]) return items; def invert_list(self,*data): liststore = Gtk.ListStore(GdkPixbuf.Pixbuf, str) for item in reversed(self.liststore_images): liststore.append((item[0],item[1])) self.liststore_images = liststore self.set_model(self.liststore_images) def connect_on_selected_callback(self,function): self.connect("selection-changed",function) def connect_context_menu_button_callback(self,function): def fun(widget,event): if ((event.type == Gdk.EventType.BUTTON_RELEASE and event.button == 3) or (event.type == Gdk.EventType.KEY_PRESS and event.hardware_keycode == 135)): function() self.connect("button-release-event",fun) self.connect("key-press-event",fun) lios-3-2.7.2/lios/ui/gtk/loop.py000066400000000000000000000022721345364566700163510ustar00rootroot00000000000000#!/usr/bin/python3 ########################################################################### # Lios - Linux-Intelligent-Ocr-Solution # Copyright (C) 2015-2016 Nalin.x.Linux GPL-3 # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ########################################################################### from gi.repository import Gtk from gi.repository import Gdk def start_main_loop(): Gtk.main() def threads_init(): Gdk.threads_init() def stop_main_loop(data=None): Gtk.main_quit() def acquire_lock(): Gdk.threads_enter() def release_lock(): Gdk.threads_leave() lios-3-2.7.2/lios/ui/gtk/menu.py000066400000000000000000000073061345364566700163470ustar00rootroot00000000000000#!/usr/bin/python3 ########################################################################### # Lios - Linux-Intelligent-Ocr-Solution # Copyright (C) 2015-2016 Nalin.x.Linux GPL-3 # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ########################################################################### from gi.repository import Gtk from lios.ui.gtk import icon from lios import macros SEPARATOR = 1; class Menu(Gtk.Menu): def __init__(self): super(Menu,self).__init__() class ImageMenuItem(Gtk.ImageMenuItem): def __init__(self,label): super(ImageMenuItem,self).__init__(label) class SeparatorMenuItem(Gtk.SeparatorMenuItem): def __init__(self): super(SeparatorMenuItem,self).__init__() class MenuBar(Gtk.MenuBar): def __init__(self,item_list): super(MenuBar,self).__init__() self.agr = Gtk.AccelGroup() for item in item_list: menu = create_menu(item,self.agr) self.append(menu) def get_accel_group(self): return self.agr def create_menu(item,agr): if (type(item) == list ): menu_item = ImageMenuItem(item[0]) menu = Gtk.Menu() if (item[0] in icon.stock_icon_dict.keys()): image = Gtk.Image() #image.set_from_icon_name(icon.stock_icon_dict[item[0]],10) image.set_from_file(macros.icon_dir+icon.stock_icon_dict[item[0]]+".png") menu_item.set_image(image) menu_item.set_always_show_image(True) for i in item[1:]: sub_menu = create_menu(i,agr) menu.append(sub_menu) menu_item.set_submenu(menu) menu_item.set_use_underline(True) return menu_item else: if(item == SEPARATOR): terminal_menu_item = SeparatorMenuItem() return (terminal_menu_item) else: terminal_menu_item = ImageMenuItem(item[0]) if (item[0] in icon.stock_icon_dict.keys()): image = Gtk.Image() #image.set_from_icon_name(icon.stock_icon_dict[item[0]],10) image.set_from_file(macros.icon_dir+icon.stock_icon_dict[item[0]]+".png") terminal_menu_item.set_image(image) terminal_menu_item.set_always_show_image(True) terminal_menu_item.connect("activate",item[1]) if(item[2] != "None"): key, mod = Gtk.accelerator_parse(item[2]) terminal_menu_item.add_accelerator("activate", agr, key, mod, Gtk.AccelFlags.VISIBLE) return (terminal_menu_item) #** Context Menu related classes and functions **# class MenuItem(Gtk.MenuItem): def __init__(self,label): super(MenuItem,self).__init__(label) class ContextMenu(Gtk.Menu): def __init__(self,item_list): super(ContextMenu,self).__init__() for item in item_list: menu = create_context_menu(item) self.append(menu) def pop_up(self,*data): self.popup(None,None,None,None,0,0) self.show_all() def create_context_menu(menu_list): if (type(menu_list) == list ): menu_item = MenuItem(menu_list[0]) menu = Gtk.Menu() for item in menu_list[1:]: sub_menu = create_context_menu(item) menu.append(sub_menu) menu_item.set_submenu(menu) return menu_item else: if(menu_list == SEPARATOR): terminal_menu_item = SeparatorMenuItem() else: terminal_menu_item = MenuItem(menu_list[0]) terminal_menu_item.connect("activate",menu_list[1]) return (terminal_menu_item) lios-3-2.7.2/lios/ui/gtk/print_dialog.py000066400000000000000000000074611345364566700200600ustar00rootroot00000000000000#!/usr/bin/python3 ########################################################################### # Lios - Linux-Intelligent-Ocr-Solution # Copyright (C) 2015-2016 Nalin.x.Linux GPL-3 # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ########################################################################### from gi.repository import Gtk from gi.repository import Pango from gi.repository import PangoCairo import math class print_with_action(): PREVIEW = Gtk.PrintOperationAction.PREVIEW PRINT_DIALOG = Gtk.PrintOperationAction.PRINT_DIALOG EXPORT = Gtk.PrintOperationAction.EXPORT def __init__(self, text, action=None,filename = None): self.text_to_print = text self.layout = None self.page_breaks = None self.font = "sans" self.font_size=12 if action==None: action = Gtk.PrintOperationAction.PREVIEW paper_size = Gtk.PaperSize.new(Gtk.PAPER_NAME_A4) setup = Gtk.PageSetup() setup.set_paper_size(paper_size) setup.set_orientation(Gtk.PageOrientation.LANDSCAPE) # PrintOperation print_ = Gtk.PrintOperation() print_.set_default_page_setup(setup) print_.set_unit(Gtk.Unit.MM) print_.set_embed_page_setup(True) print_.connect("begin_print", self.begin_print) print_.connect("draw_page", self.draw_page) print_.connect("create-custom-widget", self.create_custom_widget) print_.connect("custom-widget-apply", self.custom_widget_apply) print_.set_custom_tab_label("Font") if action == Gtk.PrintOperationAction.EXPORT: print_.set_export_filename(filename) res = print_.run(action,None) def create_custom_widget(self,*data): self.fontbutton = Gtk.FontButton() return self.fontbutton def custom_widget_apply(self,*data): self.font = self.fontbutton.get_font_name() desc = Pango.FontDescription.from_string(self.font) self.font_size = desc.get_size()/Pango.SCALE def begin_print(self, operation, context): width = context.get_width() height = context.get_height() self.layout = context.create_pango_layout() self.layout.set_font_description(Pango.FontDescription(self.font)) self.layout.set_width(int(width*Pango.SCALE)) self.layout.set_text(self.text_to_print,len(self.text_to_print)) num_lines = self.layout.get_line_count() self.lines_per_page = math.floor(context.get_height() / (self.font_size/2)) pages = ( int(math.ceil( float(num_lines) / float(self.lines_per_page) ) ) ) operation.set_n_pages(pages) def draw_page (self, operation, context, page_number): cr = context.get_cairo_context() cr.set_source_rgb(0, 0, 0) start_line = page_number * self.lines_per_page if page_number + 1 != operation.props.n_pages: end_line = start_line + self.lines_per_page else: end_line = self.layout.get_line_count() cr.move_to(0, 0) iter = self.layout.get_iter() i=0 while 1: if i > start_line: #Must be get_line_readonly line = iter.get_line_readonly() cr.rel_move_to(0, self.font_size/2) PangoCairo.show_layout_line(cr,line) i += 1 if not (i < end_line and iter.next_line()): break if __name__ == "__main__": data="" file = open("/usr/share/lios/readme.text","r") for x in file.readlines(): data = data + x action = Gtk.PrintOperationAction.PREVIEW printer = print_with_action(data,action) lios-3-2.7.2/lios/ui/gtk/terminal.py000066400000000000000000000064211345364566700172130ustar00rootroot00000000000000#!/usr/bin/python3 ########################################################################### # Lios - Linux-Intelligent-Ocr-Solution # Copyright (C) 2015-2016 Nalin.x.Linux GPL-3 # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ########################################################################### from gi.repository import Gtk, GObject, Vte from gi.repository import GLib from gi.repository import Gdk class Terminal(Vte.Terminal): def __init__(self,path): super(Terminal,self).__init__() if hasattr(self, 'spawn_sync'): self.spawn_sync(Vte.PtyFlags.DEFAULT, #default is fine path, #where to start the command? ["/bin/sh"], #where is the emulator? [], #it's ok to leave this list empty GLib.SpawnFlags.DO_NOT_REAP_CHILD, None, #at least None is required None); else: self.fork_command_full(Vte.PtyFlags.DEFAULT, #default is fine path, #where to start the command? ["/bin/sh"], #where is the emulator? [], #it's ok to leave this list empty GLib.SpawnFlags.DO_NOT_REAP_CHILD, None, #at least None is required None); def run_command(self,command): command = command+"\n" length = len(command) self.feed_child(command, length) def connect_child_exit(self,function): self.connect ("child-exited", function) def connect_context_menu_button_callback(self,function): def fun(widget,event): if ((event.type == Gdk.EventType.BUTTON_RELEASE and event.button == 3) or (event.type == Gdk.EventType.KEY_PRESS and event.hardware_keycode == 135)): function() self.connect("button-release-event",fun) self.connect("key-press-event",fun) class TheWindow(Gtk.Window): def __init__(self): Gtk.Window.__init__(self, title="inherited cell renderer") self.set_default_size(600, 300) self.terminal = Terminal("~/home") #Set up a button to click and run a demo command self.button = Gtk.Button("Do The Command") self.button.connect("clicked", self.InputToTerm) #end demo command code #set up the interface box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL) box.pack_start(self.button, False, True, 0) #a scroll window is required for the terminal scroller = Gtk.ScrolledWindow() scroller.set_hexpand(True) scroller.set_vexpand(True) scroller.add(self.terminal) box.pack_start(scroller, False, True, 2) self.add(box) def InputToTerm(self, clicker): command = "echo \"Sending this command to a virtual terminal.\"" self.terminal.run_command(command); if (__name__ == "__main__"): win = TheWindow() win.connect("delete-event", Gtk.main_quit) win.show_all() Gtk.main() lios-3-2.7.2/lios/ui/gtk/text_view.py000066400000000000000000000244741345364566700174260ustar00rootroot00000000000000#!/usr/bin/python3 ########################################################################### # Lios - Linux-Intelligent-Ocr-Solution # Copyright (C) 2015-2016 Nalin.x.Linux GPL-3 # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ########################################################################### from gi.repository import Gtk from gi.repository import Gdk from gi.repository import GdkPixbuf from gi.repository import Pango class TextView(Gtk.TextView): AT_START=0 AT_CURSOR=1 AT_END=2 def __init__(self): super(TextView, self).__init__() self.set_wrap_mode(Gtk.WrapMode.WORD) buffer = self.get_buffer() self.highlight_tag = buffer.create_tag('Reading') def connect_insert(self,function): buffer = self.get_buffer() buffer.connect("insert-text",lambda x, y,z,a : function()) def connect_delete(self,function): buffer = self.get_buffer() buffer.connect("delete-range",lambda x, y,z : function()) def set_text(self,text): buffer = self.get_buffer() buffer.set_text(text); def get_text(self): buffer = self.get_buffer() start,end = buffer.get_bounds() text = buffer.get_text(start,end,False) return text # For Text Cleaner def get_text_from_cursor_to_end(self): buffer = self.get_buffer() end = buffer.get_end_iter() mark = buffer.get_insert() start = buffer.get_iter_at_mark(mark) text = buffer.get_text(start,end,False) return text def delete_text_from_cursor_to_end(self): buffer = self.get_buffer() end = buffer.get_end_iter() mark = buffer.get_insert() start = buffer.get_iter_at_mark(mark) buffer.delete(start,end) def insert_text(self,text,position,place_cursor=False): buffer = self.get_buffer() if (position == TextView.AT_START): iter = buffer.get_start_iter() buffer.insert(iter,text) elif position == TextView.AT_CURSOR: buffer.insert_at_cursor(text) else: iter = buffer.get_end_iter() buffer.insert(iter,text) def set_highlight_font(self,highlight_font): self.highlight_tag.set_property('font',highlight_font) def set_highlight_color(self,highlight_color): self.highlight_tag.set_property('foreground', Gdk.color_parse(highlight_color).to_string()) def set_highlight_background(self,background_highlight_color): self.highlight_tag.set_property('background', Gdk.color_parse(background_highlight_color).to_string()) def set_font(self,font_discription): pangoFont = Pango.FontDescription(font_discription) self.modify_font(pangoFont) def set_font_color(self,font_color): self.modify_fg(Gtk.StateFlags.NORMAL, Gdk.color_parse(font_color)) def set_background_color(self,background_color): self.modify_bg(Gtk.StateFlags.NORMAL, Gdk.color_parse(background_color)) def get_cursor_line_number(self): buffer = self.get_buffer() insert_mark = buffer.get_insert() offset = buffer.get_iter_at_mark(insert_mark) return offset.get_line() def get_line_count(self): buffer = self.get_buffer() return buffer.get_line_count() def move_cursor_to_line(self,line_number): buffer = self.get_buffer() iter = buffer.get_iter_at_line(line_number) buffer.place_cursor(iter) self.scroll_to_iter(iter, 0.0,False,0.0,0.0) def get_modified(self): buffer = self.get_buffer() return buffer.get_modified() def set_modified(self,value): buffer = self.get_buffer() buffer.set_modified(value) def has_selection(self): buffer = self.get_buffer() return buffer.get_has_selection() def get_selected_text(self): buffer = self.get_buffer() start,end = buffer.get_selection_bounds() return buffer.get_text(start,end,0) def delete_all_text(self): buffer = self.get_buffer() start, end = buffer.get_bounds() buffer.delete(start, end) # Placing a bookmark def get_mark_at_line(self,line): buffer = self.get_buffer() iter = buffer.get_iter_at_line(line) return buffer.create_mark(None,iter,True) # Moving to existing bookmark def move_cursor_to_mark(self,mark): buffer = self.get_buffer() iter = buffer.get_iter_at_mark(mark) buffer.place_cursor(iter) self.scroll_to_iter(iter, 0.0,False,0.0,0.0) # For saving Bookmark with line number def get_line_number_of_mark(self,mark): buffer = self.get_buffer() iter = buffer.get_iter_at_mark(mark) return iter.get_line() def get_cursor_mark(self): buffer = self.get_buffer() return buffer.get_insert() # For autofilling new bookmark name def get_current_line_text(self): buffer = self.get_buffer() mark = buffer.get_insert() start_iter = buffer.get_iter_at_mark(mark) end_iter = start_iter.copy() start_iter.backward_sentence_start() end_iter.forward_to_line_end() return buffer.get_text(start_iter,end_iter,True) # For highlighting bookmark position and go-to-line def highlights_cursor_line(self): buffer = self.get_buffer() self.remove_all_highlights() mark = buffer.get_insert() start_iter = buffer.get_iter_at_mark(mark) end_iter = start_iter.copy() end_iter.forward_to_line_end() self.scroll_to_iter(start_iter, 0.0,False,0.0,0.0) buffer.apply_tag(self.highlight_tag, start_iter, end_iter) #Find , Find and Replace , Spell check , TextReader def remove_all_highlights(self): buffer = self.get_buffer() start = buffer.get_start_iter() end = buffer.get_end_iter() buffer.remove_tag(self.highlight_tag, start, end) def replace_last_word(self,replace_word): buffer = self.get_buffer() buffer.delete(self.start_iter, self.end_iter) buffer.insert(self.start_iter," "+replace_word) self.start_iter = self.end_iter.copy() def get_next_word(self): buffer = self.get_buffer() insert_mark = buffer.get_insert() self.start_iter = buffer.get_iter_at_mark(insert_mark) self.end_iter = self.start_iter.copy() iter0 = self.start_iter.copy() iter0.backward_word_start() self.remove_all_highlights() self.end_iter.forward_word_end() buffer.apply_tag(self.highlight_tag, self.start_iter, self.end_iter) buffer.place_cursor(self.end_iter) return buffer.get_text(self.start_iter,self.end_iter,0) def get_previous_word(self): buffer = self.get_buffer() insert_mark = buffer.get_insert() self.end_iter = buffer.get_iter_at_mark(insert_mark) self.start_iter = self.end_iter.copy() iter0 = self.end_iter.copy() iter0.forward_word_end() self.remove_all_highlights() self.start_iter.backward_word_start () buffer.apply_tag(self.highlight_tag, self.start_iter, self.end_iter) buffer.place_cursor(self.start_iter) return buffer.get_text(self.start_iter,self.end_iter,0) def get_context_text(self): buffer = self.get_buffer() insert_mark = buffer.get_insert() iter1 = buffer.get_iter_at_mark(insert_mark) iter2 = iter1.copy() iter1.backward_sentence_start() iter2.forward_sentence_end() return buffer.get_text(iter1,iter2,0) def delete_last_word(self): buffer = self.get_buffer() buffer.delete(self.start_iter,self.end_iter) def get_next_sentence(self): buffer = self.get_buffer() insert_mark = buffer.get_insert() iter1 = buffer.get_iter_at_mark(insert_mark) iter2 = iter1.copy() end = buffer.get_end_iter() self.remove_all_highlights() lineString = "" # Get text word by word till a full stop followed by a space, CR or LF found. # If no full stop found, stop at minimum of 1000 more chars # Full Stop for English(u002e), Devanagari(u0964), Sinhala(u0df4), # Chinese/Japanese(u3002), Arabic(u06d4) # Space - 0020, Carriage return(CR) - 000d , line feed (LF) - 000a while( '\u002e\u0020' not in lineString \ and '\u002e\u000d' not in lineString \ and '\u002e\u000a' not in lineString \ and '\u0964\u0020' not in lineString \ and '\u0964\u000d' not in lineString \ and '\u0964\u000a' not in lineString \ and '\u0df4\u0020' not in lineString \ and '\u0df4\u000d' not in lineString \ and '\u0df4\u000a' not in lineString \ and '\u3002\u0020' not in lineString \ and '\u3002\u000a' not in lineString \ and '\u3002\u000d' not in lineString \ and '\u06d4\u0020' not in lineString \ and '\u06d4\u000a' not in lineString \ and '\u06d4\u000d' not in lineString \ and len(lineString) < 1000 and not end.equal(iter2)): iter2.forward_char() lineString = buffer.get_text(iter1,iter2,0) buffer.apply_tag(self.highlight_tag, iter1, iter2) buffer.place_cursor(iter2) return buffer.get_text(iter1,iter2,0) def is_cursor_at_end(self): buffer = self.get_buffer() insert_mark = buffer.get_insert() iter1 = buffer.get_iter_at_mark(insert_mark) end = buffer.get_end_iter() if(end.equal(iter1)): return 1; else: return 0; def is_cursor_at_start(self): buffer = self.get_buffer() insert_mark = buffer.get_insert() iter1 = buffer.get_iter_at_mark(insert_mark) start = buffer.get_start_iter() if(start.equal(iter1)): return 1; else: return 0; # For Find/Find and Replace def move_forward_to_word(self,word): buffer = self.get_buffer() insert_mark = buffer.get_insert() self.start_iter = buffer.get_iter_at_mark(insert_mark) result = self.start_iter.forward_search(word, 0, None) if (result): self.start_iter, self.end_iter = result buffer.place_cursor(self.end_iter) self.remove_all_highlights() buffer.apply_tag(self.highlight_tag, self.start_iter, self.end_iter) self.scroll_to_iter(self.start_iter,00,False,False,False) return True return False def move_backward_to_word(self,word): buffer = self.get_buffer() insert_mark = buffer.get_insert() self.start_iter = buffer.get_iter_at_mark(insert_mark) self.end_iter = self.start_iter.copy() result = self.start_iter.backward_search(word, 0, None) if (result): self.start_iter, self.end_iter = result buffer.place_cursor(self.start_iter) self.remove_all_highlights() buffer.apply_tag(self.highlight_tag, self.start_iter, self.end_iter) self.scroll_to_iter(self.start_iter,00,False,False,False) return True return False lios-3-2.7.2/lios/ui/gtk/tree_view.py000077500000000000000000000146221345364566700173760ustar00rootroot00000000000000#!/usr/bin/python3 ########################################################################### # Lios - Linux-Intelligent-Ocr-Solution # Copyright (C) 2015-2016 Nalin.x.Linux GPL-3 # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ########################################################################### from gi.repository import Gtk class CellRendererSpin(Gtk.CellRendererSpin): def __init__(self,pos): super(CellRendererSpin,self).__init__() self.pos = pos class CellRendererText(Gtk.CellRendererText): def __init__(self,pos): super(CellRendererText,self).__init__() self.pos = pos class CellRendererToggle(Gtk.CellRendererToggle): def __init__(self,pos): super(CellRendererToggle,self).__init__() self.pos = pos class TreeView(Gtk.TreeView): def __init__(self,name_type_tuple_list,function): super(TreeView,self).__init__() self.function = function; self.cursor_change_handler_id = None type_list = [] i = 0; for item in name_type_tuple_list: type_list.append(item[1]) if(item[1] == float): cell = CellRendererSpin(i) adjustment = Gtk.Adjustment(0, 0, 10000, 1, 10, 0) cell.set_property("adjustment", adjustment) cell.set_property("digits", 3) cell.connect("edited", self.on_float_edited) elif(item[1] == int): cell = CellRendererSpin(i) adjustment = Gtk.Adjustment(0, 0, 10000, 1, 10, 0) cell.set_property("adjustment", adjustment) cell.connect("edited", self.on_float_edited) elif(item[1] == bool): cell = CellRendererToggle(i) cell.set_radio(True) cell.connect("toggled", self.on_bool_edited) else: cell = CellRendererText(i) cell.connect("edited", self.on_edited) if(item[2] == True): cell.set_property("editable", True) col = Gtk.TreeViewColumn(item[0], cell, text=i) self.append_column(col) i = i + 1; self.rs = Gtk.ListStore(*type_list) self.set_model(self.rs); self.set_reorderable(True) #self.connect("cursor-changed",self.__treeview_image_cursor_changed) def append(self,item): self.rs.append(item); def remove(self,index): iter = self.rs.get_iter(index) self.rs.remove(iter); def set_list(self,list): if(self.cursor_change_handler_id): self.handler_block(self.cursor_change_handler_id) self.rs.clear() for item in list: self.rs.append(item) if(self.cursor_change_handler_id): self.handler_unblock(self.cursor_change_handler_id) def block_cursor_change_signal(self): if(self.cursor_change_handler_id): self.handler_block(self.cursor_change_handler_id) def unblock_cursor_change_signal(self): if(self.cursor_change_handler_id): self.handler_unblock(self.cursor_change_handler_id) #def set_selected_row(self,row): # self.handler_block(self.cursor_change_handler_id) # self.set_cursor(row); # self.handler_unblock(self.cursor_change_handler_id) def get_list(self): # list comprehension used to unpack Gtk.ListStore return [[ i for i in item ] for item in self.rs] def clear(self): self.rs.clear() def on_float_edited(self, widget, path, value): self.rs[path][widget.pos] = float(value) self.function(int(path)) def on_bool_edited(self, widget, path): self.rs[path][widget.pos] = True self.function(int(path)) def on_edited(self, widget, path, value): self.rs[path][widget.pos] = str(value) self.function(int(path)) def connect_update_callback(self,function): self.function = function def connect_cursor_change_function(self,function): self.cursor_change_handler_id = self.connect("cursor-changed", lambda x: function()) def connect_rows_reordered_function(self,function): self.rows_reordered_handler_id = self.connect("drag-end", lambda x,y: function()) def get_selected_row_index(self): item = self.get_selection() model,iter = item.get_selected() path = item.get_selected_rows()[0] if (iter == None): return 0; path = path.get_path(iter) return(path.get_indices()[0]); def set_column_visible(self,column_number, value): column = self.get_column(column_number); column.set_visible(value); class TestWindow(Gtk.Window): def function(self,row): print(row) print(self.tv.get_list()) def __init__(self): Gtk.Window.__init__(self, title="Hello World") self.tv = TreeView([("X",float,True),("Y",float,True),("Width",float,True),("Height",float,True),("Letter",str,True)],self.function) self.tv.append([10,20,40,40,"a"]); self.tv.append([20,30,40,40,"b"]); self.box = Gtk.VBox(spacing=6) self.add(self.box) self.box.pack_start(self.tv, True, True, 0) self.button1 = Gtk.Button(label="Get List") self.button1.connect("clicked", self.on_button1_clicked) self.box.pack_start(self.button1, False, False, 0) self.button2 = Gtk.Button(label="Set List") self.button2.connect("clicked", self.on_button2_clicked) self.box.pack_start(self.button2, False, False, 0) self.button3 = Gtk.Button(label="Letter Show") self.button3.connect("clicked", self.on_button3_clicked) self.box.pack_start(self.button3, False, False, 0) self.button4 = Gtk.Button(label="Letter Hide") self.button4.connect("clicked", self.on_button4_clicked) self.box.pack_start(self.button4, False, False, 0) self.add(self.box) self.set_default_size(400,400); def on_button1_clicked(self, widget): print(self.tv.get_list()) def on_button2_clicked(self, widget): self.tv.set_list([(25,10,45,60)]) def on_button3_clicked(self, widget): self.tv.set_column_visible(4,True); def on_button4_clicked(self, widget): self.tv.set_column_visible(4,False); if __name__ == "__main__": win = TestWindow() win.connect("delete-event", Gtk.main_quit) win.show_all() Gtk.main() lios-3-2.7.2/lios/ui/gtk/widget.py000066400000000000000000000132151345364566700166620ustar00rootroot00000000000000#!/usr/bin/python3 ########################################################################### # Lios - Linux-Intelligent-Ocr-Solution # Copyright (C) 2015-2016 Nalin.x.Linux GPL-3 # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ########################################################################### from gi.repository import Gtk from gi.repository import GLib from gi.repository import Gdk from gi.repository import Atk from lios.ui.gtk import icon class Entry(Gtk.Entry): def __init__(self): super(Entry,self).__init__() def connect_change_handler(self,function): self.connect("changed",function) def connect_activate_function(self,function): self.connect("activate",function) #set_text() #get_text() class Label(Gtk.Label): def __init__(self,text): super(Label,self).__init__(text) #set_use_markup() class Button(Gtk.Button): def __init__(self,label): super(Button,self).__init__(label) def connect_function(self,function): self.connect("clicked",function) class IconButton(Gtk.Button): def __init__(self,label): super(IconButton,self).__init__() image = Gtk.Image() image.set_from_icon_name(icon.stock_icon_dict[label],8) self.set_image(image) self.set_hexpand(False) self.set_vexpand(False) def connect_function(self,function): self.connect("clicked",function) class SpinButton(Gtk.SpinButton): def __init__(self,value=1,lower=0,upper=100,step_incr=1,page_incr=5,page_size=0): super(SpinButton,self).__init__() adj = Gtk.Adjustment(value, lower, upper, step_incr, page_incr, page_size) self.set_adjustment(adj) self.set_value(value) def connect_function(self,function): self.connect("clicked",function) #def set_value(self,value): # self.set_value(value) def get_value(self): return self.get_value_as_int() class ComboBox(Gtk.ComboBoxText): def __init__(self): super(ComboBox,self).__init__() model = Gtk.ListStore(str) self.set_model(model) renderer_text = Gtk.CellRendererText() self.pack_start(renderer_text, True) def add_item(self,item): model = self.get_model() model.append([item]) def connect_change_callback_function(self,function): self.connect("changed",function); def clear(self): model = self.get_model() model.clear() #set_active class ListView(Gtk.TreeView): def __init__(self,title): super(ListView,self).__init__() model = Gtk.ListStore(str) self.set_model(model) renderer = Gtk.CellRendererText() column = Gtk.TreeViewColumn(title, renderer, text=0) self.append_column(column) def add_item(self,item): model = self.get_model() model.append([item]) def get_selected_item(self): tree_selection = self.get_selection() model,tree_iter = tree_selection.get_selected() return model.get_value(tree_iter,0) def get_selected_item_index(self): tree_selection = self.get_selection() model,tree_iter = tree_selection.get_selected() i = 0; for item in model: if item[0] == model[tree_iter][0]: return i; i = i + 1; return -1; def remove_selected_item(self): tree_selection = self.get_selection() model,tree_iter = tree_selection.get_selected() model.remove(tree_iter) def clear(self): model = self.get_model() model.clear() def connect_on_select_callback(self,function): self.connect("row-activated",function) class ColorButton(Gtk.ColorButton): def __init__(self): super(ColorButton,self).__init__() def set_color_from_string(self,color): self.set_color(Gdk.color_parse(color)) def get_color_as_string(self): return self.get_color().to_string(); class FontButton(Gtk.FontButton): def __init__(self): super(FontButton,self).__init__() def connect_function(self,function): self.connect("font-set",function) #set_font(font desc) #get_font_name() class Separator(Gtk.HSeparator): def __init__(self): super(Separator,self).__init__() class CheckButton(Gtk.CheckButton): def __int__(self,label): super(CheckButton,self).__int__() self.set_label(label) def connect_handler_function(self,function): self.connect("clicked",function) class ProgressBar(Gtk.ProgressBar): def __init__(self): super(ProgressBar,self).__init__() self.activity_mode = True a = GLib.timeout_add(20, self.progressbar_timeout, None) def progressbar_timeout(self, user_data): if self.activity_mode: self.pulse() #else: # new_value = self.get_fraction() + 0.01 # if new_value > 1: # new_value = 0 # self.set_fraction(new_value) return True def set_pulse_mode(self,mode): self.activity_mode = mode; class Statusbar(Gtk.Frame): def __init__(self): super(Statusbar,self).__init__() self.label = Gtk.Label() frame_inner = Gtk.Frame() frame_inner.add(self.label) atk_ob1 = frame_inner.get_accessible() atk_ob1.set_role(Atk.Role.NOTIFICATION) self.add(frame_inner) atk_ob = self.get_accessible() atk_ob.set_role(Atk.Role.STATUSBAR) def set_text(self,text): self.label.set_text(text) child = self.get_children()[0] atk_ob = child.get_accessible() atk_ob.notify_state_change(Atk.StateType.SHOWING,True); def set_line_wrap(self,val): self.label.set_line_wrap(val) lios-3-2.7.2/lios/ui/gtk/window.py000066400000000000000000000027651345364566700167160ustar00rootroot00000000000000#!/usr/bin/python3 ########################################################################### # Lios - Linux-Intelligent-Ocr-Solution # Copyright (C) 2015-2016 Nalin.x.Linux GPL-3 # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . ########################################################################### from gi.repository import Gtk from gi.repository import GdkPixbuf class Window(Gtk.Window): def __init__(self,title): super(Window,self).__init__() self.set_title(title) def connect_close_function(self,function): self.connect("delete-event",function) def connect_menubar(self,menubar): self.add_accel_group(menubar.get_accel_group()) def connect_configure_event_handler(self,function): self.connect("configure-event",function) def set_taskbar_icon(self,file_path): pixbuf = GdkPixbuf.Pixbuf.new_from_file(file_path) self.set_icon(pixbuf) #add() #get_size() lios-3-2.7.2/make_deb.sh000077500000000000000000000030511345364566700147400ustar00rootroot00000000000000version=`grep "Version: " control | sed '$s/Version: //g'` package=`grep "Package: " control | sed '$s/Package: //g'` architecture=`grep "Architecture: " control | sed '$s/Architecture: //g'` package_name=$package"_"$version"_"$architecture mkdir -p $package_name/DEBIAN mkdir -p $package_name/usr/lib/python3/dist-packages/lios/ git pull cp -r lios/* $package_name/usr/lib/python3/dist-packages/lios/ cp -r share $package_name/usr/ cp -r bin $package_name/usr/ printf "See commits : https://gitlab.com/Nalin-x-Linux/lios-3/commits/master\n\n" > $package_name/usr/share/doc/lios/changelog git log >> $package_name/usr/share/doc/lios/changelog gzip -n -9 $package_name/usr/share/doc/lios/changelog $package_name/usr/share/doc/lios/changelog.gz cp control postinst postrm $package_name/DEBIAN/ cd $package_name find -name "*~" -delete find . -type f ! -regex '.*.hg.*' ! -regex '.*?debian-binary.*' ! -regex '.*?DEBIAN.*' -printf '%P ' | xargs md5sum > DEBIAN/md5sums sudo chown -R root DEBIAN/postinst DEBIAN/postrm DEBIAN/md5sums usr/ sudo chgrp -R root DEBIAN/postinst DEBIAN/postrm DEBIAN/md5sums usr/ sudo chmod -R 0755 DEBIAN/postinst DEBIAN/postrm usr/ sudo chmod -R 0644 DEBIAN/md5sums usr/share/applications/Lios.desktop usr/share/applications/Tesseract-Trainer.desktop usr/share/doc/lios/* usr/share/menu/lios usr/share/man/man1/lios.1.gz usr/share/man/man1/train-tesseract.1.gz sudo chmod -R 0644 usr/share/lios/lios.png usr/share/lios/readme.text usr/share/lios/text_cleaner_list.text usr/share/pixmaps/lios.xpm cd ../ dpkg -b $package_name sudo rm -rf $package_name lios-3-2.7.2/po/000077500000000000000000000000001345364566700132715ustar00rootroot00000000000000lios-3-2.7.2/po/Linux-intelligent-ocr-solution.pot000066400000000000000000000513131345364566700220660ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR ORGANIZATION # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: \n" "POT-Creation-Date: 2018-04-29 08:51+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: pygettext.py 1.5\n" "X-Generator: Poedit 1.8.7.1\n" "X-Poedit-Basepath: ../lios\n" "X-Poedit-SearchPath-0: .\n" #: editor.py:50 msgid "Select" msgstr "" #: editor.py:51 msgid "Character Encoding : " msgstr "" #: editor.py:110 editor.py:112 msgid "Start new without saving ?" msgstr "" #: editor.py:111 msgid "Start-New!" msgstr "" #: editor.py:133 editor.py:803 train_tesseract.py:1082 msgid "Select the file to open" msgstr "" #: editor.py:154 train_tesseract.py:1071 msgid "Save " msgstr "" #: editor.py:187 msgid "Select the file to append" msgstr "" #: editor.py:196 msgid "Select the file to insert at cursor" msgstr "" #: editor.py:224 main.py:1209 msgid "Filename please" msgstr "" #: editor.py:234 msgid "Select the file to import" msgstr "" #: editor.py:244 msgid "Text Cleaner" msgstr "" #: editor.py:253 msgid "Give match and replace" msgstr "" #: editor.py:253 editor.py:504 editor.py:515 editor.py:742 editor.py:763 #: main.py:425 train_tesseract.py:518 msgid "Close!" msgstr "" #: editor.py:253 main.py:1301 train_tesseract.py:796 msgid "Ok" msgstr "" #: editor.py:254 msgid "Match : " msgstr "" #: editor.py:255 msgid "Replace : " msgstr "" #: editor.py:298 train_tesseract.py:163 train_tesseract.py:363 msgid "Add" msgstr "" #: editor.py:300 train_tesseract.py:234 msgid "Remove" msgstr "" #: editor.py:303 main.py:243 train_tesseract.py:172 train_tesseract.py:230 msgid "Import" msgstr "" #: editor.py:305 main.py:244 train_tesseract.py:175 train_tesseract.py:232 msgid "Export" msgstr "" #: editor.py:308 imageview.py:80 main.py:79 msgid "Clear" msgstr "" #: editor.py:310 main.py:262 msgid "Restore" msgstr "" #: editor.py:313 msgid "Apply from cursor" msgstr "" #: editor.py:316 msgid "Apply on entire text" msgstr "" #: editor.py:319 editor.py:390 editor.py:460 editor.py:716 preferences.py:418 #: train_tesseract.py:240 train_tesseract.py:363 train_tesseract.py:733 #: train_tesseract.py:832 msgid "Close" msgstr "" #: editor.py:349 editor.py:422 msgid "Bookmark Table" msgstr "" #: editor.py:350 editor.py:423 msgid "Select the bookmark" msgstr "" #: editor.py:381 editor.py:458 msgid "Jump" msgstr "" #: editor.py:384 msgid "Scroll Text to position" msgstr "" #: editor.py:387 editor.py:709 main.py:92 main.py:216 train_tesseract.py:166 msgid "Delete" msgstr "" #: editor.py:487 msgid "Select the bookmark file to import" msgstr "" #: editor.py:504 main.py:1050 msgid "Warning!" msgstr "" #: editor.py:505 msgid "File must be saved inorder to bookmark the text!" msgstr "" #: editor.py:515 msgid "Create new Bookmark" msgstr "" #: editor.py:515 main.py:249 msgid "Bookmark" msgstr "" #: editor.py:516 msgid "Name : " msgstr "" #: editor.py:542 editor.py:580 editor.py:644 msgid "Context label" msgstr "" #: editor.py:556 msgid " Find word : " msgstr "" #: editor.py:562 editor.py:620 msgid "Next" msgstr "" #: editor.py:564 editor.py:622 msgid "Previous" msgstr "" #: editor.py:572 editor.py:636 msgid "Find Dialog" msgstr "" #: editor.py:594 msgid "No match found" msgstr "" #: editor.py:609 msgid " word : " msgstr "" #: editor.py:612 msgid " Replace word : " msgstr "" #: editor.py:624 msgid "Replace" msgstr "" #: editor.py:626 msgid "Replace-All" msgstr "" #: editor.py:642 msgid "Suggestions" msgstr "" #: editor.py:699 msgid " Misspelled word : " msgstr "" #: editor.py:705 msgid "Change" msgstr "" #: editor.py:707 msgid "Change All" msgstr "" #: editor.py:711 msgid "Ignore" msgstr "" #: editor.py:713 msgid "Ignore All" msgstr "" #: editor.py:715 msgid "Add to user dict" msgstr "" #: editor.py:731 main.py:144 main.py:197 main.py:239 msgid "Spell-Check" msgstr "" #: editor.py:742 msgid "Go to line" msgstr "" #: editor.py:742 main.py:425 msgid "Go" msgstr "" #: editor.py:744 msgid "Line Number : " msgstr "" #: editor.py:763 msgid "Audio converter " msgstr "" #: editor.py:763 msgid "Convert" msgstr "" #: editor.py:767 msgid "Speed : " msgstr "" #: editor.py:771 msgid "Volume : " msgstr "" #: editor.py:775 msgid "Pitch : " msgstr "" #: editor.py:779 msgid "Split Time : " msgstr "" #: editor.py:785 msgid "Voice : " msgstr "" #: editor.py:828 msgid "Enter the file name" msgstr "" #: imageview.py:75 msgid "_Delete" msgstr "" #: imageview.py:77 msgid "Shortcut Alt+D" msgstr "" #: main.py:77 main.py:225 msgid "Take-Screenshot" msgstr "" #: main.py:78 main.py:224 msgid "Scan-Using-Webcam" msgstr "" #: main.py:78 main.py:231 msgid "_Recognize" msgstr "" #: main.py:82 msgid "Recognize" msgstr "" #: main.py:83 msgid "Recognize-With-Rotation" msgstr "" #: main.py:85 main.py:110 main.py:124 main.py:201 msgid "Rotate-Left" msgstr "" #: main.py:86 main.py:109 main.py:123 main.py:204 msgid "Rotate-Twice" msgstr "" #: main.py:87 main.py:108 main.py:122 main.py:207 msgid "Rotate-Right" msgstr "" #: main.py:88 main.py:210 msgid "Invert-List" msgstr "" #: main.py:89 main.py:143 main.py:187 main.py:212 main.py:260 msgid "Save" msgstr "" #: main.py:90 main.py:214 msgid "Export-As-Pdf" msgstr "" #: main.py:111 main.py:125 train_tesseract.py:1017 msgid "Zoom-In" msgstr "" #: main.py:111 main.py:125 train_tesseract.py:1019 msgid "Zoom-Fit" msgstr "" #: main.py:112 main.py:126 train_tesseract.py:1021 msgid "Zoom-Out" msgstr "" #: main.py:113 main.py:129 main.py:234 msgid "Recognize-Selected-Areas" msgstr "" #: main.py:114 main.py:130 main.py:232 msgid "Recognize-Current-Image" msgstr "" #: main.py:115 main.py:131 main.py:233 msgid "Recognize-Current-Image-With-Rotation" msgstr "" #: main.py:127 msgid "Train-Selected-Areas" msgstr "" #: main.py:128 msgid "Save-Selected-Areas" msgstr "" #: main.py:142 main.py:185 msgid "New" msgstr "" #: main.py:145 main.py:191 msgid "Redo" msgstr "" #: main.py:145 main.py:191 msgid "Undo" msgstr "" #: main.py:147 main.py:194 msgid "Find" msgstr "" #: main.py:148 main.py:195 msgid "Find-Replace" msgstr "" #: main.py:150 main.py:253 msgid "Start/Stop-Reader" msgstr "" #: main.py:152 main.py:199 msgid "Go-To-Line" msgstr "" #: main.py:153 main.py:199 msgid "Go-To-Page" msgstr "" #: main.py:185 msgid "_File" msgstr "" #: main.py:186 msgid "Open" msgstr "" #: main.py:187 msgid "Save-As" msgstr "" #: main.py:188 msgid "Export-Text-As-Pdf" msgstr "" #: main.py:188 msgid "Print" msgstr "" #: main.py:189 msgid "Print-Preview" msgstr "" #: main.py:190 main.py:279 msgid "Quit" msgstr "" #: main.py:191 msgid "_Edit" msgstr "" #: main.py:193 msgid "Append-Text" msgstr "" #: main.py:193 msgid "Punch-Text" msgstr "" #: main.py:200 msgid "Preferences" msgstr "" #: main.py:201 msgid "_Image" msgstr "" #: main.py:201 main.py:204 main.py:207 msgid "Current" msgstr "" #: main.py:202 main.py:205 main.py:208 msgid "Selected" msgstr "" #: main.py:203 main.py:206 main.py:209 msgid "All" msgstr "" #: main.py:212 main.py:214 main.py:216 msgid "Selected-Images" msgstr "" #: main.py:213 main.py:215 main.py:217 msgid "All-Images" msgstr "" #: main.py:218 msgid "_Scan" msgstr "" #: main.py:218 main.py:271 msgid "Update-Scanner-List" msgstr "" #: main.py:219 msgid "Scan-Image" msgstr "" #: main.py:220 msgid "Scan-Image-Repeatedly" msgstr "" #: main.py:221 msgid "Scan-and-Ocr" msgstr "" #: main.py:222 msgid "Scan-and-Ocr-Repeatedly" msgstr "" #: main.py:223 msgid "Optimise-Scanner-Brightness" msgstr "" #: main.py:226 main.py:229 msgid "Selection" msgstr "" #: main.py:227 main.py:230 msgid "Full" msgstr "" #: main.py:228 msgid "Take-and-Recognize-Screenshot" msgstr "" #: main.py:235 msgid "Recognize-Selected-Images" msgstr "" #: main.py:236 msgid "Recognize-All-Images" msgstr "" #: main.py:237 msgid "Recognize-Selected-with-rotation" msgstr "" #: main.py:238 msgid "Recognize-All-with-rotation" msgstr "" #: main.py:239 msgid "_Tools" msgstr "" #: main.py:240 msgid "Train-Tesseract" msgstr "" #: main.py:241 main.py:242 msgid "Text-Cleaner" msgstr "" #: main.py:245 msgid "Apply-From-Cursor" msgstr "" #: main.py:246 msgid "Apply-Entire" msgstr "" #: main.py:247 msgid "Audio-Converter" msgstr "" #: main.py:248 msgid "Dictionary" msgstr "" #: main.py:250 msgid "Bookmark-Table" msgstr "" #: main.py:251 msgid "Import-Bookmarks" msgstr "" #: main.py:252 msgid "Bookmark-Table-Complete" msgstr "" #: main.py:254 msgid "Increase-Reader-Speed" msgstr "" #: main.py:255 msgid "Decrease-Reader-Speed" msgstr "" #: main.py:256 msgid "Stop-All-Process" msgstr "" #: main.py:257 msgid "Preferences-General" msgstr "" #: main.py:257 main.py:276 msgid "_Preferences" msgstr "" #: main.py:258 msgid "Preferences-Recognition" msgstr "" #: main.py:259 msgid "Preferences-Scanning" msgstr "" #: main.py:261 msgid "Load" msgstr "" #: main.py:263 msgid "Help" msgstr "" #: main.py:263 msgid "Open-Readme" msgstr "" #: main.py:264 main.py:277 msgid "Video-Tutorials" msgstr "" #: main.py:265 msgid "Open-Home-Page" msgstr "" #: main.py:266 msgid "Get-Source-Code" msgstr "" #: main.py:267 main.py:278 msgid "About" msgstr "" #: main.py:273 msgid "Scan" msgstr "" #: main.py:337 msgid "Welcome to {} Version {}" msgstr "" #: main.py:425 msgid "Go to page" msgstr "" #: main.py:426 msgid "Page Number : " msgstr "" #: main.py:493 msgid "Extracting images from Pdf" msgstr "" #: main.py:515 main.py:636 msgid "Completed!" msgstr "" #: main.py:603 msgid "Getting devices" msgstr "" #: main.py:621 msgid "Setting Scanner {}" msgstr "" #: main.py:641 msgid "No Scanner Detected!" msgstr "" #: main.py:685 main.py:1036 main.py:1095 main.py:1120 main.py:1164 main.py:1284 msgid "completed!" msgstr "" #: main.py:695 main.py:877 msgid "No Scanner Detected!. Please update scanner list and try again" msgstr "" #: main.py:698 msgid "Scanning {} with resolution={} brightness={}" msgstr "" #: main.py:708 msgid "Scan Completed!" msgstr "" #: main.py:712 msgid "Adding image to list" msgstr "" #: main.py:716 msgid "Image added" msgstr "" #: main.py:794 main.py:832 msgid "Recognizing {}" msgstr "" #: main.py:801 main.py:845 msgid "Page {}" msgstr "" #: main.py:820 msgid "#Scanning" msgstr "" #: main.py:825 msgid "#Scan Compleated" msgstr "" #: main.py:831 msgid "#Running OCR" msgstr "" #: main.py:834 msgid "#Placing text and cursor" msgstr "" #: main.py:839 msgid "#Placing text and cursor Finished" msgstr "" #: main.py:840 msgid "#Redraw" msgstr "" #: main.py:842 msgid "#Redraw Compleated" msgstr "" #: main.py:847 msgid "#Preview Updated" msgstr "" #: main.py:856 msgid "#Compleated " msgstr "" #: main.py:857 msgid "Compleated" msgstr "" #: main.py:883 msgid "Scanning with resolution={} brightness={} for detecting angle of rotation" msgstr "" #: main.py:903 msgid "Optimize Scanner-Brightness" msgstr "" #: main.py:904 msgid "Optimize" msgstr "" #: main.py:905 preferences.py:418 msgid "Apply" msgstr "" #: main.py:906 main.py:1137 msgid "Cancel" msgstr "" #: main.py:908 msgid "Angle to be rotated : " msgstr "" #: main.py:916 msgid "Current-Value" msgstr "" #: main.py:920 preferences.py:284 msgid "Start" msgstr "" #: main.py:924 msgid "Distance" msgstr "" #: main.py:928 preferences.py:286 msgid "End" msgstr "" #: main.py:932 msgid "Result" msgstr "" #: main.py:954 msgid "Set Mode of rotation" msgstr "" #: main.py:955 msgid "Yes set this rotation" msgstr "" #: main.py:956 msgid "No continue with existing mode" msgstr "" #: main.py:965 msgid "Rotation mode changed to manual at angle {} degree" msgstr "" #: main.py:1014 msgid "Got {} words at brightness {}. Scanning with resolution={} brightness={}" msgstr "" #: main.py:1017 msgid "Scanning with resolution={} brightness={}" msgstr "" #: main.py:1030 msgid "Recognizing {0}test.pnm" msgstr "" #: main.py:1051 train_tesseract.py:261 train_tesseract.py:367 #: train_tesseract.py:700 train_tesseract.py:712 train_tesseract.py:733 #: train_tesseract.py:889 train_tesseract.py:1155 msgid "No" msgstr "" #: main.py:1051 train_tesseract.py:261 train_tesseract.py:368 #: train_tesseract.py:700 train_tesseract.py:712 train_tesseract.py:733 #: train_tesseract.py:889 train_tesseract.py:1154 msgid "Yes" msgstr "" #: main.py:1052 msgid "Current text not saved! do you want to load readme without saving ? " msgstr "" #: main.py:1075 msgid "Running OCR on selected image {}" msgstr "" #: main.py:1110 msgid "Running OCR on selected image {} (without rotating)" msgstr "" #: main.py:1137 msgid "Deleting !" msgstr "" #: main.py:1137 msgid "Yes Delete" msgstr "" #: main.py:1138 msgid "Are you sure you want to delete selected images ?" msgstr "" #: main.py:1151 msgid "Nothing selected" msgstr "" #: main.py:1160 msgid "Rotating selected image {} to {}" msgstr "" #: main.py:1217 msgid "Select Folder to save images" msgstr "" #: main.py:1233 msgid "Give pdf filename(with extention) to save images" msgstr "" #: main.py:1271 msgid "Running OCR on selected Area [ X={} Y={} Width={} Height={} ]" msgstr "" #: main.py:1301 msgid "Dictionary not found!" msgstr "" #: main.py:1302 msgid "" "Please install aspell, ispell, hunspell, myspell, or uspell \n" "dictionary for your language({0}) and restart Lios!\n" "Otherwise spellchecker and auto-rotation will work with english(fallback). \n" "\n" "For example on debian based system one can install aspell or \n" "hunspell french dictionary using following commands\n" "apt-get install aspell-fr\n" "apt-get install hunspell-fr\n" "\t\t\n" "or ispell dict using \n" "apt-get install ifrench \n" " \n" "On rpm based system use \n" "yum install aspell-fr\n" "\t\t\t\n" "On arch based system use \n" "pacman -S aspell-fr" msgstr "" #: main.py:1340 msgid "save_preferences as " msgstr "" #: main.py:1345 msgid "Preferences saved to " msgstr "" #: main.py:1351 msgid "Select the image" msgstr "" #: main.py:1357 msgid "Preferences loaded from " msgstr "" #: main.py:1364 msgid "Preferences Restored" msgstr "" #: main.py:1382 msgid "Select files to open" msgstr "" #: main.py:1462 msgid "" "Lios is a free and open source software\n" " \t\t\tfor converting print into text using a scanner or camara.\n" "\t\t\tIt can also produce text from other sources. Such as images,\n" "\t\t\tPdf, or screenshot. Program is given total accessibility \n" "\t\t\tfor visually impaired. Lios is written in python3 and we release \n" "\t\t\tit under GPL3 licence. There are great many possibilities\n" "\t\t\tfor this program. Feedback is the key to it." msgstr "" #: main.py:1472 msgid "Visit Home Page" msgstr "" #: preferences.py:186 train_tesseract.py:408 msgid "Font" msgstr "" #: preferences.py:191 msgid "Font Color" msgstr "" #: preferences.py:197 msgid "Background Color" msgstr "" #: preferences.py:203 msgid "Highlight Font" msgstr "" #: preferences.py:208 msgid "Highlight Color" msgstr "" #: preferences.py:213 msgid "Highlight Background" msgstr "" #: preferences.py:218 msgid "Speech-Module" msgstr "" #: preferences.py:225 msgid "Speech-Language" msgstr "" #: preferences.py:231 msgid "Speech-Rate" msgstr "" #: preferences.py:234 msgid "Speech-Volume" msgstr "" #: preferences.py:237 msgid "Speech-Pitch" msgstr "" #: preferences.py:255 msgid "General" msgstr "" #: preferences.py:260 msgid "Engine" msgstr "" #: preferences.py:269 msgid "Language" msgstr "" #: preferences.py:278 msgid "Run Text Cleaner" msgstr "" #: preferences.py:282 msgid "Insert Position" msgstr "" #: preferences.py:285 msgid "Cursor" msgstr "" #: preferences.py:294 msgid "Mode Of Rotation" msgstr "" #: preferences.py:296 msgid "Full Automatic" msgstr "" #: preferences.py:297 msgid "Partial Automatic" msgstr "" #: preferences.py:298 msgid "Manual" msgstr "" #: preferences.py:303 msgid "Angle" msgstr "" #: preferences.py:305 msgid "00" msgstr "" #: preferences.py:306 msgid "90" msgstr "" #: preferences.py:307 msgid "180" msgstr "" #: preferences.py:308 msgid "270" msgstr "" #: preferences.py:315 msgid "Page Numbering Type" msgstr "" #: preferences.py:317 msgid "Single Page" msgstr "" #: preferences.py:318 msgid "Double Page" msgstr "" #: preferences.py:323 msgid "Starting Page Number" msgstr "" #: preferences.py:341 msgid "Recognition" msgstr "" #: preferences.py:351 train_tesseract.py:477 msgid "Resolution" msgstr "" #: preferences.py:356 msgid "Brightness" msgstr "" #: preferences.py:361 msgid "Scan Area" msgstr "" #: preferences.py:364 msgid "Full Scan Area" msgstr "" #: preferences.py:365 msgid "Three Quarters" msgstr "" #: preferences.py:366 msgid "Two Quarters" msgstr "" #: preferences.py:367 msgid "One Quarters" msgstr "" #: preferences.py:370 msgid "Driver" msgstr "" #: preferences.py:381 msgid "Number of Pages to Scan" msgstr "" #: preferences.py:386 msgid "Time Bitween Repeted Scanning" msgstr "" #: preferences.py:393 msgid "Change to binary or lineart if possible" msgstr "" #: preferences.py:396 msgid "Cache Calibration" msgstr "" #: preferences.py:412 msgid "Scanning" msgstr "" #: preferences.py:418 msgid "Lios Preferences" msgstr "" #: train_tesseract.py:52 msgid "Tesseract Trainer" msgstr "" #: train_tesseract.py:57 msgid "Tesseract is not installed" msgstr "" #: train_tesseract.py:64 msgid "" "Tesseract training executable are not installed. \n" "Please make sure following exicutables are installed\n" "\n" "combine_tessdata, unicharset_extractor, shapeclustering, mftraining, cntraining and text2image.\n" "\n" "If you forget to build training tools then use 'make training' and 'sudo make training-install' to build it " msgstr "" #: train_tesseract.py:82 msgid "Copy" msgstr "" #: train_tesseract.py:83 msgid "Paste" msgstr "" #: train_tesseract.py:153 msgid "Train images-box" msgstr "" #: train_tesseract.py:160 train_tesseract.py:832 msgid "Train" msgstr "" #: train_tesseract.py:169 msgid "Delete-All" msgstr "" #: train_tesseract.py:220 msgid "Dictionary's" msgstr "" #: train_tesseract.py:222 msgid "Language " msgstr "" #: train_tesseract.py:226 msgid "Tessdata directory " msgstr "" #: train_tesseract.py:260 msgid "Search entire filesystem for tessdata ?" msgstr "" #: train_tesseract.py:262 msgid "" "Do you want to search entire filesystem for tessdata ?\n" "This may take awhile!" msgstr "" #: train_tesseract.py:362 msgid "Add new ambiguous" msgstr "" #: train_tesseract.py:370 msgid "Match " msgstr "" #: train_tesseract.py:371 msgid "Replace " msgstr "" #: train_tesseract.py:372 msgid "Mandatory" msgstr "" #: train_tesseract.py:387 msgid "Select files to import" msgstr "" #: train_tesseract.py:398 train_tesseract.py:601 msgid "Save filename" msgstr "" #: train_tesseract.py:414 msgid "Choose-Font-File" msgstr "" #: train_tesseract.py:429 msgid "Select font file" msgstr "" #: train_tesseract.py:443 msgid "Select input file" msgstr "" #: train_tesseract.py:458 msgid "Font Size" msgstr "" #: train_tesseract.py:461 msgid "Input Text File" msgstr "" #: train_tesseract.py:464 msgid "Choose" msgstr "" #: train_tesseract.py:467 msgid "Writing Mode" msgstr "" #: train_tesseract.py:474 msgid "Inter-character space" msgstr "" #: train_tesseract.py:480 msgid "Degrade-image" msgstr "" #: train_tesseract.py:482 msgid "Exposure-Level" msgstr "" #: train_tesseract.py:485 msgid "Ligatur-Mode" msgstr "" #: train_tesseract.py:518 msgid "Generate" msgstr "" #: train_tesseract.py:518 msgid "Generate-Image" msgstr "" #: train_tesseract.py:588 msgid "Select language file" msgstr "" #: train_tesseract.py:680 msgid "Select images to import" msgstr "" #: train_tesseract.py:699 msgid "No curresponding box files found!" msgstr "" #: train_tesseract.py:701 msgid "" "Do you want to auto annotate box file with existing language ?\n" "This may take awhile!" msgstr "" #: train_tesseract.py:711 msgid "No curresponding font_desc files found!" msgstr "" #: train_tesseract.py:713 msgid "Do you want to fill it with following font ?" msgstr "" #: train_tesseract.py:732 msgid "Delete file too ?" msgstr "" #: train_tesseract.py:734 msgid "Do you want to delete files(image,box,font_desc) too ?" msgstr "" #: train_tesseract.py:761 msgid " Alrady exist! Please edit name to avoid replacing" msgstr "" #: train_tesseract.py:762 msgid "Place it" msgstr "" #: train_tesseract.py:765 msgid "File Name : " msgstr "" #: train_tesseract.py:795 msgid "Error : running command failed" msgstr "" #: train_tesseract.py:831 msgid "Training images..." msgstr "" #: train_tesseract.py:888 msgid "Combine with dictionarys too ?" msgstr "" #: train_tesseract.py:890 msgid "" "Do you want to add dictionarys ? \t\t\n" "Do it if only all characters used in dictionarys are going to be trained!" msgstr "" #: train_tesseract.py:1023 msgid "Export-Boxes" msgstr "" #: train_tesseract.py:1025 msgid "Load-Boxes" msgstr "" #: train_tesseract.py:1125 msgid "Find :" msgstr "" #: train_tesseract.py:1154 msgid "Not found!" msgstr "" lios-3-2.7.2/po/fr.po000066400000000000000000001047421345364566700142500ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR ORGANIZATION # FIRST AUTHOR , YEAR. # msgid "" msgstr "" "Project-Id-Version: lios\n" "POT-Creation-Date: 2018-05-28 19:27+0100\n" "PO-Revision-Date: 2018-05-28 19:48+0100\n" "Last-Translator: L'Africain\n" "Language-Team: \n" "Language: fr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Generated-By: pygettext.py 1.5\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" "X-Generator: Poedit 1.8.7.1\n" "X-Poedit-SourceCharset: UTF-8\n" "X-Poedit-Basepath: ../lios\n" "X-Poedit-SearchPath-0: .\n" #: cam.py:36 msgid "Press take/close button at the right side" msgstr "Appuyer sur le bouton Prendre/Fermer sur le côté droit" #: cam.py:45 msgid "Take" msgstr "Prendre" #: cam.py:48 editor.py:319 editor.py:390 editor.py:457 editor.py:712 #: preferences.py:416 train_tesseract.py:240 train_tesseract.py:363 #: train_tesseract.py:733 train_tesseract.py:832 msgid "Close" msgstr "Fermer" #: editor.py:50 msgid "{} Decode error Select Other Character Encoding" msgstr "{} Erreur de décodage sélectionnez un autre encodage" #: editor.py:50 msgid "Select" msgstr "Sélectionner" #: editor.py:51 msgid "Character Encoding : " msgstr "Encodage : " #: editor.py:110 editor.py:112 msgid "Start new without saving ?" msgstr "Démarrer un nouveau sans enregistrer ?" #: editor.py:111 main.py:935 main.py:1166 msgid "Cancel" msgstr "Annuler" #: editor.py:111 msgid "Start-New!" msgstr "Démarrer un nouveau !" #: editor.py:133 train_tesseract.py:1082 msgid "Select the file to open" msgstr "Sélectionner le fichier à ouvrir" #: editor.py:154 train_tesseract.py:1071 msgid "Save " msgstr "Enregistrer " #: editor.py:187 msgid "Select the file to append" msgstr "Sélectionner le fichier à ajouter" #: editor.py:196 msgid "Select the file to insert at cursor" msgstr "Sélectionnez le fichier à insérer au curseur" #: editor.py:224 main.py:1238 msgid "Filename please" msgstr "Veuillez entrer un nom de fichier" #: editor.py:234 msgid "Select the file to import" msgstr "Sélectionner le fichier à importer" #: editor.py:244 msgid "Text Cleaner" msgstr "Nettoyage du texte" #: editor.py:246 msgid "Match" msgstr "Correspondance " #: editor.py:246 editor.py:621 msgid "Replace" msgstr "Remplacer" #: editor.py:253 msgid "Give match and replace" msgstr "Donner une correspondance et remplacer" #: editor.py:253 main.py:1329 train_tesseract.py:796 msgid "Ok" msgstr "Ok" #: editor.py:253 editor.py:501 editor.py:512 editor.py:738 editor.py:759 #: main.py:435 train_tesseract.py:518 msgid "Close!" msgstr "Fermer !" #: editor.py:254 msgid "Match : " msgstr "Correspondance : " #: editor.py:255 msgid "Replace : " msgstr "Remplacer : " #: editor.py:298 train_tesseract.py:163 train_tesseract.py:363 msgid "Add" msgstr "Ajouter" #: editor.py:300 train_tesseract.py:234 msgid "Remove" msgstr "Supprimer" #: editor.py:303 main.py:247 train_tesseract.py:172 train_tesseract.py:230 #: ui/gtk/icon.py:31 msgid "Import" msgstr "Importer" #: editor.py:305 main.py:248 train_tesseract.py:175 train_tesseract.py:232 #: ui/gtk/icon.py:32 msgid "Export" msgstr "Exporter" #: editor.py:308 imageview.py:80 main.py:79 ui/gtk/icon.py:68 msgid "Clear" msgstr "Vider" #: editor.py:310 main.py:266 ui/gtk/icon.py:97 msgid "Restore" msgstr "Restaurer" #: editor.py:313 msgid "Apply from cursor" msgstr "Appliquer depuis le curseur" #: editor.py:316 msgid "Apply on entire text" msgstr "Appliquer à tout le texte" #: editor.py:349 editor.py:422 msgid "Bookmark Table" msgstr "Liste des signets" #: editor.py:350 editor.py:423 msgid "Select the bookmark" msgstr "Sélectionner le signet" #: editor.py:381 editor.py:455 msgid "Jump" msgstr "Aller directement à" #: editor.py:384 msgid "Scroll Text to position" msgstr "Faire défiler le texte jusqu'à la position" #: editor.py:387 editor.py:705 main.py:92 main.py:220 train_tesseract.py:166 #: ui/gtk/icon.py:45 msgid "Delete" msgstr "Supprimer" #: editor.py:484 msgid "Select the bookmark file to import" msgstr "Sélectionner le fichier de signets à importer" #: editor.py:501 main.py:1079 msgid "Warning!" msgstr "Attention !" #: editor.py:502 msgid "File must be saved inorder to bookmark the text!" msgstr "Le fichier doit être sauvegardé pour en faire un signet !" #: editor.py:512 msgid "Create new Bookmark" msgstr "Créer un nouveau signet" #: editor.py:512 main.py:253 ui/gtk/icon.py:78 msgid "Bookmark" msgstr "Signet" #: editor.py:513 msgid "Name : " msgstr "Nom : " #: editor.py:539 editor.py:577 editor.py:641 msgid "Context label" msgstr "Étiquette contextuelle" #: editor.py:553 msgid " Find word : " msgstr "Rechercher un mot : " #: editor.py:559 editor.py:617 msgid "Next" msgstr "Suivant" #: editor.py:561 editor.py:619 msgid "Previous" msgstr "Précédent" #: editor.py:569 editor.py:633 msgid "Find Dialog" msgstr "Fenêtre de recherche" #: editor.py:591 msgid "No match found" msgstr "Aucune correspondance trouvée" #: editor.py:606 msgid " Word: " msgstr " Mot : " #: editor.py:609 msgid " Replace word: " msgstr "Mot de remplacement : " #: editor.py:623 msgid "Replace All" msgstr "Tout remplacer" #: editor.py:639 msgid "Suggestions" msgstr "Suggestions" #: editor.py:663 msgid "Spell Check finished" msgstr "Vérification orthographique terminée" #: editor.py:695 msgid " Misspelled word : " msgstr " Mot à corriger  : " #: editor.py:701 msgid "Change" msgstr "Modifier" #: editor.py:703 msgid "Change All" msgstr "Tout modifier" #: editor.py:707 msgid "Ignore" msgstr "Ignorer" #: editor.py:709 msgid "Ignore All" msgstr "Tout ignorer" #: editor.py:711 msgid "Add to user dict" msgstr "Ajouter au dico perso" #: editor.py:727 main.py:145 main.py:201 main.py:243 ui/gtk/icon.py:36 msgid "Spell-Check" msgstr "Vérification orthographique" #: editor.py:738 msgid "Go to line" msgstr "Aller à la ligne" #: editor.py:738 main.py:435 msgid "Go" msgstr "Aller" #: editor.py:740 msgid "Line Number : " msgstr "Numéro de ligne : " #: editor.py:759 msgid "Audio converter " msgstr "Convertisseur audio" #: editor.py:759 msgid "Convert" msgstr "Convertir" #: editor.py:763 msgid "Speed : " msgstr "Vitesse : " #: editor.py:767 msgid "Volume : " msgstr "Volume : " #: editor.py:771 msgid "Pitch : " msgstr "Niveau : " #: editor.py:775 msgid "Split Time : " msgstr "" #: editor.py:782 msgid "Voice : " msgstr "Voix : " #: editor.py:786 msgid "MP3 (liblame required)" msgstr "MP3 (liblame requit)" #: editor.py:787 msgid "WAV" msgstr "WAV" #: editor.py:789 msgid "Format : " msgstr "Format : " #: editor.py:809 main.py:89 main.py:144 main.py:191 main.py:216 main.py:264 #: ui/gtk/icon.py:26 msgid "Save" msgstr "Enregistrer" #: editor.py:837 msgid "Enter the file name" msgstr "Entrer le nom du fichier" #: imageview.py:58 main.py:206 main.py:209 main.py:212 msgid "Selected" msgstr "Sélectionné" #: imageview.py:59 msgid "X" msgstr "X" #: imageview.py:59 msgid "Y" msgstr "Y" #: imageview.py:60 msgid "Width" msgstr "Largeur" #: imageview.py:60 msgid "Height" msgstr "Hauteur" #: imageview.py:61 msgid "Letter" msgstr "Lettre" #: imageview.py:75 msgid "_Delete" msgstr "_Supprimer" #: imageview.py:77 msgid "Shortcut Alt+D" msgstr "Raccourci Alt+D" #: main.py:77 main.py:143 main.py:190 ui/gtk/icon.py:25 msgid "Open" msgstr "Ouvrir" #: main.py:77 main.py:229 ui/gtk/icon.py:90 msgid "Take-Screenshot" msgstr "Prendre-une-capture-d'écran" #: main.py:78 main.py:228 ui/gtk/icon.py:89 msgid "Scan-Using-Webcam" msgstr "Numériser avec la webcam" #: main.py:78 main.py:235 ui/gtk/icon.py:60 msgid "_Recognize" msgstr "_Reconnaître" #: main.py:82 ui/gtk/icon.py:59 msgid "Recognize" msgstr "Reconnaître" #: main.py:83 msgid "Recognize-With-Rotation" msgstr "Reconnaître-avec-rotation" #: main.py:85 main.py:110 main.py:127 main.py:205 ui/gtk/icon.py:51 msgid "Rotate-Left" msgstr "Pivoter-à-gauche" #: main.py:86 main.py:109 main.py:126 main.py:208 ui/gtk/icon.py:53 msgid "Rotate-Twice" msgstr "Pivoter-deux-fois" #: main.py:87 main.py:108 main.py:125 main.py:211 ui/gtk/icon.py:52 msgid "Rotate-Right" msgstr "Pivoter-à-droite" #: main.py:88 main.py:214 ui/gtk/icon.py:58 msgid "Invert-List" msgstr "Inverser-la-liste" #: main.py:90 main.py:218 ui/gtk/icon.py:71 msgid "Export-As-Pdf" msgstr "Exporter en pdf" #: main.py:111 main.py:128 train_tesseract.py:1017 ui/gtk/icon.py:48 msgid "Zoom-In" msgstr "Agrandir" #: main.py:111 main.py:128 train_tesseract.py:1019 ui/gtk/icon.py:49 msgid "Zoom-Fit" msgstr "Taille par défaut" #: main.py:112 main.py:129 train_tesseract.py:1021 ui/gtk/icon.py:50 msgid "Zoom-Out" msgstr "Diminuer" #: main.py:113 main.py:123 main.py:238 ui/gtk/icon.py:65 msgid "Recognize-Selected-Areas" msgstr "Reconnaître-les-zones-sélectionnées" #: main.py:114 main.py:122 main.py:236 ui/gtk/icon.py:66 msgid "Recognize-Current-Image" msgstr "Reconnaître-l'image-courante" #: main.py:115 main.py:124 main.py:237 ui/gtk/icon.py:67 msgid "Recognize-Current-Image-With-Rotation" msgstr "Reconnaître-l'image-courante-avec rotation" #: main.py:130 msgid "Train-Selected-Areas" msgstr "Former les zones sélectionnées" #: main.py:131 msgid "Save-Selected-Areas" msgstr "Enregistrer-les-zones-sélectionnées" #: main.py:143 main.py:189 ui/gtk/icon.py:24 msgid "New" msgstr "Nouveau" #: main.py:146 main.py:195 ui/gtk/icon.py:43 msgid "Undo" msgstr "Annuler" #: main.py:146 main.py:195 ui/gtk/icon.py:44 msgid "Redo" msgstr "Rétablir" #: main.py:148 main.py:198 ui/gtk/icon.py:28 msgid "Find" msgstr "Trouver" #: main.py:149 main.py:199 ui/gtk/icon.py:29 msgid "Find-Replace" msgstr "Rechercher-remplacer" #: main.py:151 main.py:257 ui/gtk/icon.py:37 msgid "Start/Stop-Reader" msgstr "Démarrer/Arrêter le lecteur" #: main.py:153 main.py:203 ui/gtk/icon.py:42 msgid "Go-To-Line" msgstr "Aller à la ligne" #: main.py:154 main.py:203 ui/gtk/icon.py:41 msgid "Go-To-Page" msgstr "Aller à la page" #: main.py:189 ui/gtk/icon.py:23 msgid "_File" msgstr "_Fichier" #: main.py:191 ui/gtk/icon.py:27 msgid "Save-As" msgstr "Enregistrer sous" #: main.py:192 ui/gtk/icon.py:70 msgid "Export-Text-As-Pdf" msgstr "Exporter le texte en pdf" #: main.py:192 ui/gtk/icon.py:69 msgid "Print" msgstr "Imprimer" #: main.py:193 ui/gtk/icon.py:72 msgid "Print-Preview" msgstr "Aperçu" #: main.py:194 main.py:283 ui/gtk/icon.py:73 msgid "Quit" msgstr "Quitter" #: main.py:195 ui/gtk/icon.py:74 msgid "_Edit" msgstr "_Édition" #: main.py:197 ui/gtk/icon.py:46 msgid "Punch-Text" msgstr "" #: main.py:197 ui/gtk/icon.py:47 msgid "Append-Text" msgstr "Ajouter-le-texte" #: main.py:204 ui/gtk/icon.py:93 msgid "Preferences" msgstr "Préférences" #: main.py:205 ui/gtk/icon.py:54 msgid "_Image" msgstr "_Image" #: main.py:205 main.py:208 main.py:211 msgid "Current" msgstr "Courant" #: main.py:207 main.py:210 main.py:213 msgid "All" msgstr "Tout" #: main.py:216 main.py:218 main.py:220 msgid "Selected-Images" msgstr "Images sélectionnées" #: main.py:217 main.py:219 main.py:221 msgid "All-Images" msgstr "Toutes les images" #: main.py:222 ui/gtk/icon.py:83 msgid "_Scan" msgstr "_Numériser" #: main.py:222 main.py:275 ui/gtk/icon.py:82 msgid "Update-Scanner-List" msgstr "Mettre à jour la liste des scanners" #: main.py:223 ui/gtk/icon.py:84 msgid "Scan-Image" msgstr "Numériser une image" #: main.py:224 ui/gtk/icon.py:85 msgid "Scan-Image-Repeatedly" msgstr "Numériser une image à plusieurs reprises" #: main.py:225 ui/gtk/icon.py:86 msgid "Scan-and-Ocr" msgstr "Numériser et ROC" #: main.py:226 ui/gtk/icon.py:87 msgid "Scan-and-Ocr-Repeatedly" msgstr "CNumérisation et ROC à plusieurs reprises" #: main.py:227 ui/gtk/icon.py:88 msgid "Optimise-Scanner-Brightness" msgstr "Optimiser la luminosité du scanneur" #: main.py:230 main.py:233 msgid "Selection" msgstr "Sélection" #: main.py:231 main.py:234 msgid "Full" msgstr "Tout" #: main.py:232 ui/gtk/icon.py:91 msgid "Take-and-Recognize-Screenshot" msgstr "Prendre-et-reconaître-une-capture-d'écran" #: main.py:239 ui/gtk/icon.py:61 msgid "Recognize-Selected-Images" msgstr "Reconnaître-les-images-sélectionnées" #: main.py:240 ui/gtk/icon.py:62 msgid "Recognize-All-Images" msgstr "Reconnaître-toutes-les-images" #: main.py:241 ui/gtk/icon.py:63 msgid "Recognize-Selected-with-rotation" msgstr "Reconnaître-la-selection-avec-rotation" #: main.py:242 ui/gtk/icon.py:64 msgid "Recognize-All-with-rotation" msgstr "Reconnaître-tout-avec-rotation" #: main.py:243 ui/gtk/icon.py:99 msgid "_Tools" msgstr "_Outils" #: main.py:244 ui/gtk/icon.py:35 msgid "Train-Tesseract" msgstr "" #: main.py:245 main.py:246 ui/gtk/icon.py:30 msgid "Text-Cleaner" msgstr "Nettoyage du texte" #: main.py:249 ui/gtk/icon.py:33 msgid "Apply-From-Cursor" msgstr "Appliquer depuis le curseur" #: main.py:250 ui/gtk/icon.py:34 msgid "Apply-Entire" msgstr "Appliquer à tout" #: main.py:251 ui/gtk/icon.py:101 msgid "Audio-Converter" msgstr "Convertisseur audio" #: main.py:252 ui/gtk/icon.py:100 msgid "Dictionary" msgstr "Dictionnaire" #: main.py:254 ui/gtk/icon.py:79 msgid "Bookmark-Table" msgstr "Liste des signets" #: main.py:255 ui/gtk/icon.py:80 msgid "Import-Bookmarks" msgstr "Importer des signets" #: main.py:256 ui/gtk/icon.py:81 msgid "Bookmark-Table-Complete" msgstr "Liste-des-signets-complète" #: main.py:258 ui/gtk/icon.py:38 msgid "Increase-Reader-Speed" msgstr "Augmenter la vitesse du lecteur" #: main.py:259 ui/gtk/icon.py:39 msgid "Decrease-Reader-Speed" msgstr "Ralentir la vitesse du lecteur" #: main.py:260 ui/gtk/icon.py:40 msgid "Stop-All-Process" msgstr "Arrêter tous les processus" #: main.py:261 main.py:280 ui/gtk/icon.py:92 msgid "_Preferences" msgstr "_Préférences" #: main.py:261 ui/gtk/icon.py:95 msgid "Preferences-General" msgstr "Préférences générales" #: main.py:262 ui/gtk/icon.py:96 msgid "Preferences-Recognition" msgstr "Préférences de reconnaissance" #: main.py:263 ui/gtk/icon.py:94 msgid "Preferences-Scanning" msgstr "Préférences de numérisation" #: main.py:265 ui/gtk/icon.py:98 msgid "Load" msgstr "Charger" #: main.py:267 ui/gtk/icon.py:102 msgid "Help" msgstr "Aide" #: main.py:267 ui/gtk/icon.py:103 msgid "Open-Readme" msgstr "Ouvrir le Readme" #: main.py:268 main.py:281 ui/gtk/icon.py:104 msgid "Video-Tutorials" msgstr "Tutoriels Vidéo" #: main.py:269 ui/gtk/icon.py:105 msgid "Open-Home-Page" msgstr "Ouvrir la page d'accueil" #: main.py:270 ui/gtk/icon.py:106 msgid "Get-Source-Code" msgstr "Obtenir le code source" #: main.py:271 main.py:282 ui/gtk/icon.py:107 msgid "About" msgstr "À propos" #: main.py:277 msgid "Scan" msgstr "Numériser" #: main.py:347 msgid "Welcome to {} Version {}" msgstr "Bienvenue dans {} Version {}" #: main.py:435 msgid "Go to page" msgstr "Aller à la page" #: main.py:436 msgid "Page Number : " msgstr "Numéro de page : " #: main.py:510 msgid "Select PDF Type" msgstr "Sélectionner le type de PDF" #: main.py:511 msgid "Containing images only" msgstr "Contient uniquement des images" #: main.py:512 msgid "Containing text or images" msgstr "Contient du texte ou des images" #: main.py:516 msgid "Please select PDF Type. Seems to me that {} is a {} PDF." msgstr "" "Veuillez selectionner un type de PDF. Il sembleq que {} soit un PDF {}." #: main.py:534 msgid "Extracting images from Pdf" msgstr "Extraction des images depuis le pdf" #: main.py:556 main.py:677 msgid "Completed!" msgstr "Terminé !" #: main.py:644 msgid "Getting devices" msgstr "Obtention des périphériques" #: main.py:662 msgid "Setting Scanner {}" msgstr "Paramètres du scanneur {}" #: main.py:682 msgid "No Scanner Detected!" msgstr "Aucun scanner détecté !" #: main.py:726 main.py:1065 main.py:1124 main.py:1149 main.py:1193 main.py:1312 msgid "completed!" msgstr "Terminé !" #: main.py:736 main.py:906 msgid "No Scanner Detected!. Please update scanner list and try again" msgstr "" "Aucun scanneur détecté ! Veuillez mettre à jour la liste des scanneurs et " "essayer à nouveau" #: main.py:739 msgid "Scanning {}, resolution {}, brightness {}" msgstr "Numérisation {}, résolution {}, luminosité {}" #: main.py:749 msgid "Scan Completed!" msgstr "Numérisation terminée !" #: main.py:832 main.py:867 msgid "Recognizing {}" msgstr "Reconnaissance {}" #: main.py:839 main.py:876 msgid "Page {}" msgstr "Page {}" #: main.py:886 msgid "Compleated" msgstr "Terminé" #: main.py:912 msgid "" "Scanning with resolution {}, brightness {}, for detecting angle of rotation." msgstr "" "Numérisation avec la résolution de {} et la luminosité de {} pour détecter " "l'angle de rotation." #: main.py:929 msgid "Click 'Optimize' to start optimisation " msgstr "Cliquer sur 'Optimiser' pour démarrer l'optimisation " #: main.py:932 msgid "Optimize Scanner-Brightness" msgstr "Optimiser la luminosité du scanneur" #: main.py:933 msgid "Optimize" msgstr "Optimiser" #: main.py:934 preferences.py:416 msgid "Apply" msgstr "Appliquer" #: main.py:937 msgid "Angle to be rotated : " msgstr "Angle à pivoter : " #: main.py:945 msgid "Current-Value" msgstr "Valeur actuelle" #: main.py:949 preferences.py:284 msgid "Start" msgstr "Début" #: main.py:953 msgid "Distance" msgstr "Distance" #: main.py:957 preferences.py:286 msgid "End" msgstr "Fin" #: main.py:961 msgid "Result" msgstr "Résultat" #: main.py:983 msgid "Set Mode of rotation" msgstr "Définir le motde de rotation" #: main.py:984 msgid "Yes set this rotation" msgstr "Oui définir cette rotation" #: main.py:985 msgid "No continue with existing mode" msgstr "Non continuer avec le mode existant" #: main.py:986 msgid "" "Do you want to fix the angle at {}\t\t\t\t\n" "degree manual rotation ?" msgstr "" "Voulez-vous fixer l'angle à {}\t\t\t\t\n" "degré manuel de rotation ?" #: main.py:994 msgid "Rotation mode changed to manual at angle {} degree" msgstr "Le mode de rotation a changé en manuel à l'angle de {} degré" #: main.py:1022 msgid "Optimisation Result " msgstr "Résultat de l'optimisation " #: main.py:1024 msgid "" "\n" "Got {} Words at brightness {}" msgstr "" #: main.py:1043 msgid "" "Got {} words at brightness {}. Scanning with resolution {}, brightness {}." msgstr "" #: main.py:1046 msgid "Scanning with resolution {}, brightness {}." msgstr "Numérisation avec la résolution de {} et la luminosité de {}." #: main.py:1059 #, python-brace-format msgid "Recognizing {0}test.pnm" msgstr "Reconnaissance de {0}test.pnm" #: main.py:1075 msgid "Terminated" msgstr "Terminé" #: main.py:1080 train_tesseract.py:261 train_tesseract.py:367 #: train_tesseract.py:700 train_tesseract.py:712 train_tesseract.py:733 #: train_tesseract.py:889 train_tesseract.py:1155 msgid "No" msgstr "Non" #: main.py:1080 train_tesseract.py:261 train_tesseract.py:368 #: train_tesseract.py:700 train_tesseract.py:712 train_tesseract.py:733 #: train_tesseract.py:889 train_tesseract.py:1154 msgid "Yes" msgstr "Oui" #: main.py:1081 msgid "Current text not saved! do you want to load readme without saving ? " msgstr "" "Le texte courant n'a pas été enregistré ! Voulez-vous charger le readme sans " "sauvegarder ? " #: main.py:1104 msgid "Running OCR on selected image {}" msgstr "Exécution de la ROC sur l' image sélectionnée {}" #: main.py:1139 msgid "Running OCR on selected image {} (without rotating)" msgstr "Exécution de la ROC sur l' image sélectionnée {} (sans rotation)" #: main.py:1166 msgid "Deleting !" msgstr "Suppression !" #: main.py:1166 msgid "Yes Delete" msgstr "Oui supprimer" #: main.py:1167 msgid "Are you sure you want to delete selected images ?" msgstr "Êtes-vous certain de vouloir supprimer les images selectionnées ?" #: main.py:1180 msgid "Nothing selected" msgstr "Rien de sélectionné" #: main.py:1189 msgid "Rotating selected image {} to {}" msgstr "Rotation de l'image sélectionnée {} à {}" #: main.py:1246 msgid "Select Folder to save images" msgstr "Sélectionner le dossier où enregistrer les images" #: main.py:1262 msgid "Give pdf filename(with extention) to save images" msgstr "" "Donnez un nom de fichier au pdf (avec extension) pour enregistrer les images" #: main.py:1299 msgid "Running OCR on selected Area [ X={} Y={} Width={} Height={} ]" msgstr "" "Exécution de la ROC sur la zone sélectionnée [ X={} Y={} Largeur={} " "Hauteur={} ]" #: main.py:1329 msgid "Dictionary not found!" msgstr "Le dictionnaire n'a pas été trouvé !" #: main.py:1331 #, python-brace-format msgid "" "Please install aspell, ispell, hunspell, myspell, or uspell \n" "dictionary for your language({0}) and restart Lios!\n" "Otherwise spellchecker and auto-rotation will work with english(fallback). \n" "\n" "For example on debian based system one can install aspell or \n" "hunspell french dictionary using following commands\n" "apt-get install aspell-fr\n" "apt-get install hunspell-fr\n" "\t\t\n" "or ispell dict using \n" "apt-get install ifrench \n" " \n" "On rpm based system use \n" "yum install aspell-fr\n" "\t\t\t\n" "On arch based system use \n" "pacman -S aspell-fr" msgstr "" "Veuillez installer le dictionnaire aspell, ispell, hunspell, myspell ou " "uspell\n" "pour votre langue ({0}) et redémarrez Lios!\n" "Sinon, le correcteur orthographique et l'auto-rotation fonctionneront avec " "l'anglais (fallback).\n" "\n" "Par exemple, sur les systèmes basés sur Debian, on peut installer le " "dictionnaire français aspell ou\n" "hunspell en utilisant les commandes suivantes\n" "apt-get install aspell-fr\n" "apt-get install hunspell-fr\n" "\t\t\n" "ou le dictionnaire ispell avec\n" "apt-get install ifrench\n" " \n" "Ou pour les systèmes basées sur le rpm\n" "yum install aspell-fr\n" "\t\t\t\n" "Sur les systèmes basés sur arch\n" "pacman -S aspell-fr" #: main.py:1368 msgid "Save preferences as " msgstr "Enregistrer les préférences sous " #: main.py:1373 msgid "Preferences saved to " msgstr "Les préférences ont été enregistrées dans " #: main.py:1379 msgid "Select the image" msgstr "Sélectionner l'image" #: main.py:1385 msgid "Preferences loaded from " msgstr "Les préférences ont été chargées depuis " #: main.py:1392 msgid "Preferences Restored" msgstr "Les préférences ont été restaurées" #: main.py:1410 msgid "Select files to open" msgstr "Sélectionner les fichiers à ouvrir" #: main.py:1488 msgid "Lios" msgstr "Lios" #: main.py:1489 main.py:1490 msgid "Linux-Intelligent-Ocr-Solution" msgstr "Linux-Intelligent-Ocr-Solution" #: main.py:1493 msgid "" "Lios is a free and open source software\n" " \t\t\tfor converting print into text using a scanner or camara.\n" "\t\t\tIt can also produce text from other sources. Such as images,\n" "\t\t\tPdf, or screenshot. Program is given total accessibility \n" "\t\t\tfor visually impaired. Lios is written in python3 and we release \n" "\t\t\tit under GPL3 licence. There are great many possibilities\n" "\t\t\tfor this program. Feedback is the key to it." msgstr "" "Lios est un logiciel libre et gratuit\n" "\t\t\tpour convertir une impression en texte en utilisant un scanneur ou une " "webcam.\n" "\t\t\tIl peut aussi génerer du texte à partir d'autres sources. Par exemple " "une image,\n" "\t\t\tun pdf, ou une capture d'écran. Le logiciel est fourni avec les " "options d'accessibilité totale\n" "\t\t\tpour les malvoyants. Lios est écrit en python3 et livré\n" "\t\t\tsous licence GPL3. Il existe de nombreuses possibilités\n" "\t\t\tpour ce programme. Les retours en sont la clé." #: main.py:1503 msgid "Visit Home Page" msgstr "Visiter la page d'accueil" #: preferences.py:186 train_tesseract.py:408 msgid "Font" msgstr "Police" #: preferences.py:191 msgid "Font Color" msgstr "Couleur de police" #: preferences.py:197 msgid "Background Color" msgstr "Couleur d'arrière-plan" #: preferences.py:203 msgid "Highlight Font" msgstr "Police de surlignage" #: preferences.py:208 msgid "Highlight Color" msgstr "Couleur de surlignage" #: preferences.py:213 msgid "Highlight Background" msgstr "Arrière-plan du surlignage" #: preferences.py:218 msgid "Speech-Module" msgstr "Module de synthèse vocale" #: preferences.py:225 msgid "Speech-Language" msgstr "Langue de la synthèse vocale" #: preferences.py:231 msgid "Speech-Rate" msgstr "Débit de la synthèse vocale" #: preferences.py:234 msgid "Speech-Volume" msgstr "Volume de la synthèse vocale" #: preferences.py:237 msgid "Speech-Pitch" msgstr "Niveau de la synthèse vocale" #: preferences.py:255 msgid "General" msgstr "Général" #: preferences.py:260 msgid "Engine" msgstr "Moteur ROC" #: preferences.py:269 msgid "Language" msgstr "Langue" #: preferences.py:278 msgid "Run Text Cleaner" msgstr "Exécuter le nettoyage du texte" #: preferences.py:282 msgid "Insert Position" msgstr "Position d'insertion" #: preferences.py:285 msgid "Cursor" msgstr "Curseur" #: preferences.py:294 msgid "Mode Of Rotation" msgstr "Mode de rotation" #: preferences.py:296 msgid "Full Automatic" msgstr "Automatique" #: preferences.py:297 msgid "Partial Automatic" msgstr "Partiellement automatique" #: preferences.py:298 msgid "Manual" msgstr "Manuel" #: preferences.py:303 msgid "Angle" msgstr "Angle" #: preferences.py:305 msgid "00" msgstr "00" #: preferences.py:306 msgid "90" msgstr "90" #: preferences.py:307 msgid "180" msgstr "180" #: preferences.py:308 msgid "270" msgstr "270" #: preferences.py:315 msgid "Page Numbering Type" msgstr "Type de numérotation de page" #: preferences.py:317 msgid "Single Page" msgstr "Page simple" #: preferences.py:318 msgid "Double Page" msgstr "Page double" #: preferences.py:323 msgid "Starting Page Number" msgstr "Numéro de page commençant" #: preferences.py:341 msgid "Recognition" msgstr "Reconnaissance" #: preferences.py:351 train_tesseract.py:477 msgid "Resolution" msgstr "Résolution" #: preferences.py:356 msgid "Brightness" msgstr "Luminosité" #: preferences.py:361 msgid "Scan Area" msgstr "Zone de numérisation" #: preferences.py:364 msgid "Full Scan Area" msgstr "Zone de numérisation complète" #: preferences.py:365 msgid "Three Quarters" msgstr "Trois quarts" #: preferences.py:366 msgid "Two Quarters" msgstr "Deux quarts" #: preferences.py:367 msgid "One Quarters" msgstr "Un quart" #: preferences.py:370 msgid "Driver" msgstr "Pilote" #: preferences.py:379 msgid "Number of Pages to Scan" msgstr "Nombre de pages à numériser " #: preferences.py:384 msgid "Time Bitween Repeted Scanning" msgstr "Durée entre les numérisations" #: preferences.py:391 msgid "Change to binary or lineart if possible" msgstr "Passer au code binaire ou linéaire si possible" #: preferences.py:394 msgid "Cache Calibration" msgstr "Étalonnage du cache" #: preferences.py:410 msgid "Scanning" msgstr "Numérisation" #: preferences.py:416 msgid "Lios Preferences" msgstr "Lios préférences" #: train_tesseract.py:52 msgid "Tesseract Trainer" msgstr "ROC avec Tesseract" #: train_tesseract.py:57 msgid "Tesseract is not installed" msgstr "Tesseract n'est pas installé" #: train_tesseract.py:64 msgid "" "Tesseract training executable are not installed. \n" "Please make sure following exicutables are installed\n" "\n" "combine_tessdata, unicharset_extractor, shapeclustering, mftraining, " "cntraining and text2image.\n" "\n" "If you forget to build training tools then use 'make training' and 'sudo " "make training-install' to build it " msgstr "" "Les exécutables de reconnaissance de Tesseract ne sont pas installés.\n" "Veuillez vous assurer que les exécutables suivants sont bien installés :\n" "\n" "combine_tessdata, unicharset_extractor, shapeclustering, mftraining, " "cntraining and text2image.\n" "\n" "Si vous avez oublié de compiler les outils de reconnaissance utiliser 'make " "training' et 'sudo make training-install' pour le compiler " #: train_tesseract.py:82 ui/gtk/icon.py:76 msgid "Copy" msgstr "Copier " #: train_tesseract.py:83 ui/gtk/icon.py:77 msgid "Paste" msgstr "Coller" #: train_tesseract.py:153 msgid "Train images-box" msgstr "Reconnaître les cadres images" #: train_tesseract.py:160 train_tesseract.py:832 msgid "Train" msgstr "Reconnaître" #: train_tesseract.py:169 msgid "Delete-All" msgstr "Tout supprimer" #: train_tesseract.py:220 msgid "Dictionary's" msgstr "Du dictionnaire" #: train_tesseract.py:222 msgid "Language " msgstr "Langue" #: train_tesseract.py:226 msgid "Tessdata directory " msgstr "Dossier Tessdata" #: train_tesseract.py:260 msgid "Search entire filesystem for tessdata ?" msgstr "Rechercher un fichier système complet pour tessdata ?" #: train_tesseract.py:262 msgid "" "Do you want to search entire filesystem for tessdata ?\n" "This may take awhile!" msgstr "" "Voulez-vous rechercher un fichier système complet pour tessdata ?\n" "Cela peut prendre du temps !" #: train_tesseract.py:362 msgid "Add new ambiguous" msgstr "" #: train_tesseract.py:370 msgid "Match " msgstr "Correspondance " #: train_tesseract.py:371 msgid "Replace " msgstr "Remplacer" #: train_tesseract.py:372 msgid "Mandatory" msgstr "" #: train_tesseract.py:387 msgid "Select files to import" msgstr "Sélectionner les fichiers à importer" #: train_tesseract.py:398 train_tesseract.py:601 msgid "Save filename" msgstr "Enregistrer le nom du fichier" #: train_tesseract.py:414 msgid "Choose-Font-File" msgstr "Sélectionner le fichier de police" #: train_tesseract.py:429 msgid "Select font file" msgstr "Sélectionner le fichier de police" #: train_tesseract.py:443 msgid "Select input file" msgstr "Sélectionner un fichier d'entrée" #: train_tesseract.py:458 msgid "Font Size" msgstr "Taille de la police" #: train_tesseract.py:461 msgid "Input Text File" msgstr "Fichier texte d'entrée" #: train_tesseract.py:464 msgid "Choose" msgstr "Choisir" #: train_tesseract.py:467 msgid "Writing Mode" msgstr "Mode d'écriture" #: train_tesseract.py:474 msgid "Inter-character space" msgstr "" #: train_tesseract.py:480 msgid "Degrade-image" msgstr "Mettre l'image en dégrader" #: train_tesseract.py:482 msgid "Exposure-Level" msgstr "Niveau d'exposition" #: train_tesseract.py:485 msgid "Ligatur-Mode" msgstr "" #: train_tesseract.py:518 msgid "Generate-Image" msgstr "Générer l'image" #: train_tesseract.py:518 msgid "Generate" msgstr "Générer" #: train_tesseract.py:588 msgid "Select language file" msgstr "Sélectionner la langue du fichier" #: train_tesseract.py:680 msgid "Select images to import" msgstr "Sélectionner les images à importer" #: train_tesseract.py:699 msgid "No curresponding box files found!" msgstr "Aucun fichier de cadres correspondant n'a été trouvé !" #: train_tesseract.py:701 msgid "" "Do you want to auto annotate box file with existing language ?\n" "This may take awhile!" msgstr "" "Voulez-vous annoter automatiquement le fichier du cadre avec la langue " "existante ?\n" "Cela peut prendre un certain temps!" #: train_tesseract.py:711 msgid "No curresponding font_desc files found!" msgstr "Pas de fichiers font_desc correspondant trouvés !" #: train_tesseract.py:713 msgid "Do you want to fill it with following font ?" msgstr "Voulez-vous le remplir avec la police suivante ?" #: train_tesseract.py:732 msgid "Delete file too ?" msgstr "Supprimer également le fichier ?" #: train_tesseract.py:734 msgid "Do you want to delete files(image,box,font_desc) too ?" msgstr "" "Voulez-vous également supprimer les fichiers (images, cadre, polices) ?" #: train_tesseract.py:761 msgid " Alrady exist! Please edit name to avoid replacing" msgstr "Existe déjà ! Veuillez éditer le nom pour éviter de l'écraser" #: train_tesseract.py:762 msgid "Place it" msgstr "Le placer" #: train_tesseract.py:765 msgid "File Name : " msgstr "Nom du fichier : " #: train_tesseract.py:795 msgid "Error : running command failed" msgstr "Erreur : l'éxécution de la commande à échouée" #: train_tesseract.py:797 #, python-brace-format msgid "" "Can't run command : {0}\n" " Please make sure you have write access to {1}" msgstr "" "Ne peut exécuter la commande : {0}\n" "Assurez-vous que vous d'avoir les droits en écriture sur {1}" #: train_tesseract.py:831 msgid "Training images..." msgstr "Images en cours de reconnaissance…" #: train_tesseract.py:833 #, python-brace-format msgid "" "Images to be trained \n" "{0}\n" " \t\t\n" "Language used : {1}\n" "Output tessdata directory : {2}" msgstr "" "Images qui doivent être reconnues\n" "{0}\n" " \t\t\n" "Langue utilisée :{1}\n" "Dossier de sortie pour tessdata :{2}" #: train_tesseract.py:888 msgid "Combine with dictionarys too ?" msgstr "Combiner également avec les dictionnaires ?" #: train_tesseract.py:890 msgid "" "Do you want to add dictionarys ? \t\t\n" "Do it if only all characters used in dictionarys are going to be trained!" msgstr "" "Voulez-vous ajouter des dictionnaires ?\t\t\n" "Faites cela uniquement si tous les caractères employés dans les " "dictionnaires doivent être reconnus !" #: train_tesseract.py:921 #, python-brace-format msgid "Recognised text from image {0} with {1}" msgstr "Reconnaissance du texte depuis l'image {0} avec {1}" #: train_tesseract.py:1023 msgid "Export-Boxes" msgstr "Exporter les cadres" #: train_tesseract.py:1025 msgid "Load-Boxes" msgstr "Charger les cadres" #: train_tesseract.py:1125 msgid "Find :" msgstr "Rechercher :" #: train_tesseract.py:1154 msgid "Not found!" msgstr "Non trouvé !" #: train_tesseract.py:1156 #, python-brace-format msgid "The word '{0}' not found! Search from start ?" msgstr "Le mot '{0}' n'a pas été trouvé ! Rechercher depuis le début ?" #: ui/gtk/icon.py:55 msgid "Import-Pdf" msgstr "Importer un pdf" #: ui/gtk/icon.py:56 msgid "Import-Folder" msgstr "Importer un dossier" #: ui/gtk/icon.py:57 msgid "Import-Image" msgstr "Importer une image" #: ui/gtk/icon.py:75 msgid "Cut" msgstr "Couper" #~ msgid " word : " #~ msgstr " mot : " #~ msgid " Replace word : " #~ msgstr "Mot de remplacement : " #~ msgid "Replace-All" #~ msgstr "Tout-remplacer" #~ msgid "save_preferences as " #~ msgstr "Enregistrer les préférences comme " #~ msgid "Scanning {} with resolution={} brightness={}" #~ msgstr "Numérisation de {} avec une résolution={} et une luminosité={}" #~ msgid "Adding image to list" #~ msgstr "Ajout d'une image à la liste" #~ msgid "Image added" #~ msgstr "Image ajoutée" #~ msgid "#Scanning" #~ msgstr "#Numérisation" #~ msgid "#Scan Compleated" #~ msgstr "#Numérisation terminée" #~ msgid "#Running OCR" #~ msgstr "#Exécution de la ROC" #~ msgid "#Redraw" #~ msgstr "#Redéssiner" #~ msgid "#Redraw Compleated" #~ msgstr "#Dessin terminé" #~ msgid "#Preview Updated" #~ msgstr "#Aperçu mis à jour" #~ msgid "#Compleated " #~ msgstr "#Terminé " #~ msgid "" #~ "Scanning with resolution={} brightness={} for detecting angle of rotation" #~ msgstr "" #~ "Numérisation avec la résolution={} et la luminosité={} pour détecter " #~ "l'angle de rotation" #~ msgid "Scanning with resolution={} brightness={}" #~ msgstr "Numérisation avec la résolution={} et la luminosité={}" lios-3-2.7.2/postinst000066400000000000000000000002631345364566700144620ustar00rootroot00000000000000#! /bin/sh set -e if [ -x "`which update-menus 2>/dev/null`" ]; then update-menus fi if [ -x "`which update-desktop-database 2>/dev/null`" ]; then update-desktop-database fi lios-3-2.7.2/postrm000066400000000000000000000002631345364566700141230ustar00rootroot00000000000000#! /bin/sh set -e if [ -x "`which update-menus 2>/dev/null`" ]; then update-menus fi if [ -x "`which update-desktop-database 2>/dev/null`" ]; then update-desktop-database fi lios-3-2.7.2/setup.py000066400000000000000000000076671345364566700144050ustar00rootroot00000000000000from distutils.core import setup from glob import glob setup(name='lios', version='2.5', description='Easy-OCR solution and Tesseract trainer for GNU/Linux', author='Nalin.x.Linux', author_email='nalin.x.Linux@gmail.com', url='https://gitlab.com/Nalin-x-Linux/lios-3', license = 'GPL-3', packages=['lios','lios/ocr','lios/scanner','lios/ui/','lios/ui/gtk'], data_files=[('share/lios/',['share/lios/readme.text','share/lios/text_cleaner_list.text','share/lios/lios.png']), ('share/lios/icons/',['share/lios/icons/about.png']), ('share/lios/icons/',['share/lios/icons/accessories-dictionary.png']), ('share/lios/icons/',['share/lios/icons/accessories-text-editor.png']), ('share/lios/icons/',['share/lios/icons/application-pdf.png']), ('share/lios/icons/',['share/lios/icons/audio-input-microphone.png']), ('share/lios/icons/',['share/lios/icons/camera.png']), ('share/lios/icons/',['share/lios/icons/camera-web.png']), ('share/lios/icons/',['share/lios/icons/check-spelling.png']), ('share/lios/icons/',['share/lios/icons/clear.png']), ('share/lios/icons/',['share/lios/icons/convert.png']), ('share/lios/icons/',['share/lios/icons/document-new.png']), ('share/lios/icons/',['share/lios/icons/document-open.png']), ('share/lios/icons/',['share/lios/icons/document-save.png']), ('share/lios/icons/',['share/lios/icons/document-save-as.png']), ('share/lios/icons/',['share/lios/icons/edit-copy.png']), ('share/lios/icons/',['share/lios/icons/edit-cut.png']), ('share/lios/icons/',['share/lios/icons/edit-paste.png']), ('share/lios/icons/',['share/lios/icons/edit-redo.png']), ('share/lios/icons/',['share/lios/icons/edit-undo.png']), ('share/lios/icons/',['share/lios/icons/emblem-favorite.png']), ('share/lios/icons/',['share/lios/icons/find.png']), ('share/lios/icons/',['share/lios/icons/find-replace.png']), ('share/lios/icons/',['share/lios/icons/flip-vertical.png']), ('share/lios/icons/',['share/lios/icons/go-down.png']), ('share/lios/icons/',['share/lios/icons/go-jump.png']), ('share/lios/icons/',['share/lios/icons/go-up.png']), ('share/lios/icons/',['share/lios/icons/gtk-execute.png']), ('share/lios/icons/',['share/lios/icons/help.png']), ('share/lios/icons/',['share/lios/icons/image.png']), ('share/lios/icons/',['share/lios/icons/info.png']), ('share/lios/icons/',['share/lios/icons/insert-text.png']), ('share/lios/icons/',['share/lios/icons/media-playback-start.png']), ('share/lios/icons/',['share/lios/icons/media-playback-stop.png']), ('share/lios/icons/',['share/lios/icons/preferences.png']), ('share/lios/icons/',['share/lios/icons/print.png']), ('share/lios/icons/',['share/lios/icons/print-preview.png']), ('share/lios/icons/',['share/lios/icons/process-stop.png']), ('share/lios/icons/',['share/lios/icons/quit.png']), ('share/lios/icons/',['share/lios/icons/remove.png']), ('share/lios/icons/',['share/lios/icons/rotate-left.png']), ('share/lios/icons/',['share/lios/icons/rotate-right.png']), ('share/lios/icons/',['share/lios/icons/scanner.png']), ('share/lios/icons/',['share/lios/icons/sort-descending.png']), ('share/lios/icons/',['share/lios/icons/system-upgrade.png']), ('share/lios/icons/',['share/lios/icons/zoom-fit.png']), ('share/lios/icons/',['share/lios/icons/zoom-in.png']), ('share/lios/icons/',['share/lios/icons/zoom-out.png']), ('share/applications/',['share/applications/Lios.desktop','share/applications/Tesseract-Trainer.desktop']), ('share/man/man1/',['share/man/man1/lios.1.gz','share/man/man1/train-tesseract.1.gz']), ('share/doc/lios/',['share/doc/lios/copyright']),('share/pixmaps/',['share/pixmaps/lios.xpm']), ('bin',['bin/lios','bin/train-tesseract'])] ) # sudo python3 setup.py install --install-data=/usr lios-3-2.7.2/share/000077500000000000000000000000001345364566700137555ustar00rootroot00000000000000lios-3-2.7.2/share/applications/000077500000000000000000000000001345364566700164435ustar00rootroot00000000000000lios-3-2.7.2/share/applications/Lios.desktop000077500000000000000000000003701345364566700207470ustar00rootroot00000000000000[Desktop Entry] Version=1.0 Type=Application Terminal=false Exec=lios %U Name=Lios Comment=Scan & Read Icon=/usr/share/lios/lios.png Categories=Graphics; MimeType=text/plain;image/bmp;image/tiff;image/jpeg;image/png;application/pdf;image/jpeg2000; lios-3-2.7.2/share/applications/Tesseract-Trainer.desktop000077500000000000000000000003751345364566700234050ustar00rootroot00000000000000[Desktop Entry] Version=1.0 Type=Application Terminal=false Exec=train-tesseract %U Name=Tesseract-Trainer Comment=Train tesseract-ocr Icon=/usr/share/lios/lios.png Categories=Graphics; MimeType=image/bmp;image/tiff;image/jpeg;image/png;image/jpeg2000; lios-3-2.7.2/share/doc/000077500000000000000000000000001345364566700145225ustar00rootroot00000000000000lios-3-2.7.2/share/doc/lios/000077500000000000000000000000001345364566700154705ustar00rootroot00000000000000lios-3-2.7.2/share/doc/lios/copyright000066400000000000000000000023711345364566700174260ustar00rootroot00000000000000This package was developed and debianized by Nalin.x.GNU It was cloned from https://gitlab.com/Nalin-x-Linux/lios-3 Copyright: Copyright (c) 2011-2015 nalin.x.linux (nalin.x.linux@gmail.com) License: GPL-3 http://www.gnu.org/licenses/gpl-3.0.html . This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. . This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. . You should have received a copy of the GNU General Public License along with this program. If not, see . . On Debian systems, the complete text of the GNU General Public License version 3 can be found in `/usr/share/common-licenses/GPL-3'. Forum : https://groups.google.com/forum/#!forum/lios Home Page : http://sourceforge.net/projects/lios/?source=navbar Video Tutorials : https://www.youtube.com/playlist?list=PLn29o8rxtRe1zS1r2-yGm1DNMOZCgdU0i lios-3-2.7.2/share/lios/000077500000000000000000000000001345364566700147235ustar00rootroot00000000000000lios-3-2.7.2/share/lios/icons/000077500000000000000000000000001345364566700160365ustar00rootroot00000000000000lios-3-2.7.2/share/lios/icons/about.png000077500000000000000000000014211345364566700176570ustar00rootroot00000000000000PNG  IHDRw=IDATx[]oٶƠv0mNRvc<[}ofja3;>=.yodKwV8b2Ϧji\nd y@8Wuu A&jM.rG\w܅$p?`iZ Hłæ {/P?T,<\囓'a9 X ŞPʩ:)Zȁ)Z9npsι1*^9)>G>stq. mjsԑ3axG P?hK %Ax JL$S3H~JpMcR#04Gv7e /B}5G@yCqP I/ mڣ_zMgpg8\cۏ% Q3}Bq;+>?Jl͆>rN[uyLjL"@a}E"Lzϼ c `߁ZT;\| #y[F)W ^"ȓ8SGg1{`ѵ{_ci|yN~%}4l1hLw߸[GȷKx!~9LcG͗5B;gOo 7w =@Mp_GSX^G^G(Y+礑̠[;,8%E^Yx5.Q֯rj/w{1IENDB`lios-3-2.7.2/share/lios/icons/accessories-dictionary.png000077500000000000000000000021761345364566700232230ustar00rootroot00000000000000PNG  IHDRw=EIDATxܓs,Y'm۶ҵmƙv۶d8{S3Layv,~ $)2QmUrlU!ڵXUD4()Q.ey_%M͍. ^ShjnXJIL:X\\캭՛8d(^x^yE~? r0vs8x0>> 1;䉛]P ǗmNC}w܌nEfl`hY@,b\/W_ 8v2A~|T}XVL&zq.HIIw}wkәT3৐aX / 1_`aE@kˑ;}/( 7΢"fp/|4nT֖!3+#M(F SS,i 1=U>]=Aza[ ;M h5rs9v˅>Khﶵ[Y*'XIեIl`۷'us؃._"v+zPA &0gvt"FW*|ν fPp}iGB)'$777tw|%[jjXHK ,xĩ"|УUZ\ECW#+jj)_&"'?-hn{u]9Ri[o~FވX@u fPp&A(}ؼe6mZ۷ 40TMĎ[i=vY]?^a! g8g۶k3uOua\ŝz˺:'(Xfn|]>ҭGqF)Z̝FwnR\#h6ļ#Cc84JFUk0bBo4yf6v .n uۯ\AF^6x'! 2vfh82iG q y:l< M8pFZ>IENDB`lios-3-2.7.2/share/lios/icons/application-pdf.png000077500000000000000000000022401345364566700216170ustar00rootroot00000000000000PNG  IHDRw=gIDATxc$W7|m۶mh3k{ǶvU ;='n8yN]OJ+P{FyF5*52|+)j)DCV^JU9r?МV1 hjjoFqB%R?P%|8 x:pYt~=DaqcRT-R 4spNmN 6lj9id2H"i/Q :VI6V%7}*z4y"Bԓ_tq-U(<.<hFGCjc"< [:}C=P7ox,J*K`Nd#';7ָhFY3w邤# ۍʦq.A@$hd涚rR!U;FDyl2uwx!r?Y:BqQa8~N'DBA@8o2Ae(;qQO#k~۴}R{puz$&>$&P@醵m9$(c&?t1iy-K%߁.. A@RJ)Hr'!=SG~xx9b㣄 ɱPRCMDWV#k:|O>A)鰺fO>EL\0 >1%kT0 P]S TA?u ̤gϝI2#:6\Mukر >*(3b8X2/ӷ//?FdL0 6>G sg X.\^H0XvbވS€踈o`Y Am-lp]]T z#O b¿Q &]D8 d%i\ 8. :o,= ,i{QKܵ+`۷t$D <9zO{sz]`n3i"r:&;ifPN@>R=K~p\.(?y=~:iۮ}d ?[^~G~8v08{Όm[h~Hԇ4:o IENDB`lios-3-2.7.2/share/lios/icons/audio-input-microphone.png000077500000000000000000000017561345364566700231570ustar00rootroot00000000000000PNG  IHDRw=IDATxp$[ҳmk;Z8{&m۶fl^⤫_,@;bf_e0٬H̜4$$A$Xy=ickފ.DD" K ILyFaQ!KW#08pbbQYuj`箝=-ͨDTT8K W/sw`۶=M EzV |QTOC߸ 4߰~JˋD2(^KeԦM%gcSE'd 14԰t"8$1prצe&cժU9~J|RQZZ;oOq Y@Hx6>) BM P*&jyVwpď?~?7{LIfğvO[@>0%y#//a!K?S6s$0R \6 z:C~\.bDӳs2!Xyx6v֕[~ﶋ%xzPd⣏>lab`UO|ruw ?@dt8)[psw=rиbЪU+:>z&E.а`&iTE#ެA~Ύ;g/U%@wg\Ιgr?2qB:p|ғ j=Sxܹf_hjjik&ף#UpÓK\y)g?yڨ㞆ښWD @s3D/oCN2Ē%K޸lNO4}@ 辎ރbwާ/˥3RVn*5SM شiKO=2w~j$DOfǿrJIENDB`lios-3-2.7.2/share/lios/icons/camera-web.png000077500000000000000000000023541345364566700205560ustar00rootroot00000000000000PNG  IHDRw=IDATx|\Kk۶خXmVl'[;ݛUY}s䤼gƦXm޶"Lk@^޽vf[dvl[NGPĔ/%pK>żp&E-@XT(ɧϟ Y樸pQhs |$ ^A(~ Ȁ455A  8,P8hhOKˊ%o(ʗkf<";;prva~EqIa{ xeL\H.D*+W-G0d >}-[쩉D"Va»Kr$$ |X];999SP$E4lڵkN;cIcƍc}PVVҲRxUHxdSb3ڳL1l<1klhτS=ԏaryu!}lyyy(((͛30 fXjb}, :O=R9w\.<xWX~VZ뤃_zaX?-rtsT9<]¢#iF`mE~DZZZpԩV266}ڮ,$11ɴp:3F_'W*SLMf/$s-b5,<G:A|m\W211ih~ѢEe KN2FDd(\\b>X_*Xg9e]V8,n޾¥s8td?ۍ.BKOP`bfH$\xF?J4F^UfXf%vڎͫs!s8| N:Aj9nݺYif:U$JJ LVTNի[j%; [{[<|!alnce 2H$i!֩gϞr+UT@$VTh$F%uMQ^U8уfoZRQ!D#m~?Զ8U{}4#Y`VIENDB`lios-3-2.7.2/share/lios/icons/camera.png000077500000000000000000000024251345364566700200020ustar00rootroot00000000000000PNG  IHDRw=IDATxܔ|GkoQٶcl*mԧSn338.q?0 ƟGFFN*))ihh_rIEE%W_e˖DӧO/O88!%%MMMǃ @Fpp0w^lX_ɸ]]]?L;;.#..?3jjj JQ^^777DDDdԩS DOO0::,--@_"Np􂵵 ss38:9/ ! HssQ\RX$F@fffh֛Xq3ut܌hQ`kkK'' 1) \\ ;G'lp lVAzz ..8o߹Dwt͏u alfJJxDZzZ),,,d  znٵf!a@Ww7I'&҂ʪJ8~2!'sġ'J.&tjjB"7o߅۸x] ###_YQI颀G!"2Db:ytt$XT ួ=M *l۹ bEEET JNN5656N=G%@X K0HB  CGꠋ[vV dq-[wVVV̬E=`\Ggg+do:-[!3+Z:042ži沨EUkg;vϾ_xW\>{_~5>+fE,Ek6sއ ӄƧclbSF}s ݮ={b8UUUҋf]f|dҕ+JsPLES^~>NH(omJ&Hޢ)螝=.Isr}l7RiB/RSS+9~x/ϡ5SKiԢBEEMz.Izee%%%%N<}|MMͨ|>pl۞+Nܩڿ/ƾ7noq/HFB!+  M$wPD2:cwVb…kp"hQAq8`J\ Fa= ԐA =(IENDB`lios-3-2.7.2/share/lios/icons/check-spelling.png000077500000000000000000000015001345364566700214330ustar00rootroot00000000000000PNG  IHDRשPLTE@@@ @@ -33.44055.38036-36-55O@KJNL;x=xG.47.46N/36B@-36.46.46-46.46.46NINP CDD.46.46.46/562894:<9>?:??;@@=BB>CB?CC?DF?EE@EE@EFBGGGHLKKPRMPNMORPSVRTWSUVYUVZ[VWZWZ\X[]X[]Y[[\^`[^`]^a\^a]_a]`c_ac^adabc_bc`be`fhdfiegiegjehjfhklhkmimnjmojmpjmpknoknpknrrtuqw)y||z{x||~/.-/3m_;tRNS  #$%&(,57KPe{ IDATxc 4!uuw7u{wu` ku`HRBaNep`&P" "eomfQ!Skholh]f#1I1##5:;˩%:.Cڭ ź$#*t5XJ]Ț(2k`FQ}_L VG7֡(&jhmW20Jp hY(j7H_PHH  $8xx/(&6v4DF iJO[IENDB`lios-3-2.7.2/share/lios/icons/clear.png000077500000000000000000000016331345364566700176400ustar00rootroot00000000000000PNG  IHDRw=bIDATx͔x+Yŧݵm۶Y>۶m۶4Ee23u1i|<osjxȉMzL#p;0C^@fa uOFh}́0h}{vNKZK!jѪR+0̉'A=u ]wێsQ/% Z/)rM;{=,Q*4Ž,x etduK^컬0QU>_F\ VTcf̑J\~8#Nf5U5Nm/X3l|a{0oBy GM'iɳC iOZXq%8:o 0t} cn<8:\lm"bVv6ushS]k+~;nЇOK'_~qo1$a 4eYP c1A3_W7 qa D0yq:M/Pǝz8/Cp:iil!V&1UqC`UuG8BƗ^qЖ?F"\zgW'$R"7 B}ikG &NM[2 U,fF}M~K  yDO oYp0UJu7`M[)τ4D{Zu>O:ޚOFoV­ $ȏ$hɆgSbpG7)g_fs>>BBBEEEFFFIIIKKKLLLPPPSSSTTTUUUWWWYYY___dddgggjjjkkklllmmmoooppprrrsssuuuvvvwwwyyy~~~tRNSg=(IDATxc3AElmmY}~0 N{[LO-0jűž~Vg`,/j&rz s;~0aR?&,ԺZ’u-}_"jDɒMW^}ԺsK1KVjN>\txO>^hퟪhҋ^Ҽ?->Ψ}߷ps0P#{tKG[{{1~k/I+/p8Z/ԗ?"zУ(hhNxʔ<P%IENDB`lios-3-2.7.2/share/lios/icons/document-new.png000077500000000000000000000020711345364566700211540ustar00rootroot00000000000000PNG  IHDRw=IDATx3Gk۶m۶m|m}gvn7mT>3+^{6݋{?gþY?v/}`;˗/?ҽvağ Xںj2iD#tUeя>X,5^lg\qWz 3={SV;Cm# # @hP5*AyYb`(j}KOG_l+r{{`ZN$ $k}u8L9AVLJ.im;73ZQYY9/k<rKOR}+l+V9 zp"\elGwEh8~|+4Esw˄*Ad܈q(K_m RY+Ρ*@y֛T ?öd̘57n13Ls΁J:RmpB8;{2}Rv `/"0b(bq"F8D4SeL:^:/Fi4MX ` y}O5n¨ &+:[Y$")ɩF]0v(&'ۉ Nj!ǎHa0}ąjF.]L:rЁ{ ,?*+utաz!@7{ѯ'z%zW;awn#˺qXb\ʸ_r# _yn¿IENDB`lios-3-2.7.2/share/lios/icons/document-open.png000077500000000000000000000015511345364566700213260ustar00rootroot00000000000000PNG  IHDRw=0IDATxSxWM2X{۶ӱgbgY6sS뺶ϓ;2N=~0URM435SgMB5-j\,=6vb ۝jkf.19dGJa՗l(PgOYBT*cZ邧GGWKs L U0+У-E,J"cӧ F}%t5\i~2ba(4fi'H Z I PU/`C34K; DI$_/lHthvDIC'Dn '%T@; GykPNMUBe Tf$~S6xAELPi˸o;o᭷|UkV򝊘'/(  _@ab—~%z y#欝7=+ꭘ}wlM{J?asEr.> vUgyAs/Ow+g.ޏS` ^^խ] 8AG6N TYvԎҭ`dt:$]9ڈVl/r݊Lg谄ƪmh`o4U`i &)Q׫/C =L+yyʦsGxC'm *Ѩ&[,:l4ϞgӣKG6ΤքgS6\57O|1GG߻ΛWRf <dvp}qY|{&`&/NDyUuEy/&}_ST7A - E5 g:y͛7'Ԍ$0]B`/G/{y`?zzيƦ:Ȳ%Ft\$>򋲱,.ceuk+-l2l=iGQi>f%IȰ AG"L"3Ho:$Uf0=; Q0 ;O=UH&2 Q ܧϣf=A+e$bvniY(*.ex }њ6wK[UMPO|Q!XZ^@Jz0@"ɓ' ϖ", ?$Gwbx@gaʞrC5$ Dta~~ṠjP/zo"eϋW^xIOBT a{g ɱ€LAT nр~r e}3}fÏOO_\Yncc- Hgq먪-n>b#lVV κ6VɺΟ?Gr(<[ $ nE!4<%Gyh#Bl lp IyɅE Ş7Wݏ-4_/>q(̑7cb9ܩo7uk=&;s5YxVv%ԺVMj*h 044NΌmockk[m0Ԍ׳Ñ066ױЌFҲ!>^nbyyA8@A 2H/$DƦTV ` #!!CK+=tzfH6y&Sq@@10ԋ>bH? ݽ.4 46vw9 KDJ'xR|~7g&`C(D}S0@mAf1 ӂ`؏H4>U"pbrj #c./jm&RtZٚzhToixj+eCuRY.H^S]X.'*Hbx}nTȅMuX%wZSkP>}GѵDvם 6vLy_gW ET\544 ]$t3rFI&:ϗD 2%# kb`=K O/3,xZs"]:-^ٱaiHba@M5u|_|ϼ8"_},> \~立ȓ'WtIZ! "J& ob7cee"L$h7#b,}=*sC4ɤQ..ȕ {vAW1hH %dq|$q⇬o9=s }aC D 4 G:DoZVfh 'IxU.IAvo|43E~aZ{./(NJӏs읿9G3yؒt=w@t55xnZ>~ }Ҋ"5p}S S{|.^^-uv~wzvF~QO +b'.//p_C':Nb _ï䐟E慟pn~DمNL!I$%-$&8Kc;x %~~ԍ7z bb23I,,?&FB!"ى%%, ,aAd "Ki$6>.CF"4m!~ /6b tIENDB`lios-3-2.7.2/share/lios/icons/edit-cut.png000077500000000000000000000021421345364566700202640ustar00rootroot00000000000000PNG  IHDRw=)IDATxT5xm(AK*J:z[Zdpk>y.labXdC{4KR $IݿɆ^eXҞPP"PZQY&w?G#F  QjEґcEI/0Da| @WW\\R0,H0,AǃۇZLznp~Ei~~e9Ȱj3_r08?7; 6&&F%&777aQ A!Qr@țaju=sBKKSxpʐmM,f1CI8:4&F,F-pM.YܮaY-- 2bG~~i׬ Hb⢇'@i >`XLF=$^wZ"A 2R<63df"tvѠ8JD>?1/y{9 챶m۶mQ6m8ԈY۶mΫ_8ԹgE&NǧOduJWEOH#ӴjM4cEtukhЀ7i6役sLx }ޑ#Cа!(X0s8|_ zx (15n+:H\:uOt7j D@iDV$Wg}ġ9@%@A*rvm#zpaBVlN =E$ ڞ3gbJԩ%cŋ[+fG C+T`Uի@e fۛ'qZ7ER=Ho+~M@%DWjZl)㉺7/@Y.YVU|n$(++1~PVz-t*Ydi;eeeDq-j5PIENDB`lios-3-2.7.2/share/lios/icons/edit-paste.png000077500000000000000000000017061345364566700206120ustar00rootroot00000000000000PNG  IHDRw=IDATxœdI׶mV,}mۯ=m{&7/so8UT_plOn25pn4DAIY۳*ރҲli-+ ],.~AJz"6mYήv#]yys澆of1K 5p/> QaXa56lZwđ;R^TuUvN ÜW*x ́,tysg{}ee)?c uu%|Ar7ώKJ>`J| *F֟ VcRLO{I,B{Z"ui4]0Ӑci1{*Ϛi3'aڬ uZ"ui LM H] f̞ ;ن2$%׿{;Aqc] &MJk  vlk \A^^`(3 !r$?~_ ozvRX8B,P`wA X&Vli(եz5K zP<$DRȪxJQi^`&1W\ng;\vF9(hF{g(9zA_7BZ / S9(,fHhmSNE;JZfNpaA\ ϴ"E41Fcq0F {"5]/| aa:"+' Z^EwO'FFFiQb\x价/.Cĥ(1Rq2 GԳ_r~CG>6!ZԢc#Șp-"*T Bà ZPȿA{A/0ȅ.c.O/矯 X"!IENDB`lios-3-2.7.2/share/lios/icons/edit-redo.png000077500000000000000000000015001345364566700204170ustar00rootroot00000000000000PNG  IHDRw=IDATx$W{b۶m۶m׶wǶm1n^lQ~y?*úa8bƱ.XI0Ak_U!DpW^9muV NP[I˪?EhFv?ф|**G q]PZ)#,U(HAX12FCxNb~n)iFuVt{쯠qts7 $Ҹ܆~;6> XoJk@ ܡ'=tL:#߮Wš?m9&6\waEJ&3 nӑ kWHyk?3ˏϴ;v=M!#l:$<Qxoܪ&]:ozP?[TX{ 1%Vm9Dg~+>͹j~ 5pnV Q X ELoVĺ|q5 yex7lܪ?7JIZ|x*6z?lǽ73aOpxM=7~?GbnH/:@sWC׈a?pݗîX"1{⟍E؛}gmB(;.7-(,_)XP#M,Vh6ڎ+iU=9/2-rб/}3f-g?͸rT]-1V. L9nWc_rLFt9"ZQ7e>(U hDIENDB`lios-3-2.7.2/share/lios/icons/edit-undo.png000077500000000000000000000014411345364566700204370ustar00rootroot00000000000000PNG  IHDRw=IDATxݕcY{m۶Zۻŵmmٶm۶;?g X ˎfL,oFǑEtA|x5x?G%t&mK% ˍ<\ s"]ػ NIZPr5͍h3 j?=uU*T?:'tPx780(}!q:o(GHWxFudG@ؽtUmZ{B1tT$SiI {*^#:+CѱAA+/ BZng:o"У1GH^4+WQywC}gQ uw~C;Zy?@i ]"C,Oo<^"Wr<=·`ljj=`s8%r-t76Uy^$=dIA<5l/ "A.:8|ݓm5[l.l__].56ct]4#_]ү##+(࿔5=qɌw4;q)ju3[{s -iRH{'IENDB`lios-3-2.7.2/share/lios/icons/emblem-favorite.png000077500000000000000000000015021345364566700216230ustar00rootroot00000000000000PNG  IHDRw=sBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org<IDATHՕo@Ɵs|vl7N$T U%@ !6$ !ѽK`@:% X(Eˇ`HRc1W==.3KU}K8]riDԢ02xio3ѹp΅Bw7BQ0L]ɕZ^lnWrdιR1Ƽt[ެ#7^`1)%(Rn:c5fa4klGQt& 5rpͪCh2ͪ#sOҡԩrJςIpyK5 =}H\GΫ@@ˮYڷNB:0 T*=; nQ_;,'m/;wЏMz\(aeYvt]- ӅBau]RjAXea*x\ Ɵk #{>+zˈ2 @5IENDB`lios-3-2.7.2/share/lios/icons/find-replace.png000077500000000000000000000030661345364566700211050ustar00rootroot00000000000000PNG  IHDRw=IDATxs|;[̩;omZ41j[9=>E.[YKOe<FT>ZsQt =VK$b =7oᨦ_ vϺLyxA1ݐ1!HN/f+X^ܶՕc@*$F㞦8rjj@xzGʾ j2apDeN`RO11 }DZfqy8)qi Nna;#!7n8vӳg^iiMBeL'zY[LjTCsg06 ===eeW^|jX|!#D4s$f< >Hxq$H(II,}ᐬ˻J&y ͭ[tFGF8l83`23U=k};WxqqQ)HN]/Ħ`{AL͡a}^Q+=C'ar)o]]]͏R-ܨPsJ| .6 ޻I<.a EhZTRur}|nhʰXm,BGGnxuSww7; WO6/7H"@d=ovIW H*_3OH|M="6<~ܲeMooz᫚,M_JE0y>6tߔ}8擝qi+׏?^B,`VXkqZs?@|ZM`}POyglTymKkk릉d㖜5-*fPq`@3AA=F1,64|kqw\YfIIQ6yoJ&`ɨ2RjDZZ6|oⰪ/Wi}Yb':st[tyI_E?e36EDD/(@=I3aQ| \sއ;z簯߇e~M3eTW$-(HIZ؜9J' a#\6ghᰛzL 39('1C$ q'+ M" ٿkl@#c5mg\R&Dzm oOhD{;lATpc7߄pS4dŶFF N#kWJĿ:4uipwCKp`ٵk͸5z{G2-3Q}?"?PBh#l.]DozkYiI2xMM 7#CA@@G##d-"^x܆[Sܱ0oP:y b`W D8V.I < `)ޗ]!_˖!#V+m3 F6IENDB`lios-3-2.7.2/share/lios/icons/find.png000077500000000000000000000027401345364566700174720ustar00rootroot00000000000000PNG  IHDRw=IDATxs|cNjIjVMڶmc̚cϬEj]{s?rys^& яmb?X;*<=Z~GP;-r m\unK]KkΛFGFAw6i|,lOêh&(Zrv?OA7[!ޯR>#@0HcEga`ҡnfp;omMrwJARp{[@,H=D$dr+җn>_XV0:jn5Mw(>oIBMz(AF-΋k׮f9u]\C0Å9@s? 4CVkk+z{ 9X=訑F{ߋ;E<0(7}w ݢ{]oR(E Bs襥Wy^p/0c\}lce\zlwa)*OfgggG"j ;,X=iJ?H;P##DzÀ"H՟| 7 eFpOO @͛Zay Qy@֡t_ʾ!=OX`__ܜ7.̩8WWW0o ,y{ }Ip^m4tֿ\|ltmɗ/PzŻ͹;AA~wڸ_ t.8P fb/o=9 $?/u={Wm9R5-`)Qaą&OoBl+9="[O(#Z^ #Ii^WޣȘ~rV}ExD>".5\(=[oP{־+"p*YX]w5|mDh'#tb`ҫb³jUO!SB#Ƨw y̍ԔE' ~`$qi9ߛ4=/ߞ4ѱVYNCI;ꀎꡲ, y@" nrf-S LcPھQ_0;Cc* Ć@Km)P9S? @NC!,ęOcU.LŠVRML@BT0(/ {<Iv C4 $.d*/+zc:A$HA?~9A D1g_~D{9_EoطAIENDB`lios-3-2.7.2/share/lios/icons/flip-vertical.png000077500000000000000000000015301345364566700213070ustar00rootroot00000000000000PNG  IHDRw=IDATxpM5N[:S΃ VBZ#Tr wp~/3K ШĖ10Z΅^Z,荻L_E>}"i-IZAhyӠ.Fl0"e^E\զ"`F~dl羅L|[^[=fh*6:i-V7CcyHYk~i16h'IٮA]hes7Ɛd-oF3/s  G=b X[nk'zf~ՏXK$6qE7y+<5.vd"<=|'>e['Aㆺgh.~;ʊ[!ԭ?"9F.} KyL8hv O{}?u7p>?B%~8`=ct.m O q lGoƛ9a -~α}V:颕 Fu!u"O7nǢ(V"nmP .IENDB`lios-3-2.7.2/share/lios/icons/go-down.png000077500000000000000000000020251345364566700201200ustar00rootroot00000000000000PNG  IHDRש4PLTEuuiqi|ff`fffflfllflslsysyyyyyy3636:6y|v###%%#wysnrm{z}Z[Wsup}{fidhkfjlgknimojnrlorkqrmtwr{}w|~y~{~|}~~ce_fid¾{}x½¾ÿSptRNS  ""##'(((((((((((((;KKPggpӥ% IDATxc I8̳&sTlv2IۤX2,yIX1Eavf`HڹvU"DBű fY3ւHZ}UI|8C$ 'ue")tS2hL)[G(0-1OjRdBlhZ#wbx΍ o\-bi뷭k/Dl@%}h)iߒIELjqL,b*N*b,ZY9Y GbOTIENDB`lios-3-2.7.2/share/lios/icons/go-jump.png000077500000000000000000000016421345364566700201300ustar00rootroot00000000000000PNG  IHDRשPLTEuuuiib|||||ff`ffflslsysyyyyy3636:6y|v###%%#rspkmgvzu|}yZ[Wnqly{wfidhkfjlgkniorktwr{}w|~y~{}ce_fidĿ{}x¾hotRNS  ""##'(((((((;KKPgg"LIDATxc8% apYm*$,`֌T  vR,Q%̚ `m*1)52A1̲dcsXY#I%b6 7Bdz:lCz4i Kx,2oZj-n= sO]Y,!\U7g2_1;VȠKο[~E^L*aL,RJjJR,ZY9Y <IENDB`lios-3-2.7.2/share/lios/icons/go-up.png000077500000000000000000000016221345364566700175770ustar00rootroot00000000000000PNG  IHDRשPLTEjjjxxpxxxq||uyy'''+++prlsurqsnyzuwzv}z}ijgornac_efbqsouxr|}x}~qtny{w|~ymojחÿ }ktRNS  ""##%%'(((((((((((((PTTF IDATxc  cWrt";7DS}Bn)$q0xEvPK! /P-o!K3HyuOnsHhN/2%='@$wJY&5LtH6xK1XdM4esͭтHk; 10$LaƆdclcg@ 6&a1-]D̴ -јL֩U)VL,I6*,ZY9Y ;DF\^Z05616939;5;<{~}/47/57:?A=AC?DF0683:;7=>8>@7<=7<>.46PSOUWS.4628:38:39;5:;5:<5;=5<=6<<6<>9@@;??UWSVXTikjz}{ƿQ@h2utRNS  !#$%)*-.:<<>@HLQSTVYZ]]blo&B{pIDATxc-D,0\LI]­;7ܺP.auv%蚛j7::Ko d0vFl^!%RHN:?|7.;V꺓'<0o3ys]=k “W>Ί eqWx3{.6 )@6V읲.%"fD#H^>+$eڱz#[kwNIc8u-ͩPZYuS8N"ؼyNg!$'*}bOYbyj#E@4KݽѱQ)_C^e[7>sl_Ct:;,vc?i(&`Y f~zrr\[Rg`6(e&A$$Xy#3J)"xr DbqR.,,XdYfeׄLJPjb`Vci[mfx]lnH4&PIxaz,0xQ 4JL6g0j@yD{QXDYȸzrs<ێWHz=-g>| yy 1 73 w{uMBĨDٳ4wF/SPI'd|aSVR ѼuE *⁐ >{=ۏ{{n;wLR" pw0Ig)& Trג<t8jn| szz=}jQ7awSe''@j-=aukP Zt.y\TQMAFHқIM4oY^UVȭNxz]6 ghusHt 0=@\с7@T`'|Om vipp  fASKud: vdO5~kj~MAcsP[*/JK_|eU8q↓N=}\$}@j'duگ8q:~?Hj-IIENDB`lios-3-2.7.2/share/lios/icons/image.png000066400000000000000000000020341345364566700176250ustar00rootroot00000000000000PNG  IHDRw=IDATx쏅m$LDn,~KC|Z覊~/kǒf((ɪ I8R v#G-, ?jq\ Enj2.趲_M9vm۶>۶غo~mۃtڣ;mAcS=>7 HZjzBB,`%QZD-Sq,xg:ME2ih h52Y 5Kk}DIcl\$]&ec.bnDǼ^@]-aC  Ii8әUlo>sިH26%q -JY4yĤ2ʟ54"Es؝VfG0:y ,&țʉ, 7c4Xۨbai,4!<-L=Y򚑬cu`2KS &P1´lj(f]4f8;"KVJZf7 Tutgԗ Algkx"\cn:bO{Uά*BrSqeNOW>Rwx^wdԊs߭Wp6)ڳ72P840B׼L"E#/[>>ωrUR.K*ͱhOrD2/JGyB9LS;ïrӕ0Mo? G<;} 7?KXJˋM% {2?,dXlIENDB`lios-3-2.7.2/share/lios/icons/info.png000077500000000000000000000017111345364566700175020ustar00rootroot00000000000000PNG  IHDRw=IDATxUtG*W*,Ŷmbڨ϶Ӽgwlsm?܎ _iw>wNIc8u-ͩPZYuS8N"ؼyNg!$'*}bOYbyj#E@4KݽѱQ)_C^e[7>sl_Ct:;,vc?i(&`Y f~zrr\[Rg`6(e&A$$Xy#3J)"xr DbqR.,,XdYfeׄLJPjb`Vci[mfx]lnH4&PIxaz,0xQ 4JL6g0j@yD{QXDYȸzrs<ێWHz=-g>| yy 1 73 w{uMBĨDٳ4wF/SPI'd|aSVR ѼuE *⁐ >{=ۏ{{n;wLR" pw0Ig)& Trג<t8jn| szz=}jQ7awSe''@j-=aukP Zt.y\TQMAFHқIM4oY^UVȭNxz]6 ghusHt 0=@\с7@T`'|Om vipp  fASKud: vdO5~kj~MAcsP[*/JK_|eU8q↓N=}\$}@j'duگ8q:~?Hj-IIENDB`lios-3-2.7.2/share/lios/icons/insert-text.png000077500000000000000000000013111345364566700210310ustar00rootroot00000000000000PNG  IHDRש8PLTEmcu7j2q<3z]\_`fst㝠߄/eik7:bghSXYZ^_\`beijKPRQVW}5;=LQRPUWQVWQVXTY[.4606816817828:39;5;=6<>z}ˁSJUtRNS $%)+/7EuIDATxz+Pضm<IWPNg.Spn{\_!P{Q |hDoa~!?2A\2 IΨ:lR.z5*{A&[%P0j+bv{q mK0L]' `>?.bܽKV.i]ԛb+E$Uh FJ. 3]">JcIENDB`lios-3-2.7.2/share/lios/icons/media-playback-start.png000077500000000000000000000012521345364566700225450ustar00rootroot00000000000000PNG  IHDRw=qIDATxpQEk۶95mnc6~~mm^%/av}S^@>!!wOw`#}|㗷Bo f]*E& 8EE&|… M6_JJJsHif"/x**ʊ}$8sR/7P4UZMHLClBr_WN<9Z%XjLZ DƆ!)5B^*]]݉DԣE Vx\b4BA>dqѬF|@fJF&zePxn~6e?s2X٘]լ ;;{Få(B||,gmk.w-*a#{e%.u݌̌+k3[,гsѾ[wA,U@* Ɇ54z*BNv/]9GAR^kBx>^ZL@P]mM:s ,ːp!>޹3Ww>} {p[0̑zG*S,>]Ч#9e%HǯjBIENDB`lios-3-2.7.2/share/lios/icons/media-playback-stop.png000077500000000000000000000006711345364566700224010ustar00rootroot00000000000000PNG  IHDRשPLTE ...JJJmmmV9;{tRNS &/8AJNS[_dhlIDATx@a1AC_@(^zv]fIQ8*?CnH34IMm {O:hW+ ^RgU;7D_K7ly_IENDB`lios-3-2.7.2/share/lios/icons/preferences.png000077500000000000000000000012571345364566700210550ustar00rootroot00000000000000PNG  IHDRשPLTEiii:::~z|w.464:;AFGNRRUWSZ^]gjhtvs~תtRNS  ""&/>f:%+IDATxӺ0m6m{/ zWetVWsVVv^.xv͢|>!-N f ud2Y( \Qp8 g4D" PLbl5H8x|2嚑p!0DBq#@J#A2G;6Jp36ww?kFDؗb44֢N`A 2}$}! 46ȱf"42\a2ݺ$zl۹ %R!F qQp DZς,IYxv*A='[p)>E\8I iVemXmُ{O8r* !`F<&e!*k֝i9ɲY%=-VAqslGmACU+Z~޲&J>^LZ`}: 8T r _svۚC~Bw{79"m4ax`ԸBF; %%%t覂>L9 X87cdѰ'?BREk|IhC |E5wGIk4b3 b9 'NYr8<CptsHW-2)A[3et>,!8qf$5a-Ʈe >(Y jpl499$ܜ}e``Йtl%)W/o47oDpx6 1(cKy~ ǚH_r0XTPP S+]pIv;۵k'7H/ H0Ԝًw^c,m*( wKsMm>dyL:jdrt  x_Ox 5ͧ4荜KXl@F&XMFg<ɳ`<`@Eh 41tESS;a My/U$[a 7v$Db>tJېTOeU5# K͔tc,y$n\)'Wbw ?IN(6:w<C{Ϟѻ7Ե12ShA-&w44uu.ddsJJw=IIs7OYJj./7 #7m[8)5CswO¢|=q棢sKS5Bhx0anmݴY\Ү_ )}]n L͍Cc} "{8qT6I} 9]0_k+ \|}TE}6(3O %'DHH@bj,RbF$)- }WOWp2r}ҲBGg{>MJN(/`G ߼Bx^TAa,!uQ7<5&G zvtu @}6Y>,s+~=Lgl-=9ppx,<|.$fEs.-M]-kk9=n3m$*QQEM q q @yUbr|s6?&򤦥BR; JJJ[%.]:m޸kI@]G{@~A>K_T!4kugg'Zn0HCt8I旈!,,l`ҼOnTUWR@ZZBdWĢ&_D:ԙSXbeMҥ̙,dzD nŚ5uNӣZe{aŚmB]4L\z6m}0žGV4,lbj ,XW@DDDXPČY{ev``?ʬkK8`μ~] 6N2eɘ4u*̟;wd>F[jBx@NhG?F_n[ ..n[MÊHuUek4 `mKPeӼw=uUe g8FF=7%2ѰI՚&uKpȲ2qmV\5iF:ԲXibF.F :@CٷheNN5Qd3k & l޶w/D޳AAhC7(st$T"D3VT2(wvFS@ɠp{Zk:77HȠd `aa%eװ` ||o!{y-PE7;w 5]]혟Õ ؀0Hf2uft338ŔO>{1~@jU0{l̔#""lΜ9ZJ|~S0ёe?ωiBQ*;w.%%%j;搜,$/5]s3v< k AYYyyy\F׳r*y}KEN~n^oR(-lWDCCl[AǞK(~a?0kx}AV|4bTWWS ++:&O,IC+*ʊejww}?I<,:GGGՋGV#8{ {{mlXr"=Ewh״4Yp(R7oTBٮp01P,@\P̍#p@1AŁXc&f)")0B B<ݨ6dryIENDB`lios-3-2.7.2/share/lios/icons/rotate-left.png000077500000000000000000000016041345364566700207760ustar00rootroot00000000000000PNG  IHDRw=KIDATx͖s#Y+X۶mgm>۶m#c3d2ytrߩSnZqtH,?GX c9C=LlO,E%0O &clybxv٤dzԙMIعYo Qrͫ1 uПrz=lTгʁ?0JP]K&^uTW^DjLR* /xKX uy75Pbuz(BW$9;##"Y76 }kASO@O4sӫ_M[S@OǪhp7퍢HݟC/ m7v@~ O6_?& EM B!SљAPUCHRh=Qt$frc{K8@]!?PBc6.R#hGҰ& DLb!U>p#< ˓bPB%#BBͯc}{a G{}-.xvơ>%JEov5v~7W&afȭoz}-.^%C锆0ZWC*CG@Z k3BX$6( q.} ܼ212t]#tr4ux{ 8&zÙ3OВ{ .[N7{ kyp>?7s0s s svV|anÆp?Fߛ1 22{201G>y]w'MkVz?U@EKIENDB`lios-3-2.7.2/share/lios/icons/rotate-right.png000077500000000000000000000016011345364566700211560ustar00rootroot00000000000000PNG  IHDRw=HIDATx|m۶m۶m'˺ ^s_/ρ>B|zDƋ]9l2rwXj0)b ^˿fSzcw~wvvv7ِ$ۤmHE܅B BhQjVE}T>WEL-B>uMB16Mb4M6ٙ;3sgwAAڻ{޽sFGGY..o9u164 axo*?Җ 0 HB(qs<sqp]G薬Wqe T:QES iUS@}YymokPwܠrkr4@jK9f2߫uzE$IQZV (着@WK/--a'`hpHSWWS.E,ɸaqE##UXZ r:vu m~IRD^;jc{%SeжiYi.///8[TިgcVŰWāߧ*eEPN;ÉK !dYijLՂ A7gJ\^ګONNhOnr;={nVlAEb*[MS%Q+7 e![6_ ц= ~~dTm(g"HUEl9?9m;D=>C3)lE Hh4\y15Sw֝lEh@rFȨb&6bp'^f 0>iTv]+K4ٳF FIENDB`lios-3-2.7.2/share/lios/icons/sort-descending.png000066400000000000000000000012721345364566700216360ustar00rootroot00000000000000PNG  IHDRw=IDATxRRa[AÆQɶ]Ƕ|z(kۻKGB?&Pad/A{JlRJ`ا( pzE~\@aO^Ùxh9do8;dvm;-M9,no/;z=4iZ&dYBU'zbqnuK%8N'[m2Ѫ˵A֨@y'o1=7)::ݿ1 㾕r.%>qֶm۶m`ͱ8 kk*`N_E-*FD#!0t}:O[Xujʢ%Q$x׽ AXX[f5hj? ol:vO6W )s03;413]H ܖV `wZ5ӣ]in3؍Z469LUGLh`zȊ-Juv ,@cs[7E Aop @((*KyyU+~/噺hUǹ V3WfQ^^vU"U㑪*Yȩb1.L]ǿ[/YYK/IENDB`lios-3-2.7.2/share/lios/icons/system-upgrade.png000077500000000000000000000021751345364566700215250ustar00rootroot00000000000000PNG  IHDRw=DIDATx͓\kضm6]VtvrcqmgZvwJ*OJ d&zD9?*Z<[$5NR +\eX"EnZC RC~-$&*`O6&+3wЙ>CmCuJYߜ}jqzB`^ vdnjra٦nH}Q!XQJKӭO4evc!Jf+h77DShM_1A1cc,hې$kJBuQsi%=D\ll5LR˯ eiٙeXkNCx==Wmf^`Rx06I%HO{ <7bT_Y w,oX{2*Ns1ZJ,7)J A!2dZ3]^'&bSg,p쀕% 1.X xG,96K/. !@NQ%{<=1{'(ͷ|+7a\Xtj.f9h@؃ VB-p R*2\9qH0k1f χ ȼϤ9|Zs&~k Ɔmsl瑘g 37ъ9N#1ʹ69lӯt7@m}1ߦ3~)b !}ݘsA o+~M.OR8 r~a`i=mC5հ$`i[wX8K`gBFuWWjכϛ$Ka99A v3ƽT|Ff9 W-4&D4Z !s\=N \?8}.`pm׸`W]S -zٞE .EʴG X3~-4AqfْD!Px S$b41y7ZI хyf1&(O%z6D3ѯmnQ0&n2b?_sⶣIENDB`lios-3-2.7.2/share/lios/icons/zoom-fit.png000077500000000000000000000013231345364566700203120ustar00rootroot00000000000000PNG  IHDRש,PLTExxx>>6992pqnMNKLMJhifwytgheZ]X貳XZVikfoqluwrz}w{~xcF6tRNS !$$%():FVbl+ IDATx̓v@ᵍrm۶pq:ə{/g$#gj{`.`W{xwN{ő]/﮷QaTP$^KQrL/aD`ZFn~ř#pо̾qh2f9#4qh-hMypjP߯:tV+t wV:ݶvco_c}x/ ԁQS(DA$7rK2 /t 1L5Xդ("~X*1L* {G\w%'IENDB`lios-3-2.7.2/share/lios/icons/zoom-in.png000077500000000000000000000013221345364566700201350ustar00rootroot00000000000000PNG  IHDRש5PLTExxx>>6992pqnMNKLMJhifwytgheZ]X貳UWSXZVac^lniwytz}w{}x_%+tRNS !$$%()FV!IDATx̓0c۶m۶pޜ,W핿m(Xuonnӫ`{\N\6ʰ#r[! @pILox<c1h!p?;`i!{o-=Cd@*l$}mrij֑mr)b8D6MdWV+;bDpvHBCo!Tk5z*[n/,eP`#aP8t O(Q(UR&p4rb1IQ)]{IENDB`lios-3-2.7.2/share/lios/icons/zoom-out.png000077500000000000000000000011771345364566700203460ustar00rootroot00000000000000PNG  IHDRשPLTExxx>>6992pqnMNKLMJhifwytgheZ]X貳XZVwytz}w{}xE ; +tRNS !$$%()FVIDATx@ m۶mMw?[U2r ߮v|͇Pe/X 6Yb*e6'RYtL νP3dk!wl y(BfW[}Reқ4BrbDO}k-G2Z\KXoZ%dj3'Y%NdJhN yoGx|H$Hq9{4>T`IENDB`lios-3-2.7.2/share/lios/lios.png000066400000000000000000000422251345364566700164040ustar00rootroot00000000000000PNG  IHDRlsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org< IDATxwd}&=StUuW3 v` @TP-u$]ln\sRh.)+AA0q53=tugW:++X|/{LFL\}lh\f>?~ɚx #hB.EHԗA ^ _G 7Ys~Dn ((dY']=뇸a $=i;|dxah^n $'\n b.2sNlٲX eoNDHiuW8nKf:r`hZLOOcaa ?|~KȚ5dnFr9KV2MS(])Dq~ʺncffGAR<_tו\ R$M7݄={T񗂴UK<joU@,=vnH _(bԩS8|01ng|O"$k.Sa l޽[Ūj&$',QNiry$=N8ս4kB48ume5n%$nUW];Qn5Y;)7 7d#Ƚ$I ;( nR)7HkSB~LNNNs?~؂J,:py+)=N l,sF% ^z Vf>vSP%IC=%$|/aXЪyviv[;?*'q $^|Eb?#wi~طoE#Ndr[GQ^EiB4EUM8_u8y$x X'/w!={w^kI~N/jϫ[@ѯ7/ٹ쵬;uΝرcy [vFD"'>aw;eȠ i;7cdYh_垇@ J,ܭwՏn{ɿ6|-Y믿z$r%xdq]dvXI(&^v#&1'ݜﻋ^͆ǻ5>d}vb1:%csAJޟhnEi瑕u]zf;潀-8^"t2z!F-?$I®](!m6 9l?, ð:pY Xna{^Tx 6֟ߑ6כ0rccc<ߨdRH䞖|^u~EeYΎ"R^Qpҷɯt˚տ[4݋~ö*>z'"~zQ҉!Ϟ(P̣ @3ɲ(8n6AO(|A*@CDX R+)I8XnCX_I,M6*aUY:Jzo@$qMT~n&pt] ذeE@D_/aNcN/Fhꅤ^ L&=;_H$:@̉^8KӕHSѠ.NxI^KE2P15ZϜ}VUqAtA›3o4]E`dYF2NXb L{!, !R7ryq*awYwrCDGtϒ   %yEA"![nYUt#A"~ܳPUބ' ð[^H*L8^0PAx$Ih4hۮR6WU&*1cnV[32CպIRܮ~I&9$d B]]ZlZkw7VԈ mxB|t?E-5Gb`0U{D?/ڼn^{ZU*Yyhϼq#zi?6 '5a&ޕ57Q Tk񤪓!D"9躎Zƭ-~XSY EҡVk]440i;?ߘ<#R CMTݲ앜ԀrӐ9^{ 7y"HrӽǓMOO >h= #@&- ?tITQ9{=ilI/Js]st]wA!N+" pZ56qOr'fFc&1;󍙙OUǚ "Htً+r5 zHu#dYO$^ ɓnR&W"u> !sN"]Y>K>h>`|MΪ DIX,8Dv^l6QTK[9(bϣ|MIW}? F 6 `SNX,r=_8z\ۭ' RՉDG:y:VWWQz$!%F${pO pV "4 Fg)/sx/{i/usO^bhh;TT~2 +X2Wj'znOBА]fˋgm4X]]AV2yHQ0q%+4 zF ]puT9NLzuݖT"Na G?qx鎢t\.;#JbmȝܷZ-J94ܸDGUUaBV{"+ 2_mz!#/!N+ Se{)J8i `uc=s=^x{ >=9LJN+w0PT*V< kxů:Y@:|eYF($atB_8H:J]T$ +9B~x=sssO=畗&Kw[`fO/l(ew'AFңR/dꙀ̠iVrz8,EKtuȺ'AjۈD"U u333xuV{ _u z꩞D5 m^Q*i?(UTe(,# <g&ŢkV7s"i&BPRT$,!X,b||'" -J%/aiJd+/g:@{!bd%ik=siPV x111I酆ah`qq'O/~yJV^Ҥ"nHv( ǻVW@֮n\. gP⑑A$du jjD"]'-gvҤfB>-~:IF{ pmm ǎ].f6%`w(dG*V* N, Ҁ' -5^ xRP?jzpHDH6_'I6T###iZVWW144$$lcCyKbs{^^aQ'''mh4P*zER4 uD偮1$IYr(u_~)2ujՖ ?վHB!dY,..tD"=hG% UUJ%]D3Mv{v@]RD=-NWT:Ae{I`*IytV'~ل%ne_/ahhȖBg_d2IdY _mxh6XYY‚c6Qu Ijb`0h4ʭyj*qLgducݑBÈbv_ sIIRWZETM${/W:'''g<3i\ D%yjңneYF$7p#[*rC_{WKkfK0OO---T*ux SQ[O\^^`СC QYa}0Mk.3/oKe $jj4+(_ H$Dy 䞖<룍bT*h4H&044.40v5jUr$]h$ID"Hvbdk9'IH$U$-[xʶiaE %$ drU@ [oE&R<=T؆aP(ؓiȲD"a"p"IJyV;pKC!~GD&G)ULǜ2a& ahhk[f G"<)*[nK/JXC`qq;* bhhϙ@$n~$HҲI4җSDaFF`0T*%ld"}}R KKKvw(LWE ߉4^yR8 A^T0H^23aYqwcD0<O^ů–ݻL&m/q Ats+%<9ջ+o [es=xꩧz3{uD9(\J2Ed}Xiw")ʾq ~!UE:Ƈ?ah'BZėZD&(|ނ#iAal6e&N:$Ivc2yg&N/̻3Xiy!O?ݥ"t?㽓xNaq琀mhd!MgڜG\4qw8`Bė^Ɨ^FRxh.vmnLTz ]=6o==YDEAYd2:t>,q/#iwn*Hsu%+iZ,EWIU^{mW˟IlV5nnEG'ޭ=E8F8F*B1ޞYSoSgVQoOC. 7܀W_}6Un$펞4E某d,/HhiL,+!Nj1߱c8 k&Tu,#xtE8x<:zOe Vn N<֋: *wvn 'B' j^AG5+1܊@ӳDa*!/{?66;WaNNB@&7 -h>dиQ,[~uG!=;^ ԴwX+O?OyJ5 ? iqMr!'NE'DS|5.4)[e<&Qm )xx駹Od#ZR5w]0x7xg I^غu+nF|Ob~~FO IDAT>ׇ vT#٭kz5wJ?x>X7" |:KY{)CkAɜ8v(x'Gܱɺd2|3KL.9홬N^B$h6yW&/~h cn)h dK[ouM-8T2X0c˫8Vdyi\I-rۣ2`W6^Y d>CPT/Zj̚] D,6^ڱc XrDd[A@h2AlL+2,~ၬj:x3Sk(N,Q}L!Bߕ½ ݸ+4MÓO>yZu*H43{'eya+Ⱥcǎ,`2ݎHN2na=kB(~VGXIQ-johsnD5AR__ۓELӴ$ mr !Yop#ĤAIH 5#,x9.$t?}-L޻$Uac9V\i|k_'$l6ĥ]E_dOk!KZ|%D!ިd+:GO摕nh *Y8gW{AI/.mN:ŵ' ӂ` ^i*WXiY")HtMrJYJfէ^?m{n\uU~ 7<;S\I>ÝC&rw'믿 A"5pX>ۗ^XIk+|V9X6&#KJ]W~bb GxTV"ՠG7v֠p}ayyB7i;ddTEss7Bt EA(t:D"h4ETZu.tRc{Kfxvkm> OGE,fn79td2FnN^EVIZ?3HB%1=i=>o#Lca/銉D#"ĜRKv{/n1^ u4$a5<6PPN(غu+a3OF"R)d2$#2@N5!aBg_~ݸ<'BsÓi4/뮻wLT?d˦D"aoGٝ އܪ}VO2,kqËIu!/$Hyx!*lE$TUE40W:`s#HOuBPϠĥ E}h44> ⪂ ޥ¶mBD5SKDh, 8ׯ4땠^%h6s.4Z?xu)5_C$hi֖`Νe J\23EMb:ЉL4T*,,,P(\rP-Uj_=3>Zzy=jD4DTwz'U&DϦivG[b}1u'gXt r A|OWw&=[h)/4ʲ5@_YlwER=A?ٳ}e WgPQ@?D`jmzO0}фdY":~&W}5M*ىn/yu&(y1`yygϞuݧ|1d~gߟYÉ{K,ݶZ2L\q!|hŕ( 6aՍ 7D*ѯ~AۑjK_{JV0 UUbU]] ,Tx,cEFSkf5;ȅB!TwyNd+EyU>o AZ󚦡j~^{ {ݻbnnsssXXXi=2 s9\Z7BMS\&T nN)x|Z[oUU1:: LLL L O}gIC@KTФJnvㅠ>nE)᭷CnC @$(vcrыIyaiNH$wB QEB"nŞn(Z-nCX'@8FZO~ۜ\ĥD"@ RBvm*E^S/"; _i:qsgWlEcޚ_uEU<.--ٍ>BA"Ppa6 z `&bȖdV4MT*4ͮcYrु{5 kzWkEXRa3p4sB'"bnbhh^ۄd(^&*B Ґ'l<a]'"]jX,c^UD>UOGr:yG0{AHzGY3riJ"ˊJ,v\>-1992qHWZ{5i X)Σܘgh+h$ACDCLx %t㙝ؿ `:"VK,ci%N/\׵$ɚS[HcO$}B`DO#J$/Y^^@/'uȧi {teAdb 4D2щ4ie12:ljp @DXFU_@XDU_DM_DۨC ,ϵ`mV6y)2D$8"B FuW=h (W((X^,biⲥS?1D`tUbRIHTrm61 FPV iŮylj1fziBr!)p)1q mȆZjJ RKX^XEZ"Kd<.UDJVZq#,!M80Dh4F`}OTfe033eO+3F 4M㒐.DDdXXhPpH PP p Rg3O: ltXE42fQ뒒iZ{sR 0_G5sus0{ՄDHBHt1C8G$㏲f:^CQCVEZEQZm`U7HURH dE &{/ƶ_:d^,3887G=ST\m/~H65Yʨ66F7l~sfB<S1%QËr3E ܆__43Y|𦏗p:vfB gȎcO?JӐ$ va( &-{c3@rSUX8 <&?z ?s=RKs)?zF|߁xӺX*Y']uKq)}J8 RǦ&kjIXldm@ J} ikv޻ 0q>3Wqo7;XD IMMZ"FVlYd 'wltӪ:OC~|/]T%|OOը[s\nXSSdsΣ-ę,~`C>scKss>x<6K3 شd]^ɌV5KRCLӄ"x3]W#^x}wM'0>?}=KcAasddm)-qf`0<.Ѡʸmַĩ˸IkpV?+ox$`02Yk7I~KV:2586:VΟY_rg;gOߋq vi7W1Ǒw__W`蛯i%khBTZW.ͬ5~֥9dU2k`x,ϗQ64 :[ęǿ஢\Jؼd-[ho`,53杬h(Zb!m6 wWJ@=il۝=o|v { H\%+cMĽ~󿼁*"Ѩub3(Vܳa|'/XL|K/ٶԀ8ñ^~EPˆ$,JXjeW<4/mil*x6jZsު^`p8~70ADd |ƟX??>@]yɳGWW:ޗHV/7Pv7$&'w{qu#) zURm$-\[?|ߔPZcy5*(VQ.QY+XȔFgaYR%wNWWoެ+xoSNah(sgR sMwcߘ?4*-̜X"K21=\lʲZ_@[Z"L; bCx($i,Y@qO$B": eN\u_zGz k%`]hz ]ޭ%`U vZ<޶$Hiϟ?B{QCCbݭ8^R莃un Do#9lĆ' wz;v[VCU̟),rd(]:BAgr+-];a ܱL (e`6GB[=MnA&922 Ik55s s-t>+ؾ7{R݅I% bȣH#ʣYaPaF?i߾}׵Z$IB"MhvC,jZqr Msd/Y9U(a$𞒬TDD9G@UbqHLD.{~Yo߾=HcIl|[NbtdN!DŽhYwf OD !$ !,eFFR=DymKy,,cfzO╟y7^G:0 T*dY[:x<|9o8 aecزmcf&0EXFDʮ&ͬ%Y6m"*4)&APJ %D !$RJ+ 8SбXJi ] ?Ww纼VE'5B֯]pGqjPF2ȌIg0G*1i'|XED(C{kƥ@PB#BI2WhbQZ0snhϝ% 3m0a1r_QضmƄDeĞy. TidGS J#H# L۫3yPC2uhR:uԡKu^AeK5W`PbF ҹCP"PEPJmaV+)P,\| źnn]}> >@Ȉ}̏,g4M˘9Up+Ԑhã)d)i:')q$)ޭ2nj0:44 CruhEr]jZƢ:L@J TTdXQXK%() ,BF ?[7**"V(wXX.cyR,H8wg:Ν;G5X§=r/dY\ve$F^N Dt xDXĚD"N bcP尐N[Ld(%&4jadʝ1Й^G]C]CYEQCYG^CVGVG@\*6 /|!8IJ7)?~$<5O,//#abb]G6Z^3Wb#Gw|(f<|>\.+_kNy FG|7Z;9 m &A`Mzt @@TD8`)KJE >!+9.EJ%=zNoDrkSM;`ǎ֌osBm۶arrRxSAx)$;pgbLܱɚ;Io0aHF͓^6lx~qQs:5ߞ\C^D}v  jWE)';: ^!iǫ_/mn|>zNgMsnx}>z~!Ƌ|~蛬4r6X 0`sæY3> 9ag7&aIENDB`lios-3-2.7.2/share/lios/readme.text000066400000000000000000000363101345364566700170710ustar00rootroot00000000000000 Linux-Intelligent-OCR-Solution *** What is Lios *** Lios is a free and open source software for converting print in to text using either scanner or a camera, It can also produce text out of scanned images from other sources such as Pdf, Image, Folder containing Images or screenshot. Program is given total accessibility for visually impaired. Lios is written in python3, and we release it under GPL-3 license. There are great many possibilities for this program, Feedback is the key to it. Report your feedback through : https://groups.google.com/forum/#!forum/lios *** Features of Lios *** 1. Import images from Scanner, PDFs, Folder, or Webcam, 2. Take and Recognize Screenshot, 3. Recognize Selected Areas(Rectangle selection), 4. Support two OCR Engines (Cuneiform,Tesseract), 5. 24 Language support (Given at the end), 30 more languages can be installed in Tesseract, 6. Full Auto Rotation for any Language(If aspell installed for the language, Eg : "sudo apt-get install aspell-hi" for Hindi, 7. Side by side view of image and output 8. Advanced Scanner Brightness optimizer, 9. Text Reader for low vision with Highlighting, With user selected Color, Font, and Background Color, 10. Audio converter(espeak), 11. Spell-checker(aspell), 12. Export as pdf (text/images), 13. Dictionary Support for English(Artha) 14. Options for save, load and reset settings, 15. Other options - Find, Find-and-Replace, Go-To-Page, Go-To-Line, Append file, Punch File, Selection of starting page number, page numbering mode and number of pages to scan, Selection of Scan area, brightness, resolution and time between repeated scanning, Output Insert position, image rotation and zoom options, etc *** Opening and Closing *** For opening Lios launch Application menu > Graphics > Lios. Or one can search in dash board and start Lios from there. Open with image items or PDF One can select required images to be imported from the file browser and open the context menu using right click or application key and select open with Lios Closing Select Quit from File menu or press Ctrl+Q *** Importing images from various sources *** # Importing image At first choose the import-image from the file menu of Lios. This will cause a file chooser dialogue to appear. One can select a particular image or multiple images files. The images will appear on image list of Lios. # Importing images from PDF At first select import-PDF item from file menu. A file chooser dialogue will appear, here you can select the PDF file to be extracted. # Importing all images in a folder At first choose the import-folder from the file menu of Lios. This will cause a file chooser dialogue to appear. One can select the folder containing images files. The images will appear on image list of Lios. # Importing image from scanner Before scanning make sure that scan menu is available and select the scanner from the Lios main interface if multiple scanners are connected. You should press Update-Scanner-List when a scanner is connected or removed. The pages and their brightness may be different. So it is important to select apt resolution, brightness and scan area while scanning book. One can change these settings from scanning page of Lios preferences. Increasing or decreasing resolution can be done by clicking on '+ - 'button or pressing up and down arrow from the resolution spin button. (Default 300) increasing or decreasing brightness can also be done in the same way. However It's better to use the brightness optimizer to set the exact brightness value for a particular book. (Default 50) The scan area can be selected using the scan-area combobox. It can be quarter, half or three quarter. (Default - Full) One can make scan using scan-image(F8) button from the scan menu # Import image from scanner repeatedly One can set the number of pages to be scanned repeatedly from scanning page of preferences also the time between the two scanning can be changed. One can start scanning repeatedly using scan-repeatedly(Ctrl+F8) item from scan menu. If you want to stop repeated scanning using stop-all-process(Ctrl+F4) item in the scan menu. # Take Screenshot One can take screenshot and recognize that using this features. There are two modes the first one is capture entire screen and the second one is capture by selecting an area. Both of this options are placed in scan menu. The second option is more preferred. This feature can be used for recognizing text from videos. # Capture image using Webcam One can start capturing by selecting Scan-Using-Webcam from scan menu. Then adjust the webcam and click on take button to capture the image. After capturing enough images close the window and select image from icon view on left side of lios and process it. *** Manipulation of imported Images *** Image manipulation options are available in Image Menu of Lios. # Invert List This is used to change the order of images # Reposition of image items one can click and drag image to any position among other images in the list. # Rotate selected Images One can rotate bunch of images that are not in exact rotation. # Delete selected Images One can delete all images or selected images from the list. # Save Images Used to save all images or selected images to a folder. # Save images as PDF One can save all images as pdf or save selected images as pdf. # OCR images without rotating Before running ocr on images we can set OCR engine, language and insert position. These options are in recognition page of Lios preferences. The selection of engine will affect the supported languages combobox. One can decide the place in which 'output text' is added. It can be at the starting position end position or wherever the cursor blinks. After setting this, one can ocr images without rotation using ocr-selected-images-without-rotating item from the ocr menu. Or selecting the images from the image list and using the same option from the properties menu(Right click) # OCR images with rotation The mode rotation can be selected from the recognition page of Lios preferences. The options available are Full automatic, Partial automatic and Manual. Full automatic – The Lios will automatically select the apt rotation. The detection may take several seconds. Partial automatic- In partial automatic mode first scanned orientation is the model for the rest. Manual – In this you can give any orientation you like for each and every image, The rotation should be set in the recognition page of Lios preferences. # OCR Rectangle selections One can select the region of interest from an image by drawing rectangles in the image using mouse. After selecting the regions one can OCR the items using Recognize-Selected-Areas Button shown left side of image view. For each entry in the list there will be starting X,Y, width and height. The overlap won't be allowed. *** Scan and OCR directly *** One can do scan and ocr directly using scan-and-ocr(F9) button from scan menu. This will first make a scan and add image to the list then ocr the image with respect to the rotation policy. # Scan-and-ocr-repeatedly(Ctrl+F9) will scan and recognize images repeatedly. The process can be stopped using stop-all-process(Ctrl+F4) button. *** Manipulation of OCR Output *** # New One can start a new book or clear the entire text by selecting new(Ctrl+N) from the File menu. This will ask confirmation if text is not saved. # Open To open a file in Lios, select the Open(Ctrl+O) button in File menu. This will cause the Open dialog to appear. Use your mouse or keyboard to select the file that you wish to open, and then click Open. The file that you've selected will open. # Save/Save As To save a file in Lios, select the Save(Ctrl+S) button from the file menu. If you are saving a new file, the Save As dialog will appear, and you can select a name for the file, as well as the directory where you would like the file to be saved. *** Other Basic Options *** This includes all text manipulation tools like cut, copy, paste, and delete text. # Punch This is used to open text on a file and paste that text in the current cursor position. This will cause the open dialog to appear, and there you can select the file to be punched. # Append Same as punch but the text will be added at the end of the current text. # Find This can be used for finding out the word in text. Finding the word in Lios can be done via Opening the find tool by Choosing Find(Ctrl+F) item from Edit menu. Enter the text that you wish to search into the Find word field. To find the next match, click Next. To find the previous match, click Previous. One can see the context for current match above the Previous and Next buttons. Also the matched word will be highlighted. # Find and Replace Editing text can be time consuming. To save time, Lios includes a Replace function that helps you to find and replace portions of text. In order to replace select Find-and-Replace(Ctrl+R) from Edit menu. Enter the text that you wish to replace into the word field. Enter the new replacement text into the Replace word field. To find the next match, click Next. To find the previous match, click Previous. One can see the context for current match below the Previous and Next buttons. To replace only the current match, click Replace. To replace all occurrences of the searched-for text, click Replace All. # Spell checker One can manually check the spelling of a text selection or the entire document. To check the spelling of a text, the appropriate dictionaries must be installed. The spell check starts at the current cursor position, or at the beginning of the text selection. Click in the document, or select the text that you want to check. Choose Spell-Check(Ctrl+F7) from the Tools menu. When a possible spelling error is encountered, the Spell check dialog opens and Lios offers some suggested corrections. Do one of the following: To accept a correction, click the suggestion, and then click change. Edit the sentence in the upper text box, and then click change. Or to add the unknown word to a user-defined dictionary, click Add to user dict. *** Readability *** # Font and Color : - General page includes options for changing Font, Color and Background colour and same options for highlighting. This can increase the readability of text. # Go-to-line Select Go-to-line(Ctrl+L) from Edit menu. The go-to-line dialogue box will appear with current line number. Now type the line number and press Enter. # Go-to-page Select Go-to-Page(Ctrl+L) from Edit menu. The Go-to-Page dialogue box will appear, type the page number and press Enter. # Text Reader One can Read the output text using TTS via setting the cursor and activating the Start-Reader(F5) item from tools menu. One can change the speed, rate, voice and reading volume from general page of Lios preferences. One can increase or decrease the speech rate while reading using Increase-Reader-Speed (Ctrl+PageUp) and Decrease-Reader-Speed (Ctrl+PageDown) buttons on the same menu. *** Utilities *** # Brightness Optimizer One can find the apt brightness for a book using the brightness optimizer brightness checker is one of the major utilities of Lios. different books demands different brightness level depending on the quality of the paper. ocr process results best on the brightness level set. It can be done using the brightness spin button in the recognition page in the Lios preferences. If one is not familiar with determining the brightness of a book, can use the brightness optimizer in the scan menu. To start optimizer select Optimize-Scanner-Brightness from scan menu. Then Lios will ask you to set the following parameters. Note that if mode of rotation in preferences is Full-Automatic or Partial-Automatic then lios will try to detect the rotation using a single scan and pop-up Optimize Scanner-Brightness dialog. In optimize dialog the first one is angle-to-be-rotated of rotation for optimizing, The second one Current-Value that is existing brightness(default value is 50), The third parameter is Start, it means, the value from which the brightness check starts(default start is 10). the forth one is distance, that is, difference between brightness level set for each consecutive scanning(default distance is 10). The forth parameter is End, it means, the value from which the brightness check Ends (default end is 90). If one does not change any value and click the optimize button. The program will scan from 10 to 90 with a gap of 10. After each scanning, the total number of words detected will be announced. After ten scanning, one can opt for further accuracy in brightness changing the values or just click Optimize button to follow the changed default values. In the end click the apply button and ocr process will be done on the brightness level set. It is highly recommended that at the beginning of a new Book, this utility may be used. Also note that a typical page that represents the quality of the book may be selected and no movement of the page kept in the scanner may be made till the process is over. # Audio converter One can use audio converter to change the text into small pieces of audio and save it as WAV Files. You can decide the speed, pitch, split time (to decide length of each WAV files) and volume before conversion. # Artha One can findout the meaning of any word using artha. Select the word and Press Alt+Ctrl+W to get the meaning, synonyms, antonyms, derivatives, word related to them, and words similar to them. # Saving and Loading Preferences Lios Preferences dialogue box contains three pages, General, Recognition and Scanning. One can save and load preferences for each book. Also one can reset the preferences using Restore item in Preferences menu. *** Scanner Trouble Shooting *** These options can be changed from scanning page of Lios Preferences. # Changing the driver The next item for selecting driver. If one driver is not working one can select the other one. # Change to Lineart or binary Lineart and binary are two modes which allow user to scan directly as black and white image. This is more appropriate for recognition. One can disable this but color scanning will take more time than lineart. # Cache Calibration By enabling Cache Calibration one can avoid heating scanner lamp each time. *** Disclaimer *** Copyright (c) 2011-2015 Lios Development Team All rights reserved . Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following license conditions are met: License: GPL-3 http://www.gnu.org/licenses/gpl-3.0.html . This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. . This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. . You should have received a copy of the GNU General Public License along with this program. If not, see . . On Debian systems, the complete text of the GNU General Public License version 3 can be found in `/usr/share/common-licenses/GPL-3'. FREE SOFTWARE FREE SOCIETY lios-3-2.7.2/share/lios/text_cleaner_list.text000066400000000000000000000000001345364566700213270ustar00rootroot00000000000000lios-3-2.7.2/share/locale/000077500000000000000000000000001345364566700152145ustar00rootroot00000000000000lios-3-2.7.2/share/locale/fr/000077500000000000000000000000001345364566700156235ustar00rootroot00000000000000lios-3-2.7.2/share/locale/fr/LC_MESSAGES/000077500000000000000000000000001345364566700174105ustar00rootroot00000000000000lios-3-2.7.2/share/locale/fr/LC_MESSAGES/Linux-intelligent-ocr-solution.mo000066400000000000000000000531131345364566700260160ustar00rootroot00000000000000*l 2$'+/2Hd|   1,^o F3: A'Lt   D! ft{     m Tw6,?0Lp   #0CR m0z        ' / 8 G W g 0~      !! %!Q0!!! ! ! !!!!!! """."# ## ####$ $$$>'$f$!$'$$ $$$% %"%'% 6%B%^%g%%%%%%%%% ''' (#(7(O(d(m( s(('( ( ((((% )3)L) f))))))) ) ) ) )** * !* .* ;*2\**=* *3*3+8+>+F+Z+ _+i+ y+++ +++'+, ,&,6,M,b,s,,,,",,-#-A-Y-j-s- ---- -- - - - ...$. ?.J.\.q. ......5. 30 @0-M0{00000 000011 !1+141M1 S1`1 d1o11111 1 111 11/12D344444;4Y4y4 44444444 45575I5Ee55555566 26>6cS666 6/6 77"7?7E7 L7.W77 77 7777b7J8Z8b8i88 8#888 8)8(989A9x9JQ:2:A:c; u;;; ;;4;;;;<+<#?<c<=w<!<<<<== =2= F=P= U=a= = ====&=L>P>V>h>y>>>>>>>> >i?p?y???????@'@.@5@K@^@+k Alrady exist! Please edit name to avoid replacing0018027090 Find word : Misspelled word : Replace word : word : AboutAddAdd to user dictAllAll-ImagesAngleAngle to be rotated : Append-TextApplyApply from cursorApply on entire textApply-EntireApply-From-CursorAre you sure you want to delete selected images ?Audio converter Audio-ConverterBackground ColorBookmarkBookmark TableBookmark-TableBookmark-Table-CompleteBrightnessCache CalibrationCan't run command : {0} Please make sure you have write access to {1}CancelChangeChange AllChange to binary or lineart if possibleCharacter Encoding : ChooseChoose-Font-FileClearCloseClose!Combine with dictionarys too ?CompleatedCompleted!Context labelConvertCopyCreate new BookmarkCurrentCurrent text not saved! do you want to load readme without saving ? Current-ValueCursorCutDecrease-Reader-SpeedDegrade-imageDeleteDelete file too ?Delete-AllDeleting !DictionaryDictionary not found!Dictionary'sDistanceDo you want to add dictionarys ? Do it if only all characters used in dictionarys are going to be trained!Do you want to auto annotate box file with existing language ? This may take awhile!Do you want to delete files(image,box,font_desc) too ?Do you want to fill it with following font ?Do you want to fix the angle at {} degree manual rotation ?Do you want to search entire filesystem for tessdata ? This may take awhile!Double PageDriverEndEngineEnter the file nameError : running command failedExportExport-As-PdfExport-BoxesExport-Text-As-PdfExposure-LevelExtracting images from PdfFile Name : File must be saved inorder to bookmark the text!Filename pleaseFindFind :Find DialogFind-ReplaceFontFont ColorFont SizeFormat : FullFull AutomaticFull Scan AreaGeneralGenerateGenerate-ImageGet-Source-CodeGetting devicesGive match and replaceGive pdf filename(with extention) to save imagesGoGo to lineGo to pageGo-To-LineGo-To-PageHeightHelpHighlight BackgroundHighlight ColorHighlight FontIgnoreIgnore AllImages to be trained {0} Language used : {1} Output tessdata directory : {2}ImportImport-BookmarksImport-FolderImport-ImageImport-PdfIncrease-Reader-SpeedInput Text FileInsert PositionJumpLanguageLanguage Line Number : Lios PreferencesLios is a free and open source software for converting print into text using a scanner or camara. It can also produce text from other sources. Such as images, Pdf, or screenshot. Program is given total accessibility for visually impaired. Lios is written in python3 and we release it under GPL3 licence. There are great many possibilities for this program. Feedback is the key to it.LoadLoad-BoxesManualMatch Match : Mode Of RotationName : NewNextNoNo Scanner Detected!No Scanner Detected!. Please update scanner list and try againNo continue with existing modeNo curresponding box files found!No curresponding font_desc files found!No match foundNot found!Nothing selectedNumber of Pages to ScanOkOne QuartersOpenOpen-Home-PageOpen-ReadmeOptimise-Scanner-BrightnessOptimizeOptimize Scanner-BrightnessPage Number : Page Numbering TypePage {}Partial AutomaticPastePitch : Place itPlease install aspell, ispell, hunspell, myspell, or uspell dictionary for your language({0}) and restart Lios! Otherwise spellchecker and auto-rotation will work with english(fallback). For example on debian based system one can install aspell or hunspell french dictionary using following commands apt-get install aspell-fr apt-get install hunspell-fr or ispell dict using apt-get install ifrench On rpm based system use yum install aspell-fr On arch based system use pacman -S aspell-frPreferencesPreferences RestoredPreferences loaded from Preferences saved to Preferences-GeneralPreferences-RecognitionPreferences-ScanningPreviousPrintPrint-PreviewQuitRecognised text from image {0} with {1}RecognitionRecognizeRecognize-All-ImagesRecognize-All-with-rotationRecognize-Current-ImageRecognize-Current-Image-With-RotationRecognize-Selected-AreasRecognize-Selected-ImagesRecognize-Selected-with-rotationRecognize-With-RotationRecognizing {0}test.pnmRecognizing {}RedoRemoveReplaceReplace Replace : Replace-AllResolutionRestoreResultRotate-LeftRotate-RightRotate-TwiceRotating selected image {} to {}Rotation mode changed to manual at angle {} degreeRun Text CleanerRunning OCR on selected Area [ X={} Y={} Width={} Height={} ]Running OCR on selected image {}Running OCR on selected image {} (without rotating)SaveSave Save-AsSave-Selected-AreasScanScan AreaScan Completed!Scan-ImageScan-Image-RepeatedlyScan-Using-WebcamScan-and-OcrScan-and-Ocr-RepeatedlyScanningSearch entire filesystem for tessdata ?SelectSelect Folder to save imagesSelect PDF TypeSelect files to importSelect files to openSelect font fileSelect images to importSelect input fileSelect language fileSelect the bookmarkSelect the bookmark file to importSelect the file to appendSelect the file to importSelect the file to insert at cursorSelect the file to openSelect the imageSelectedSelected-ImagesSelectionSet Mode of rotationSetting Scanner {}Shortcut Alt+DSingle PageSpeech-LanguageSpeech-ModuleSpeech-PitchSpeech-RateSpeech-VolumeSpeed : StartStart new without saving ?Start-New!Start/Stop-ReaderStarting Page NumberStop-All-ProcessSuggestionsTake-ScreenshotTake-and-Recognize-ScreenshotTessdata directory Tesseract TrainerTesseract is not installedTesseract training executable are not installed. Please make sure following exicutables are installed combine_tessdata, unicharset_extractor, shapeclustering, mftraining, cntraining and text2image. If you forget to build training tools then use 'make training' and 'sudo make training-install' to build it Text CleanerText-CleanerThe word '{0}' not found! Search from start ?Three QuartersTime Bitween Repeted ScanningTrainTrain images-boxTraining images...Two QuartersUndoUpdate-Scanner-ListVideo-TutorialsVisit Home PageVoice : Volume : Warning!Welcome to {} Version {}WidthWriting ModeYesYes DeleteYes set this rotation_Delete_Edit_File_Image_Preferences_Recognize_Scan_Toolscompleted!save_preferences as {} Decode error Select Other Character EncodingProject-Id-Version: lios POT-Creation-Date: 2018-04-29 08:42+0100 PO-Revision-Date: 2018-04-29 08:42+0100 Last-Translator: L'Africain Language-Team: Language: fr MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Generated-By: pygettext.py 1.5 Plural-Forms: nplurals=2; plural=(n > 1); X-Generator: Poedit 1.8.7.1 X-Poedit-SourceCharset: UTF-8 X-Poedit-Basepath: ../lios X-Poedit-SearchPath-0: . Existe déjà ! Veuillez éditer le nom pour éviter de l'écraser0018027090Rechercher un mot : Mot à corriger  : Mot de remplacement : mot : À proposAjouterAjouter au dico persoToutToutes les imagesAngleAngle à pivoter : Ajouter-le-texteAppliquerAppliquer depuis le curseurAppliquer à tout le texteAppliquer à toutAppliquer depuis le curseurÊtes-vous certain de vouloir supprimer les images selectionnées ?Convertisseur audioConvertisseur audioCouleur d'arrière-planSignetListe des signetsListe des signetsListe-des-signets-complèteLuminositéÉtalonnage du cacheNe peut exécuter la commande : {0} Assurez-vous que vous d'avoir les droits en écriture sur {1}AnnulerModifierTout modifierPasser au code binaire ou linéaire si possibleEncodage : ChoisirSélectionner le fichier de policeViderFermerFermer !Combiner également avec les dictionnaires ?TerminéTerminé !Étiquette contextuelleConvertirCopier Créer un nouveau signetCourantLe texte courant n'a pas été enregistré ! Voulez-vous charger le readme sans sauvegarder ? Valeur actuelleCurseurCouperRalentir la vitesse du lecteurMettre l'image en dégraderSupprimerSupprimer également le fichier ?Tout supprimerSuppression !DictionnaireLe dictionnaire n'a pas été trouvé !Du dictionnaireDistanceVoulez-vous ajouter des dictionnaires ? Faites cela uniquement si tous les caractères employés dans les dictionnaires doivent être reconnus !Voulez-vous annoter automatiquement le fichier du cadre avec la langue existante ? Cela peut prendre un certain temps!Voulez-vous également supprimer les fichiers (images, cadre, polices) ?Voulez-vous le remplir avec la police suivante ?Voulez-vous fixer l'angle à {} degré manuel de rotation ?Voulez-vous rechercher un fichier système complet pour tessdata ? Cela peut prendre du temps !Page doublePiloteFinMoteur ROCEntrer le nom du fichierErreur : l'éxécution de la commande à échouéeExporterExporter en pdfExporter les cadresExporter le texte en pdfNiveau d'expositionExtraction des images depuis le pdfNom du fichier : Le fichier doit être sauvegardé pour en faire un signet !Veuillez entrer un nom de fichierTrouverRechercher :Fenêtre de rechercheRechercher-remplacerPoliceCouleur de policeTaille de la policeFormat : ToutAutomatiqueZone de numérisation complèteGénéralGénérerGénérer l'imageObtenir le code sourceObtention des périphériquesDonner une correspondance et remplacerDonnez un nom de fichier au pdf (avec extension) pour enregistrer les imagesAllerAller à la ligneAller à la pageAller à la ligneAller à la pageHauteurAideArrière-plan deu surlignageCouleur de surlignagePolice de surlignageIgnorerTout ignorerImages qui doivent être reconnues {0} Langue utilisée :{1} Dossier de sortie pour tessdata :{2}ImporterImporter des signetsImporter un dossierImporter une imageImporter un pdfAugmenter la vitesse du lecteurFichier texte d'entréePosition d'insertionAller directement àLangueLangueNuméro de ligne : Lios préférencesLios est un logiciel libre et gratuit pour convertir une impression en texte en utilisant un scanneur ou une webcam. Il peut aussi génerer du texte à partir d'autres sources. Par exemple une image, un pdf, ou une capture d'écran.Le logiciel est fourni avec les options d'accessibilité totale pour les malvoyants. Lios est écrit en python3 et livré sous licence GPL3. Il existe de nombreuses possibilités pour ce programme. Les retours en sont la clé.ChargerCharger les cadresManuelCorrespondance Correspondance : Mode de rotationNom : NouveauSuivantNonAucun scanner détecté !Aucun scanneur détecté ! Veuillez mettre à jour la liste des scanneurs et essayer à nouveauNon continuer avec le mode existantAucun fichier de cadres correspondant n'a été trouvé !Pas de fichiers font_desc correspondant trouvés !Aucune correspondance trouvéeNon trouvé !Rien de sélectionnéNombres de pages à numériserOkUn quartOuvrirOuvrir la page d'accueilOuvrir le ReadmeOptimiser la luminosité du scanneurOptimiserOptimiser la luminosité du scanneurNuméro de page : Type de numérotation de pagePage {}Partiellement automatiqueCollerNiveau : Le placerVeuillez installer le dictionnaire aspell, ispell, hunspell, myspell ou uspell pour votre langue ({0}) et redémarrez Lios! Sinon, le correcteur orthographique et l'auto-rotation fonctionneront avec l'anglais (fallback). Par exemple, sur les systèmes basés sur Debian, on peut installer le dictionnaire français aspell ou hunspell en utilisant les commandes suivantes apt-get install aspell-fr apt-get install hunspell-fr ou le dictionnaire ispell avec apt-get install ifrench Ou pour les systèmes basées sur le rpm yum install aspell-fr Sur les systèmes basés sur arch pacman -S aspell-frPréférencesLes préférences ont été restauréesLes préférences ont été chargées depuis Les préférences ont été enregistrées dans Préférences généralesPréférences de reconnaissancePréférences de numérisationPrécédentImprimerAperçuQuitterReconnaissance du texte depuis l'image {0} avec {1}ReconnaissanceReconnaîtreReconnaître-toutes-les-imagesReconnaître-tout-courante-avec-rotationReconnaître-l'image-couranteReconnaître-l'image-courante-avec rotationReconnaître-les-zones-sélectionnéesReconnaître-les-images-sélectionnéesReconnaître-la-selection-avec-rotationReconnaître-avec-rotationReconnaissance de {0}test.pnmReconnaissance {}RétablirSupprimerRemplacerRemplacerRemplacer : Tout-remplacerRésolutionRestaurerRésultatPivoter-à-gauchePivoter-à-droitePivoter-deux-foisRotation de l'image sélectionnée {} à {}Le mode de rotation a changé en manuel à l'angle de {} degréExécuter le nettoyage du texteExécution de la ROC sur la zone sélectionnée [ X={} Y={} Largeur={} Hauteur={} ]Exécution de la ROC sur l' image sélectionnée {}Exécution de la ROC sur l' image sélectionnée {} (sans rotation)EnregistrerEnregistrer Enregistrer sousEnregistrer-les-zones-sélectionnéesNumériserzone de numérisationNumérisation terminée !Numériser une imageNumériser-une-image-à-plusieurs-reprisesNumériser-avec-la-webcamNumériser et ROCNumérisation-et-OCR-à-plusieurs-reprisesNumérisationRechercher un fichier système complet pour tessdata ?SélectionnerSélectionner le dossier où enregistrer les imagesSélectionner le type de PDFSélectionner les fichiers à importerSélectionner les fichiers à ouvrirSélectionner le fichier de policeSélectionner les images à importerSélectionner un fichier d'entréeSélectionner la langue du fichierSélectionner le signetSélectionner le fichier de signets à importerSélectionner le fichier à ajouterSélectionner le fichier à importerSélectionnez le fichier à insérer au curseurSélectionner le fichier à ouvrirSélectionner l'imageSélectionnéImages sélectionnéesSélectionDéfinir le motde de rotationParamètres du scanneur {}Raccourci Alt+DPage simpleLangue de la synthèse vocaleModule de synthèse vocaleNiveau de la synthèse vocaleDébit de la synthèse vocaleVolume de la synthèse vocaleVitesse : DébutDémarrer un nouveau sans enregistrer ?Démarrer un nouveau !Démarrer/Arrêter le lecteurNuméro de page commençantArrêter tous les processusSuggestionsPrendre-une-capture-d'écranPrendre-et-reconaître-une-capture-d'écranDossier TessdataROC avec TesseractTesseract n'est pas installéLes exécutables de reconnaissance de Tesseract ne sont pas installés. Veuillez vous assurer que les exécutables suivants sont bien installés : combine_tessdata, unicharset_extractor, shapeclustering, mftraining, cntraining and text2image. Si vous avez oublié de compiler les outils de reconnaissance utiliser 'make training' et 'sudo make training-install' pour le compiler Nettoyage du texteNettoyage du texteLe mot '{0}' n'a pas été trouvé ! Rechercher depuis le début ?Trois quartsDurée entre les numérisationsReconnaîtreReconnaître les cadres imagesImages en cours de reconnaissance…Deux quartsAnnulerMettre à jour la liste des scannersTutoriels VidéoVisiter la page d'accueilVoix : Volume : Attention !Bienvenue dans {} Version {}LargeurMode d'écritureOuiOui supprimerOui définir cette rotation_Supprimer_Édition_Fichier_Image_Préférences_Reconnaître_Numériser_OutilsTerminé !enregistrement_les_préférences comme {} Erreur de décodage sélectionnez un autre encodagelios-3-2.7.2/share/man/000077500000000000000000000000001345364566700145305ustar00rootroot00000000000000lios-3-2.7.2/share/man/man1/000077500000000000000000000000001345364566700153645ustar00rootroot00000000000000lios-3-2.7.2/share/man/man1/lios.1.gz000066400000000000000000000015201345364566700170310ustar00rootroot00000000000000eTێD}Wd J(NVf:vn2y۩ng<$KթSU>Bڦ~ ̿K~[$ xV( PJQrS];&'!aK /w~~ABg4N:CA(p^]m8F4`   pF6M`FV.=E(;Ϳ-1-9Ҳ`}p(+ f!-K2JBF28]Zg  B"pCLYXϥ(xDž%F79r5ZĂ%r x8<ӷԞrF6!l75d% ʨmB ݏ!*/gd} 8B4m&@/.MVvv^{mfN-&y{(%w`a]/!{Ƃ VhPQXQi֓[bDMd^a)%xyw+*{8b[Q@ ߒ9t+yXTM[H#ȗ{xsF]Q T*Y T'Qw.C {6mAVv!u?[u\ss7j~{PcvLN 2Kؕ=N62̒ ⿿ny~OMD*A]pusHݨa6.H^އX;jk9fI%8Za3idu[]]WwW( ѻQ8%?PXlios-3-2.7.2/share/man/man1/train-tesseract.1.gz000066400000000000000000000015261345364566700212010ustar00rootroot00000000000000eT]6}ϯM_Z 2+Uh- ,K!"RYU& ;kf={!mSHqwo? +h/mi jZ4t8q 6jˮ. j=ź # шKW^{y8|gmFD$Etz,!w‚; hPQXY7i֓SYjx!`W:H-λ[vfm܊*]⇜NHEלu9`H 6yٹO&tT+IHOB ]DJiR )%|~7'=N)n|]ET7"qOgjwsmϿtK؅#S }צB͏+/0 c #7A327C5A76D3", ", c #7BB07BAC7BB6", "< c #79369E543E61", "1 c #795381D86C1E", "2 c #8266A8D945E5", "3 c #8710AE2F4985", "4 c #8B85B37F4CA5", "5 c #8FA7B8594FA2", "6 c #9442BC275600", "7 c #9650BD785971", "8 c #98DABEEF5D9A", "9 c #81E683F17EAA", "0 c #86588B887E18", "q c #86F693D47301", "w c #9A7FBF2761B3", "e c #9D68BEB769A6", "r c #9560A74379A8", "t c #9BB7AF087DF7", "y c #A580BEA37EA5", "u c #9800C23855BC", "i c #98DCC2B7571D", "p c #9C48C62C5AE4", "a c #9F14CA5A5C3C", "s c #A239CE605E67", "d c #A3E5CF156043", "f c #A60BCB166D1D", "g c #A5F1D2466180", "h c #A9AFD6956470", "j c #AC6FD9A6661A", "k c #AFA6DCD268E1", "l c #B166DDCE6C39", "z c #A7B6C7F87633", "x c #A754C1F27E76", "c c #ABD3CBF97A28", "v c #AEE2D52F73C2", "b c #B3BFDD7B7269", "n c #B48BE2CB6C7C", "m c #B8EFE8686F98", "M c #B7E2E6397001", "N c #BC79EC36729F", "B c #BA6CE2257C56", "V c #C1D2F2A57675", "C c #CB7CFDC37DA7", "Z c #152B865FAD66", "A c #18BF8701ACF5", "S c #1A0588A1AEC0", "D c #22CB838FA4AA", "F c #20F18AB5AF3A", "G c #2E5E91F2B444", "H c #44F79A19B786", "J c #561CA405BEC4", "K c #5962A36BBCC5", "L c #6D06A977BE2F", "P c #72FCABA2BF28", "I c #7E98B170C2D5", "U c #8364835F8363", "Y c #893A8D9D8259", "T c #87B3876D8821", "R c #884687FF88C7", "E c #8BAC8BAD8BB2", "W c #9051984783E0", "Q c #90F693568D48", "! c #96759D4C8BD2", "~ c #93DD93E193D9", "^ c #997999839946", "/ c #9DD9AD5585C2", "( c #9807A09C8ACF", ") c #9C49A7788ADD", "_ c #9F57A0BF9D1A", "` c #A2B6B71A8330", "' c #A563B9C285D0", "] c #A247B1DD8A28", "[ c #A257AE2590E5", "{ c #A4E5B1979154", "} c #AD28BD6B94AD", "| c #A429A478A3B7", " . c #A92EAA9FA6F2", ".. c #AC5FAC72ABEC", "X. c #AF62B0BFAD53", "o. c #B543B618B32A", "O. c #BB2FBDC8B723", "+. c #B526BB73BD9D", "@. c #BD15BD73BC90", "#. c #BDC5DFDC8819", "$. c #AF9CC0E494EA", "%. c #B6A4CB669664", "&. c #BD1ED5919715", "*. c #BE16E2FC84A2", "=. c #BF48C25FBA68", "-. c #C0BDDB8B96F6", ";. c #C34CDEF3987B", ":. c #C229E5648B84", ">. c #CF53FFFF8164", ",. c #C5BAE56094C4", "<. c #C7A9E89D94B1", "1. c #CB03ED37966C", "2. c #CC43EA9F9DC8", "3. c #CF03F3199795", "4. c #CE3BF1559827", "5. c #D221F6A49919", "6. c #D412F99299CF", "7. c #D21CEFCCA470", "8. c #D50AF217A812", "9. c #D7ADF427AB8F", "0. c #821EB25FC30F", "q. c #922FBEADCDBF", "w. c #AA4FC016C7B3", "e. c #B81CBE3DC057", "r. c #A70AC1D4CB14", "t. c #ABDBC398CBC7", "y. c #BEDAD0F6D710", "u. c #C3E3C3B8C3A7", "i. c #CBEECBF0CBEE", "p. c #D033D05AD029", "a. c #C0AFCCC5D0EF", "s. c #CB51D1C3D408", "d. c #D5A1D5B0D5AB", "f. c #D8C3D7D1D76E", "g. c #DCB5D968D844", "h. c #D6B9D9A0DA8E", "j. c #D962D8E6D8BA", "k. c None", /* pixels */ "k.k.X + # # # # # # # # @ # # @ # @ @ @ @ @ @ @ + @ + + O . k.k.", "k.o : R U R T U U U U U U U U U , U , U U , , , , , , : : & X k.", "X : U U U U U U U U U U U U U U , , , , , , , , : : : : : : & . ", "O U U , U U 1 U U U U U , , U U , : , , , , , : : - : - - - = o ", "@ , , , , , , , U U U , : U U , : - : , , , , : - - - - - = - O ", "@ , , , , , : : , U , U : , ~ ..| T : , , : : - - = = - - = & o ", "+ , , : , , , : , , U , , ^ p.f.h.p.^ , , , : = & = - - = & & o ", "+ : : , : , : : - , , U R u.f.f.f.h.u.U : : & % & - - = = & $ o ", "+ : : : : , , , - : , , Q p.f.f.f.f.p.R , - # & - - - = & # # X ", "O - - : : : : , : = : , U u.j.f.f.j.@., : & # = ; - = & # @ @ o ", "o = = - : : : : , : - , , E e.s.p.+.E , - % : : - = # @ @ # # o ", "o & % & & - : > : , - : R ~ ^ X. .E ~ U & - : - % @ # # & # @ o ", "O & & # # # # = : , : U u.f.d.d.d.p.f.u.U : = # # & & & # # @ o ", "O = = = & & & # # & U e.h.g.g.h.f.f.j.f.+.: & = = & & # # @ @ o ", "o % & & = - - - - - X.0.J q.a.h.f.y.q.J I o.: = = & $ # @ + + X ", "X + + + @ @ @ # # | j.L Z S G J J G S Z L f.| & # # + O O o o . ", "X O O O O O O O 1 p.j.P F A S A Z S S F P f.p.U o X X X X X X ", ". o O O O @ # , i.f.f.a.t.K S A S S K t.a.f.f.u.: O X X . . ", " X o o + # - u.h.h.f.f.g.r.F A S F r.f.f.d.f.j.e.- @ O o . . ", ". o o O @ @ Q f.f.h.j.j.p.P A A A Z P d.f.f.f.f.j.~ # @ O O X ", ". o o O O o > i.p.i.e.u.p.0.H D D H 0.s.u.@.i.p.i.R # # @ O o . ", "> ; $ @ + + # , R U : ^ j.j.s.r.w.s.f.j.| , , : - & & % % % * * ", "8 f z y ` / ) ! ! Q , _ p.d.d.f.f.f.p.p. .Q Q Y Y W ) ] ' x z e ", "6 a s g h l l B B :.:.,.2.7.8.9.9.9.7.2.,.,.#.#.*.b l j g s a 6 ", "6 s s g h h l n s p N V N n C C m g m V V i 4 s l k j h g s a 6 ", "6 s s g h h l n 6 6 N V j 6 C N 4 s 3 N N < 4 g n k h h g s a 6 ", "6 a s g h j k l 4 p M p p 6 k s i >.4 a a g 4 < j l j h g s a 7 ", "8 s s s h j k n 4 2 a l p i k k 4 h 3 l l s 4 3 k j j h g s a 7 ", "q t x c v b l M l h l V M N C C n s n V V n j n n l l v v z y r ", " @ - > 0 ( { $.%.-.;.<.<.4.5.6.6.6.3.4.<.,.-.&.%.} [ ! Y > # . ", "k.. @ % - - : , R Q ^ | ..X.o.@.=.O.o.X. .^ ~ E U , : - & + X k.", "k.k. X O O + @ @ # # % & * - - ; - = = & & # # # + O O o . k.k." }; lios-3-2.7.2/user-guide.odt000066400000000000000000001422161345364566700154420ustar00rootroot00000000000000PK}I^2 ''mimetypeapplication/vnd.oasis.opendocument.textPK}Iovh##Thumbnails/thumbnail.pngPNG  IHDRPLTE  ( + 2 %(4$9") &$';$'"*%'79+(4.4968&G/Q5N!*D .P'2H+;X7:F2;T-D]7DY7Kf:RkC+#H7-I95Q;/S?;F?BB?TNB>WD:HFHHJUWJFQOUYXXANbEThFYtSWdR^rKcz\`mYh{cMDgTIj[Ts_Vn_beb_xdWgghijumrdmt}xjgrnuzujxwx~Xl[sb^dmfui|x{y}w~h|p#%fwH W\v<7 EX?jK\ `;oof^EߋUM&uIݤnR7M&uIݤnR/uUf+l@NPoAG>wfVםOxZٷ짦tc{>oLLזYd>S/$W7IZl`˧(?nG#P?Inq$^S~mBC˂=-9{YWV(-?@в+?VF*u!I,KQJihRa^Oᔑv}yRT5szrU>EIӞAXи4ٍ0ũ",]LI we%_KKggKgllٸq`S_gk۹+--_ڸ~=᩻X+Wkٲ5ze5}j㏵q#UwUwZ_ZuWxP/?S$Ƨ,](UwH4/Yoxܷ~_'s{o=dzoPOӟƏ Uk_uxF^e*K3nlR70u|6g;QlzTSisܰuYVTQ^_/C7N-? =B^mnM:F `v'MeFVz^؛(ʵ;<яUvz$[&G24"C-!*SlؒtiM_}jk}uua$gv~0D(FRv?%zezLi)J H={k-׽uo}[E: J?9p=~㾾~W =+zz);7Vןo]mDmrM=;4t]/gW K`4ZDVӍ0tJD4bA8筌yȱ.Nţtt*Fk5ZUZ*(Q\e%=c%ˉ vm9G-v hBW$w1&|;3}䢨w XߪF0>V>Q"9/8 . \4~e8#|#%e{􉮡x>Ga}1 䓜1! /M T5F[¾D`u( 0&R]b CgXE KY*( 8D) AZ*! BΒ;v /qUY|#K׹BpB{ y91ujy150K]5V WӔ8)Ym\3(Bĥ K `p2 2xDx0^ I0$$eP0$)Bdy\cyZd TY*B 0iXRLp-aTf!EP< /P><9i`` :HG *wV>pa+婡+۱H$ xBs! tAvXo(ō]Tr=lw$`nkT=5D#F^D9Ԃ w ȼ[ '3\֨TCԱi#\d Q ki1H%IMUj 8p!cMb%? KE= ژ )9%̟Ji. ?^n=ڝ`g JsOTEw1۶9'D3![fY"iuH۪dŗs9ٳФ^t ʋf(梗Y|~9l(g1S&u{f&3fOGtxfrr|$-쟙S/w߻#=wԞ%F痊idӆ4M&uW:bTUb;{ G]njL KBВ-ĢtehiЇC'j4o^ݿ2Qx㚻RJoO䆢><[]+[o+ި ^m~zuMo8xզƒu!A(eӢZEڴXJ"@&)3!jڐwz;wj:yRQtCcGUBsbu,Y5 Q^ ~c(BaJD,!NDQW!s<y$eȑ$G*$\$$ Jz藙zh`+* ]/K"vuf!hַm@ȍH( u._fB\|&K%@9`KnPsj*˛sܒfKmXlP:g]%1S+\{nκl(]P]E/UOuƂ'eaG0 "( 1>k@E @*jSͳ;yG +Cl}mH!~(GD;K_s=\)͹U je"\* LKyw4W޾udn1wq=B}-^V+Jmxr="Ch1 &馑 ~bhd"",,CĶ7cȶx%]yMZ "a`7oE臃"p@oá+8P-e#V>a ]3 !Oj*ucKfQXzrVԕ0s)4Y%a9Jx)`J˵U?QXR4||Eӈ,'&JqڂS,%@<7t\غo~~)N0x ]͕Lp4Qx'ǀ T" 1Wa. ݝ|ɀ5Ma( ^{ש%W q0MAHGbG4.S"qJ'~ V$(S ƺ@@=~"%(*^_b\Ȧ&ϡֻ/!;hIaZYQF"Sp90W_ Nay^ ;=~濄^?sv8o C4z<|")h@V |O ~?Bͮ ;i 2T|=$9?Z9(䄰1o pkQ}!;cGӽ7P5i)5:pv/\Xy8I,dKDeH@LX}_R8!Z,Vb**%P~BEԴ[w?"Āeb{Mtv, &s =oC~GyWS*.YOL=[4H4J<u/4[ԣ"}(iVaiYp󒲫Wjx]v1 6tVn`ڭ:dleռMf 3y(&ۄ`mƬb͚iIxJ*KhX>0uMf0mY.IO6-T8egt{1#e٦$G]DNp<C+? N.[$ŷaΟKpȱ 4 -M]cEy5I6&kq8DIĢ^ > 9X VjM*;"`7\/I+*!ȳ$B;Ϙ|/.7>_T<[%8[L34;Q]|o{F lYjIQF /_viN $["|ߦ̱`b˼|.8‡0^},@Wϳ} qA?#r[xеQ[>Z<w)l<] xF {$r@QV鱄>SYKUhwC䰺L9b>!я߻?(y$gPr ӐElj]EEބx>؁ -F A2s/d/~ n)y(Kk/zO(e˅6ܑ v V|#  8 L݇ǥEHU$(7.A,5$x6SwxGnQǨPԇf64,u訁@~E^=#4[b\kf8Ztff|+T,FqA۲r57IP;b4|Dӏ!l8jͺ){faQX!IT$ڒ}һ "Z6 dmR141crf:C,5\Ovq4P<{y>%F#a(I\`@h4Z9Yh[ q]11 uXaړzBicD=˵+Q_):"reȩ1emD+fv`\°/=s\-\Oe:j4,](GP  _!`G/"嗌[c*B2Y"5[*Q׎O`U(T,\Tw1N \p~wh1r)ZVb@/1cey6 2[r+]bQ'SV t0p?W(3!p]?}mq4mCnDuBb%)F>")UDAr %1DLʨ)l@1$G:r]Oǔ_h^n>ok5W{ұzc)ԅ&7Sx{0 uT/) o-tzb5EpMEbi$!8Ch,6b<v͡]DwO w7],lPgAXSnQ@ 73/yh R ZRx. | L9!P1`ƺ53'hWi?j :Wh{"R| Qm U8·}-(T#bfsHkv. S5B%E"=Sr\ Bt|r7\+n=1Fa\彬څ ]6B7b?Y?=w''-/.f]!#!C>'0F2%X:B_er {orJN#c甐^7t'r&bİ*˕<@axbIUE)ec8uP񆺨$I:8ۇ |c@"=[V7.۳o/C<o7@^1 [Sp w/q.N.Y.]VB v), Cn_b36+|MGd挻l.$e%lޮfXM\v.({oahNtg$vصY%:= Z5rVS:G3wFcR[PlgM]Y3Q^'\F4o#Ø<$E #&V3 ڭc\eeogIݤnR7M&uIݤnR7M&uIݤnR7M&uIݤnRr~ IENDB`PK}I layout-cachecd`d(Hg``p ,P"eX /D=ʙ䜁)c2PK+&>FkPK}I6!5DD5Pictures/10000201000000AB000000AB563B5AA6C0D3A786.pngPNG  IHDRlsBIT|d pHYs B(xtEXtSoftwarewww.inkscape.org< IDATxwd}&=StUuW3 v` @TP-u$]ln\sRh.)+AA0q53=tugW:++X|/{LFL\}lh\f>?~ɚx #hB.EHԗA ^ _G 7Ys~Dn ((dY']=뇸a $=i;|dxah^n $'\n b.2sNlٲX eoNDHiuW8nKf:r`hZLOOcaa ?|~KȚ5dnFr9KV2MS(])Dq~ʺncffGAR<_tו\ R$M7݄={T񗂴UK<joU@,=vnH _(bԩS8|01ng|O"$k.Sa l޽[Ūj&$',QNiry$=N8ս4kB48ume5n%$nUW];Qn5Y;)7 7d#Ƚ$I ;( nR)7HkSB~LNNNs?~؂J,:py+)=N l,sF% ^z Vf>vSP%IC=%$|/aXЪyviv[;?*'q $^|Eb?#wi~طoE#Ndr[GQ^EiB4EUM8_u8y$x X'/w!={w^kI~N/jϫ[@ѯ7/ٹ쵬;uΝرcy [vFD"'>aw;eȠ i;7cdYh_垇@ J,ܭwՏn{ɿ6|-Y믿z$r%xdq]dvXI(&^v#&1'ݜﻋ^͆ǻ5>d}vb1:%csAJޟhnEi瑕u]zf;潀-8^"t2z!F-?$I®](!m6 9l?, ð:pY Xna{^Tx 6֟ߑ6כ0rccc<ߨdRH䞖|^u~EeYΎ"R^Qpҷɯt˚տ[4݋~ö*>z'"~zQ҉!Ϟ(P̣ @3ɲ(8n6AO(|A*@CDX R+)I8XnCX_I,M6*aUY:Jzo@$qMT~n&pt] ذeE@D_/aNcN/Fhꅤ^ L&=;_H$:@̉^8KӕHSѠ.NxI^KE2P15ZϜ}VUqAtA›3o4]E`dYF2NXb L{!, !R7ryq*awYwrCDGtϒ   %yEA"![nYUt#A"~ܳPUބ' ð[^H*L8^0PAx$Ih4hۮR6WU&*1cnV[32CպIRܮ~I&9$d B]]ZlZkw7VԈ mxB|t?E-5Gb`0U{D?/ڼn^{ZU*Yyhϼq#zi?6 '5a&ޕ57Q Tk񤪓!D"9躎Zƭ-~XSY EҡVk]440i;?ߘ<#R CMTݲ앜ԀrӐ9^{ 7y"HrӽǓMOO >h= #@&- ?tITQ9{=ilI/Js]st]wA!N+" pZ56qOr'fFc&1;󍙙OUǚ "Htً+r5 zHu#dYO$^ ɓnR&W"u> !sN"]Y>K>h>`|MΪ DIX,8Dv^l6QTK[9(bϣ|MIW}? F 6 `SNX,r=_8z\ۭ' RՉDG:y:VWWQz$!%F${pO pV "4 Fg)/sx/{i/usO^bhh;TT~2 +X2Wj'znOBА]fˋgm4X]]AV2yHQ0q%+4 zF ]puT9NLzuݖT"Na G?qx鎢t\.;#JbmȝܷZ-J94ܸDGUUaBV{"+ 2_mz!#/!N+ Se{)J8i `uc=s=^x{ >=9LJN+w0PT*V< kxů:Y@:|eYF($atB_8H:J]T$ +9B~x=sssO=畗&Kw[`fO/l(ew'AFңR/dꙀ̠iVrz8,EKtuȺ'AjۈD"U u333xuV{ _u z꩞D5 m^Q*i?(UTe(,# <g&ŢkV7s"i&BPRT$,!X,b||'" -J%/aiJd+/g:@{!bd%ik=siPV x111I酆ah`qq'O/~yJV^Ҥ"nHv( ǻVW@֮n\. gP⑑A$du jjD"]'-gvҤfB>-~:IF{ pmm ǎ].f6%`w(dG*V* N, Ҁ' -5^ xRP?jzpHDH6_'I6T###iZVWW144$$lcCyKbs{^^aQ'''mh4P*zER4 uD偮1$IYr(u_~)2ujՖ ?վHB!dY,..tD"=hG% UUJ%]D3Mv{v@]RD=-NWT:Ae{I`*IytV'~ل%ne_/ahhȖBg_d2IdY _mxh6XYY‚c6Qu Ijb`0h4ʭyj*qLgducݑBÈbv_ sIIRWZETM${/W:'''g<3i\ D%yjңneYF$7p#[*rC_{WKkfK0OO---T*ux SQ[O\^^`СC QYa}0Mk.3/oKe $jj4+(_ H$Dy 䞖<룍bT*h4H&044.40v5jUr$]h$ID"Hvbdk9'IH$U$-[xʶiaE %$ drU@ [oE&R<=T؆aP(ؓiȲD"a"p"IJyV;pKC!~GD&G)ULǜ2a& ahhk[f G"<)*[nK/JXC`qq;* bhhϙ@$n~$HҲI4җSDaFF`0T*%ld"}}R KKKvw(LWE ߉4^yR8 A^T0H^23aYqwcD0<O^ů–ݻL&m/q Ats+%<9ջ+o [es=xꩧz3{uD9(\J2Ed}Xiw")ʾq ~!UE:Ƈ?ah'BZėZD&(|ނ#iAal6e&N:$Ivc2yg&N/̻3Xiy!O?ݥ"t?㽓xNaq琀mhd!MgڜG\4qw8`Bė^Ɨ^FRxh.vmnLTz ]=6o==YDEAYd2:t>,q/#iwn*Hsu%+iZ,EWIU^{mW˟IlV5nnEG'ޭ=E8F8F*B1ޞYSoSgVQoOC. 7܀W_}6Un$펞4E某d,/HhiL,+!Nj1߱c8 k&Tu,#xtE8x<:zOe Vn N<֋: *wvn 'B' j^AG5+1܊@ӳDa*!/{?66;WaNNB@&7 -h>dиQ,[~uG!=;^ ԴwX+O?OyJ5 ? iqMr!'NE'DS|5.4)[e<&Qm )xx駹Od#ZR5w]0x7xg I^غu+nF|Ob~~FO IDAT>ׇ vT#٭kz5wJ?x>X7" |:KY{)CkAɜ8v(x'Gܱɺd2|3KL.9홬N^B$h6yW&/~h cn)h dK[ouM-8T2X0c˫8Vdyi\I-rۣ2`W6^Y d>CPT/Zj̚] D,6^ڱc XrDd[A@h2AlL+2,~ၬj:x3Sk(N,Q}L!Bߕ½ ݸ+4MÓO>yZu*H43{'eya+Ⱥcǎ,`2ݎHN2na=kB(~VGXIQ-johsnD5AR__ۓELӴ$ mr !Yop#ĤAIH 5#,x9.$t?}-L޻$Uac9V\i|k_'$l6ĥ]E_dOk!KZ|%D!ިd+:GO摕nh *Y8gW{AI/.mN:ŵ' ӂ` ^i*WXiY")HtMrJYJfէ^?m{n\uU~ 7<;S\I>ÝC&rw'믿 A"5pX>ۗ^XIk+|V9X6&#KJ]W~bb GxTV"ՠG7v֠p}ayyB7i;ddTEss7Bt EA(t:D"h4ETZu.tRc{Kfxvkm> OGE,fn79td2FnN^EVIZ?3HB%1=i=>o#Lca/銉D#"ĜRKv{/n1^ u4$a5<6PPN(غu+a3OF"R)d2$#2@N5!aBg_~ݸ<'BsÓi4/뮻wLT?d˦D"aoGٝ އܪ}VO2,kqËIu!/$Hyx!*lE$TUE40W:`s#HOuBPϠĥ E}h44> ⪂ ޥ¶mBD5SKDh, 8ׯ4땠^%h6s.4Z?xu)5_C$hi֖`Νe J\23EMb:ЉL4T*,,,P(\rP-Uj_=3>Zzy=jD4DTwz'U&DϦivG[b}1u'gXt r A|OWw&=[h)/4ʲ5@_YlwER=A?ٳ}e WgPQ@?D`jmzO0}фdY":~&W}5M*ىn/yu&(y1`yygϞuݧ|1d~gߟYÉ{K,ݶZ2L\q!|hŕ( 6aՍ 7D*ѯ~AۑjK_{JV0 UUbU]] ,Tx,cEFSkf5;ȅB!TwyNd+EyU>o AZ󚦡j~^{ {ݻbnnsssXXXi=2 s9\Z7BMS\&T nN)x|Z[oUU1:: LLL L O}gIC@KTФJnvㅠ>nE)᭷CnC @$(vcrыIyaiNH$wB QEB"nŞn(Z-nCX'@8FZO~ۜ\ĥD"@ RBvm*E^S/"; _i:qsgWlEcޚ_uEU<.--ٍ>BA"Ppa6 z `&bȖdV4MT*4ͮcYrु{5 kzWkEXRa3p4sB'"bnbhh^ۄd(^&*B Ґ'l<a]'"]jX,c^UD>UOGr:yG0{AHzGY3riJ"ˊJ,v\>-1992qHWZ{5i X)Σܘgh+h$ACDCLx %t㙝ؿ `:"VK,ci%N/\׵$ɚS[HcO$}B`DO#J$/Y^^@/'uȧi {teAdb 4D2щ4ie12:ljp @DXFU_@XDU_DM_DۨC ,ϵ`mV6y)2D$8"B FuW=h (W((X^,biⲥS?1D`tUbRIHTrm61 FPV iŮylj1fziBr!)p)1q mȆZjJ RKX^XEZ"Kd<.UDJVZq#,!M80Dh4F`}OTfe033eO+3F 4M㒐.DDdXXhPpH PP p Rg3O: ltXE42fQ뒒iZ{sR 0_G5sus0{ՄDHBHt1C8G$㏲f:^CQCVEZEQZm`U7HURH dE &{/ƶ_:d^,3887G=ST\m/~H65Yʨ66F7l~sfB<S1%QËr3E ܆__43Y|𦏗p:vfB gȎcO?JӐ$ va( &-{c3@rSUX8 <&?z ?s=RKs)?zF|߁xӺX*Y']uKq)}J8 RǦ&kjIXldm@ J} ikv޻ 0q>3Wqo7;XD IMMZ"FVlYd 'wltӪ:OC~|/]T%|OOը[s\nXSSdsΣ-ę,~`C>scKss>x<6K3 شd]^ɌV5KRCLӄ"x3]W#^x}wM'0>?}=KcAasddm)-qf`0<.Ѡʸmַĩ˸IkpV?+ox$`02Yk7I~KV:2586:VΟY_rg;gOߋq vi7W1Ǒw__W`蛯i%khBTZW.ͬ5~֥9dU2k`x,ϗQ64 :[ęǿ஢\Jؼd-[ho`,53杬h(Zb!m6 wWJ@=il۝=o|v { H\%+cMĽ~󿼁*"Ѩub3(Vܳa|'/XL|K/ٶԀ8ñ^~EPˆ$,JXjeW<4/mil*x6jZsު^`p8~70ADd |ƟX??>@]yɳGWW:ޗHV/7Pv7$&'w{qu#) zURm$-\[?|ߔPZcy5*(VQ.QY+XȔFgaYR%wNWWoެ+xoSNah(sgR sMwcߘ?4*-̜X"K21=\lʲZ_@[Z"L; bCx($i,Y@qO$B": eN\u_zGz k%`]hz ]ޭ%`U vZ<޶$Hiϟ?B{QCCbݭ8^R莃un Do#9lĆ' wz;v[VCU̟),rd(]:BAgr+-];a ܱL (e`6GB[=MnA&922 Ik55s s-t>+ؾ7{R݅I% bȣH#ʣYaPaF?i߾}׵Z$IB"MhvC,jZqr Msd/Y9U(a$𞒬TDD9G@UbqHLD.{~Yo߾=HcIl|[NbtdN!DŽhYwf OD !$ !,eFFR=DymKy,,cfzO╟y7^G:0 T*dY[:x<|9o8 aecزmcf&0EXFDʮ&ͬ%Y6m"*4)&APJ %D !$RJ+ 8SбXJi ] ?Ww纼VE'5B֯]pGqjPF2ȌIg0G*1i'|XED(C{kƥ@PB#BI2WhbQZ0snhϝ% 3m0a1r_QضmƄDeĞy. TidGS J#H# L۫3yPC2uhR:uԡKu^AeK5W`PbF ҹCP"PEPJmaV+)P,\| źnn]}> >@Ȉ}̏,g4M˘9Up+Ԑhã)d)i:')q$)ޭ2nj0:44 CruhEr]jZƢ:L@J TTdXQXK%() ,BF ?[7**"V(wXX.cyR,H8wg:Ν;G5X§=r/dY\ve$F^N Dt xDXĚD"N bcP尐N[Ld(%&4jadʝ1Й^G]C]CYEQCYG^CVGVG@\*6 /|!8IJ7)?~$<5O,//#abb]G6Z^3Wb#Gw|(f<|>\.+_kNy FG|7Z;9 m &A`Mzt @@TD8`)KJE >!+9.EJ%=zNoDrkSM;`ǎ֌osBm۶arrRxSAx)$;pgbLܱɚ;Io0aHF͓^6lx~qQs:5ߞ\C^D}v  jWE)';: ^!iǫ_/mn|>zNgMsnx}>z~!Ƌ|~蛬4r6X 0`sæY3> 9ag7&aIENDB`PK}I styles.xml]KWrNHx'N\T "! Y`HOI%굞kƇF7^f'8ct5pДO?E{:ORKMys>~ EIOD2έ瞨XWqK ]%oMM}锡UWa 3UxͳhF. $HCuF/d0XVWeaN%W peg|0 , U?뫔)fAm*wy 4ζ;NO8eH,Z~_l-%ykP%}yJSU hU@W;WLKت;WUMHXNųz oϰguICnv&NϱВgz>{=A{%c,!20j^>|seERyU skWW56s-)m@єdg?s$A,)p:l ,ζ ڦv|V80m:w򮛥}PIi?nygVA{W:R(OEbS4mr%eI!iN#~pXOK&SOL [&W:X%GmoMŮۀ[S FXv1jt"yAzfEZ91>r^A.El_ )Ղ(*m2n@Ӿ׹;bݭݾ噑OeƖP4Pt] GA}J1#=~eHw-@wa|`[p( 5H߼2[( 5H߾*8Җpq^}x9) 5H߿2oa#4p*A|ІsEi Gz4|UPЧԠS|7L>Qg4/_dqSP+[:˗R>cyt,_J s~#Rj]H;˗RZAaP9m$۳!6IXWi?GiG4R 'H0n~F pCKQ]pOʟ3n`.W>O?:4$i~ 0VDe_,+n 8; 1TgC{!K⇫VM0"/L0D(xm,5LP qӻ Wp+|n*0ִ~>ڱoInP2?߅U9.k~NhֵVf5 vlO}ՕD  JPXZTzNC~ n[x_zn;FfG{PێmK]7PTָ ŻPK$3. bPK}Imeta.xmlO0; aVJE%nY߾ezo=!x93V IhiJ]}C&7OOJ/Π:o-JѪkq;MznkFR+kk8}G&2$2w:U^Nm7n;qIi :"8x]͊L͊ʊ洌`٥[*O)[t$=VUkUUd_Ȍqjjdm+לU7~,v u 7'ִ lpXlV| Y%tGVzme`b #3+~ ty> C(Π=cr zGQ{Rȧ+[ 1C'Lş,92%Do}?;:hTm|'Z=hO<3fFl'ᴚ)u#A\[L{L#ͷzPlR}ڂ' DTuG 3zm%_Ӳ5.Bl 'l|/o{[%z*$Euʃ΂816aaXۊ7J;)_M3o2!=6G 1~j{T?D[D XܝJTJiR MWT5K{F'G<.dnxD+Q)#rkgvLp4C@E"XRF_ z!{Ol=}sOq`Fу滤r2}8J+P* >O3'tKK}, r|e5"&0Ly([,">wj3R&lcPcOJ4-;˶@ciWb|ndgOmu3>GQ_@ɦLRI=/bG@RVЦp0bEl6f2d]=dѐrJe{`s?Q'7;8s=RimcmϊUDeC~?P}^WPK8&)PK}IConfigurations2/statusbar/PK}IConfigurations2/toolpanel/PK}IConfigurations2/popupmenu/PK}IConfigurations2/images/Bitmaps/PK}IConfigurations2/menubar/PK}IConfigurations2/floater/PK}I'Configurations2/accelerator/current.xmlPKPK}IConfigurations2/progressbar/PK}IConfigurations2/toolbar/PK}I manifest.rdf͓n0{vȄ]I BhwދEV{sDv;̴(>wހ4IzҴX_||O׷YrB-u;8dž ΅7ڍJޜnP9H6{c.|c'!"=rKLY=A^\_?PK䜽U$PK}I content.xml}ے6~OC浊D["dIGݲeEU2ꋟ?l&BduD.H 3e8v(4t"O>_'=<ߡn䬗4LGNozdI"$K\Ea$}к;k\һmgl[Kf!nLnvƶrw/j. F^X_Ho.ïOi8?=5΢x~Ms5[〵rsPkgyvISv~ضvGCu-GKsf7,($&j57hbjɭ$}q}e9o}O :H}gged"?^W$vONb>M/bLj$I{ٰQ |px$HJeݫ#%'0 M_fvK$} 2Nir j8f>ިn)Y"L Jgd@T2G*izt@T2C*iL'6 *YOJr5w6{blO3 mCwD?gM6O'ԩ_f0~?'zemC?MU;$}85U@p8MݥqJ_6&#l;p.eװtvmC ٦媓z/Zf8~0miQ5(O3+vm~_OΉpcyI @4gzr^:IrO΋I͓ɜN_#ZsK鞜fDՇB'K:Cgdy:ȓV!M&Stt36 ݓrO9R{VMM͙M$,5^˻zd޽Rj]~H36 ͩ6Ct9fa4h z4c^&}LlݱAHP{x[mGj,8k#AYH-"PKQtN(_bT#_O%'9S]KQhsn3d9jmj,hsԳma?mNtճeYhsFt˒S4%cGFYOEtØ̤T9Mcg&'ͩNT,%'͉QK6W tjS3wh/‰(9!D62OtS%xOLS | |2(;aH|7CqxPF.>iM ya;R8abQuZppqd S۠uֳTrCL2!46к}a:m-]3ISeL ePVOׇwb6^4c'@מ3A6HS2#%k#/ͳ7]m$f?(K` M M&vI[%7 2_ìEcJ'WA<Ā޸%~8J̰ gyR})>階߻tMQ"{#f ۟ub5YMJ|͏;?I(7sj7>.I'__/o~&`ٻKZ$%qzX'̮[fm$0O1仲1gǼ+mj9nCMIF_Ǒo*ls?'=$5dV>bf8&[zKP؏|0->2Lӥc.cˋqe]#.c˱pePsF7]Ɩe*z2 {BLe}J-c:;]oYC3,}{1ۯj5ԑW޿C7]#1^C: w/7:Dcߡ@qWl]oxշ/tNxnJKKT5/4.oKgL_DZ@M[&s]o{0>p$ppS[`;ۖ#:옪Y| ^ۭ+> ^N6/I?r^gOAɝ#n;(=(vc!o5!X5ӈw`#;ԕuh5!v+gRoH99ՉT$ iԒCl_飏X$%_"4!>:L'O-IV ;^v[ٌ쿜0WĜXR:dٯ gI]+jצt2?{$Q%u{=+PܾN’f~001ծ#M&01fCe!bN)u0pۣP于g C3aH6 CIj94z@yG'Pz\14sU20Z+F)e:NmnLRw CjS}h:NYcӘ MRUaa:6=Yc:66!e CԩAakݮn.Z.sSgwWgfvC1ujV:ѵV79d:a :uq)KڑTz'HG{w/ҡuT雯b=Zz)5W`~Rj֢;ԬQ9d-lFJH&Υ @5ac[ҘzQdjdA੗2OjCSߴNq Ȁ쫁 Ⱦ"V(oљ,-o⾈ˀ웸o9+зfҩ%u7R[x& ʀ{mǖ!uWo쬐WXcJ]YRg4˙:娾g4N4Ud3 1Mא2,Z([dM-GJ:vr+}&7U-Bh2'ʾgbfTJ-CM3]0ַf:^Гٷfc"DcgH^}KhbJ{N*nih2`֤SMc&Xr fU,>O, vӳ%.4Mi 3L.Cw D~ n;~KJf'%' %ZagY]Rj K|YxMyv.֑CX_*5U-Yj.G#2rg)G-h2"VF,LHeE\&K-hEXiJ5\3Ֆq4b D[Yk2r IjG#Z4x*}s܀W`(a؝/nQyhYLIi3Ik]ɮHr?)K1 gANҘ  &}y[;Lm_pax9wi9Тfsx0l~xitk$o3CC+wdZ`f9:(+Z/@L4s -gmL؏ lG!TRe|XԃNir?]eR˟[cgrR}e\N D j,'DIeD2a6}48o܇6PRMSkajX;ϐ/_i.KkSu˂([%9V7}^ZRG][č%8Mx1 Dء [S& (dp2"6Ng %C }*oSP!AA]+`W`o)||72N0g5 ٘*K+<:Tam3|E؀+G|陠搜F)jM 3s!ALg lLmtylo&R#l]*8?lhӳQ'MUqCKGq<8VV"{߰e;L+ɋSEv8ZyzDsXzyoKh\ H4v.Ңi/ޞ݃Y8bPBwB}]j^i>ezr~Vo@銔kPcDcwni09S0c߃yFLqc5u92*HRv[8; .P;7w?ޤXaBwjql 6ƪjR6^n 0UWo? 9xL| 'DL848%K g!%P<ث6TDyrR(נ 椇 v>rʈ؎ *7K8o(*fkPĬ ?ft…j;@[X%@Q%NsC~c?%k7R*iC>oFXi 2WOoqs)t:]7f[Q9F3d*!(A-qD#n\NS FE郒"L~3Ш?fQfړܵu8;&Z s{@ |&H|dB FX<`>7r6;اdp H)o`2' %]GLr7??>Cr߰fD޸ϹvZU8ݡߊ Yp*|S"2[ Mo,o͘.oނ <ۧB"řšЪ:Uh`Kij>OloٱL1xq59:?QǸk(svVYH B7Q>naab q> f`! lǖ :,i(?Amr ˎ:te9Jbh[.I,"1LU2M=ہ:7ȼdqG;H2(okkeVHE="Tҙ)ݢ2A TJPɄ2/gc|u%#v z>jc@}klS2(Ko0Q-|vmd*4TE$wR}(&*bl͋hdSM{jc%[˯ƏĝE%m#lE#'rQTO@p›. `: PK@FF(\|MwUgAYqt´~ g*@=: qtF ʶu,AF+qkxU pjI d/h|gNc bjCͪ7Pfp:x%) goꭃpРܞjÞVt#(t/a5oF$v:,ꩂj\e Ѻg=6q#M ;:+zZfA!6 |>c@&x<$f~r|i}7G9qt6v`Vã?[l ^g&m$ɦ h!PvH"+c(3,ݦ,1Lc$eY<70l"a-h l3'#6>n=H ! pog2D"Z.+rIJG"Z2z{A$* JF4 l%6tl! # 0fgXl<ϔ+GS,'8Ғ/An(Aj)Cv7pN2y^-egQUYp iLPˁb c Y]"^~{ t0؀RܣxrbL =wSՆd%?Iȣ+h2M9Y|q[\qt+\*,YAINb_"s?{E=bRd6):r]Di,E7ghܒíyFDjmkt gx))َ~qaJ <1j˄X n5N^íضNhji!rpJv9c;0Hakm'IIqk|B gvYJBfds`6~ wV"JeeP@ 𶿢һݩRwƨ[A:!R.)&,!k~[<4vk'k.ZDcf\eۇb"u8{q 9,2[(6oH# hɔlRWN{Pt6|z2Vn~rd0bܹ'Kb?kÝGvXBnn&gV sątgFT(GVD\^z5Zx"&0Sd-qwl`t4=A&ƄAJj|9;C? w&)3+wృ[Ţ1p.a3.57#H}IGBH]=ݯބj#ͦ[:ٖ3?l)9`B3+`Z\+&|"D~C'[QKFS3qD԰ 1q d٨"zɵ,W%˸.2 o_1Fuo3, dڤ+ ̮?/ QoNwɚG/tABBZ6,|SNff: ۟85#o]*y󣬼jxê4 #ENmYlҭ,.Ӝ6j@}[!K"-8^T~bL 1_-- 4UÌkl&-+T(Sܻa[x)oC`) 9QP0vBL4c}rf܎U] ?Wˇq|KIDe3. ގ$T+ NwH;r4 \,#yvj-pY5);~:=CIɺ yQVeJ ' :Jx]WSnttLV&W㷭ٮ ;pr\XΘJ&1qR`🧿hLX)[Pv%r\?M>k KN &M:~렮>TV.V6r)"X{zKtG)R\QKc!Ŵ(e:y!cx|Ĭ"P:[9n75 K Jb"4NApKs*\`\"@bFU(&Ρw b;_8g:-wUdbۺf*ѱf0Wиk@6L!JHoY*2vW}CTм!Uy$Wt)4C}Ay6Mc6/!n X oOlꢩf汨 1&Z9vUeI=*1͋I7?gViI_=/.S\몰Ki6@ f).Y\Aq[U_Mhvj(Qx9 \ rϲYLUw!;=V.A/ N풸;dCR!+Ē|9mQu2ee'd1qI'*C*q2 TzP_֬N*bv"U_d5-vfFj1$0{7ʘnq*"iFLr>s/cY bm/OԆ_bv·7}d 6WqS+nkOwhsT(bJV,| tT5 |H2Qt~_8{mV1a*>_Y!ix{DHaֵaxͰ5 d0I(TI#^f5 (GO\d;Z9 'g z(E™*b WENc|Kn.bLJlVolܨs VX;Yhnht(O5y|cR8Q o//ݭey @GY/MX3!6>Y'3'M eT/4d\,)ţ%1ABqbW(=@5^ʴw\k 9;9^KaM_Q0<ŏb O3]hʎܷ| EeM8-F.Wd !3F](|NRZ;l%rh5lVh'VcO$ɛsz@>rvB~%QbpC/3Z #go, Y46]5QE 7&}|GA#O& YC󲆒eIKRtF\(rP /晡]2 =o+ [bW93xڷ6Z]ܺٶ[}ZfO4MԯFyɽ߰r6}_0z-䊢1 i#(o8 ?v Idp s 9>$'l1vI .&yea4;p^aВ`ns +[aZC?Dz3 hXWſtltQ!C.l!|TMUQwkťb̄(7ţ7b6&{^&w ɖ ŧGqT&w~oBw#~«)D63ZPJ_6/XkCEmkzLkWYs9RPDj0]Wgxv$zjec5*)-2 KfC4,WYqcv` q슕-"8F+Н meg̊a^Z,`R l!d|~qfgHdvie,y%Y.?`Ew$5?3c^%ah[4DIWX;췘b4dWy[Đ%*\g5ox^1b&C@*` 'f.Ȣ妨W{S&N_#KKVf~`3fv 缴3_.jg4^"(.YDQ/A:Y[n,Qv^fW!Pɶ+r,E83cYl2HƜ_2ie }uR_9g4f 21 X1x2I>\' O!UٕN|H2$cTQF߉ia/N*"TT6go=G6I.񛥀pUqU6f @e(= `_Q,NQ_I O7Z e~n[LqmzϪkfxېP-rbnR_JL ?$CxƬHn};).MHs]O*3 ?0{-FʢHybeU|lJ 2ڶ֥19?I@̏5 lu!y&4Dqb4ͶKR\n)<y$Dzu>f)B_k ~ >gwbuplz4u' ؾ9Ny LY6 "GN8 G;lSz',syG(\x? -`͎ެX%K7ѡr?ؔ=29S>?ΤL[y9Y={#\g/?qB,u0ʐf˷gT9idgri)XB+AB0 (;=g'vҞfk'Zx 4oQ:KpHmũN)0f֚ţ2vAAÚ ld~ĚHK2(784` 乓ٷş Pne*Ifo*IpV( B|i"8j^c\wTL2dVH`,_$a1T뺡TΎ 6Wf+掠H]9-GrⰗkF(ȾV.3 NKy h@H^Ura[1xlm>ݞ|{?u 2 DK&oݼZV,Z|\m 9[I=#7+f V9|L}~iMLU; CGd/1 Y"Ze1< Nƀ̗Z|ӧ׿KkJH<}= ˟߾{{;7>)Oo_~~wIWKeDazDݽa 4">A >$pD,@Ǽ=AS ao!3# Ht*W>,6 &Fk s$layout-cachePK}I6!5DD5$Pictures/10000201000000AB000000AB563B5AA6C0D3A786.pngPK}I$3. b istyles.xmlPK}IAvmeta.xmlPK}I8&) Yxsettings.xmlPK}I~Configurations2/statusbar/PK}I~Configurations2/toolpanel/PK}I)Configurations2/popupmenu/PK}IaConfigurations2/images/Bitmaps/PK}IConfigurations2/menubar/PK}IConfigurations2/floater/PK}I' Configurations2/accelerator/current.xmlPK}IaConfigurations2/progressbar/PK}IConfigurations2/toolbar/PK}Ih рmanifest.rdfPK}I䜽U$META-INF/manifest.xmlPK}Ilfw;/ content.xmlPK k