pax_global_header00006660000000000000000000000064122033523150014506gustar00rootroot0000000000000052 comment=6f61ae08c2ccb52162f729defa6a2af15f468012 Tools-0.2.15/000077500000000000000000000000001220335231500126735ustar00rootroot00000000000000Tools-0.2.15/AUTHORS000066400000000000000000000002501220335231500137400ustar00rootroot00000000000000This is a fork of pyuic from PyQt4. Authors - PySide developers PyQt4 pyuic authors - Torsten Marek - Phil Thompson PyQt4 pyrcc4 authors - Trolltech - Phil Thompson Tools-0.2.15/CMakeLists.txt000066400000000000000000000055051220335231500154400ustar00rootroot00000000000000cmake_minimum_required(VERSION 2.6) project(pyside-tools) find_package(Shiboken 1.1.1 REQUIRED) find_package(Qt4 4.5.0 REQUIRED) find_package(PySide 1.0.6 REQUIRED) set(pyside_tools_MAJOR_VERSION "0") set(pyside_tools_MINOR_VERSION "2") set(pyside_tools_MICRO_VERSION "15") set(pyside_tools_VERSION "${pyside_tools_MAJOR_VERSION}.${pyside_tools_MINOR_VERSION}.${pyside_tools_MICRO_VERSION}") configure_file("pysideuic/__init__.py.in" "__init__.py" @ONLY) option(BUILD_TESTS "Build tests." TRUE) # UIC stuff if (NOT SITE_PACKAGE) execute_process( COMMAND ${SHIBOKEN_PYTHON_INTERPRETER} -c "from __future__ import print_function; \\ from distutils import sysconfig; \\ print(sysconfig.get_python_lib(1,0,prefix='${CMAKE_INSTALL_PREFIX}'))" OUTPUT_VARIABLE SITE_PACKAGE OUTPUT_STRIP_TRAILING_WHITESPACE) if (NOT SITE_PACKAGE) message(FATAL_ERROR "Could not detect Python module installation directory.") endif() endif() install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/pyside-uic DESTINATION bin PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/__init__.py" DESTINATION "${SITE_PACKAGE}/pysideuic") install(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/pysideuic DESTINATION ${SITE_PACKAGE} PATTERN "*.in" EXCLUDE PATTERN "*pysideuic/__init__.py" EXCLUDE PATTERN "*pysideuic\\__init__.py" EXCLUDE) # Man pages for pyside-uic if (NOT win32) file(GLOB manpages "${CMAKE_CURRENT_SOURCE_DIR}/pysideuic/*.1") install(FILES ${manpages} DESTINATION share/man/man1) endif() configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY) add_custom_target(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake") set(ARCHIVE_NAME ${CMAKE_PROJECT_NAME}-${pyside_tools_VERSION}) add_custom_target(dist COMMAND mkdir -p "${CMAKE_BINARY_DIR}/${ARCHIVE_NAME}" && git log > "${CMAKE_BINARY_DIR}/${ARCHIVE_NAME}/ChangeLog" && git archive --prefix=${ARCHIVE_NAME}/ HEAD --format=tar --output="${CMAKE_BINARY_DIR}/${ARCHIVE_NAME}.tar" && tar -C "${CMAKE_BINARY_DIR}" --owner=root --group=root -r "${ARCHIVE_NAME}/ChangeLog" -f "${CMAKE_BINARY_DIR}/${ARCHIVE_NAME}.tar" && bzip2 -f9 "${CMAKE_BINARY_DIR}/${ARCHIVE_NAME}.tar" && echo "Source package created at ${CMAKE_BINARY_DIR}/${ARCHIVE_NAME}.tar.bz2.\n" WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}) set(PYSIDERCC_EXECUTABLE ${CMAKE_CURRENT_BINARY_DIR}/pyrcc/pyside-rcc) add_subdirectory(pyrcc) add_subdirectory(pylupdate) if (BUILD_TESTS) enable_testing() add_subdirectory(tests) endif () Tools-0.2.15/LICENSE-rcc000066400000000000000000000432461220335231500144560ustar00rootroot00000000000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. ------------------------------------------------------------------------- Tools-0.2.15/LICENSE-uic000066400000000000000000000461521220335231500144660ustar00rootroot00000000000000Copyright (c) 2005,2006 Torsten Marek . All rights reserved. The software module is double-licensed under the revised BSD and GPL licenses. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the University nor the 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 ``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 REGENTS 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. GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. Tools-0.2.15/cmake_uninstall.cmake000066400000000000000000000016541220335231500170540ustar00rootroot00000000000000IF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") MESSAGE(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"") ENDIF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") FILE(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) STRING(REGEX REPLACE "\n" ";" files "${files}") FOREACH(file ${files}) MESSAGE(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"") IF(EXISTS "$ENV{DESTDIR}${file}") EXEC_PROGRAM( "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" OUTPUT_VARIABLE rm_out RETURN_VALUE rm_retval ) IF(NOT "${rm_retval}" STREQUAL 0) MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"") ENDIF(NOT "${rm_retval}" STREQUAL 0) ELSE(EXISTS "$ENV{DESTDIR}${file}") MESSAGE(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.") ENDIF(EXISTS "$ENV{DESTDIR}${file}") ENDFOREACH(file) Tools-0.2.15/pylupdate/000077500000000000000000000000001220335231500147025ustar00rootroot00000000000000Tools-0.2.15/pylupdate/CMakeLists.txt000066400000000000000000000017211220335231500174430ustar00rootroot00000000000000 set(lupdate_SRC fetchtr.cpp main.cpp merge.cpp metatranslator.cpp numberh.cpp proparser.cpp sametexth.cpp simtexth.cpp translator.cpp ) set(lupdate_MOC_HEADERS translator.h) qt4_wrap_cpp(lupdate_MOC_OUTFILES ${lupdate_MOC_HEADERS}) add_executable(pyside-lupdate ${lupdate_SRC} ${lupdate_MOC_OUTFILES}) include_directories(pyside-lupdate ${CMAKE_CURRENT_SOURCE_DIR} ${QT_INCLUDE_DIR} ${QT_QT_INCLUDE_DIR} ${QT_QTXML_INCLUDE_DIR} ${QT_QTCORE_INCLUDE_DIR} ${QT_QTGUI_INCLUDE_DIR}) target_link_libraries(pyside-lupdate ${QT_QTCORE_LIBRARY} ${QT_QTXML_LIBRARY} ${QT_QTGUI_LIBRARY}) install(TARGETS pyside-lupdate RUNTIME DESTINATION bin) # Man pages if (NOT win32) file(GLOB manpages "${CMAKE_CURRENT_SOURCE_DIR}/*.1") install(FILES ${manpages} DESTINATION share/man/man1) endif() Tools-0.2.15/pylupdate/fetchtr.cpp000066400000000000000000000747001220335231500170550ustar00rootroot00000000000000/* * This file is part of the PySide Tools project. * * Copyright (C) 1992-2005 Trolltech AS. All rights reserved. * Copyright (C) 2002-2007 Detlev Offenbach * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). * * Contact: PySide team * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #include #include #include #include #include #include #include #include #include #include #include #include static const char MagicComment[] = "TRANSLATOR "; static QMap needs_Q_OBJECT; static QMap lacks_Q_OBJECT; /* The first part of this source file is the Python tokenizer. We skip most of Python; the only tokens that interest us are defined here. */ enum { Tok_Eof, Tok_class, Tok_return, Tok_tr, Tok_trUtf8, Tok_translate, Tok_Ident, Tok_Comment, Tok_Dot, Tok_String, Tok_LeftParen, Tok_RightParen, Tok_Comma, Tok_None, Tok_Integer}; /* The tokenizer maintains the following global variables. The names should be self-explanatory. */ static QByteArray yyFileName; static int yyCh; static char yyIdent[128]; static size_t yyIdentLen; static char yyComment[65536]; static size_t yyCommentLen; static char yyString[65536]; static size_t yyStringLen; static qlonglong yyInteger; static QStack yySavedParenDepth; static int yyParenDepth; static int yyLineNo; static int yyCurLineNo; static int yyParenLineNo; static QTextCodec *yyCodecForTr = 0; static QTextCodec *yyCodecForSource = 0; // the file to read from (if reading from a file) static FILE *yyInFile; // the string to read from and current position in the string (otherwise) static QString yyInStr; static int yyInPos; static int buf; static int (*getChar)(); static int (*peekChar)(); static bool yyParsingUtf8; static int yyIndentationSize; static int yyContinuousSpaceCount; static bool yyCountingIndentation; // (Context, indentation level) pair. typedef QPair ContextPair; // Stack of (Context, indentation level) pairs. typedef QStack ContextStack; static ContextStack yyContextStack; static int yyContextPops; static int getCharFromFile() { int c; if ( buf < 0 ) c = getc( yyInFile ); else { c = buf; buf = -1; } if ( c == '\n' ) { yyCurLineNo++; yyCountingIndentation = true; yyContinuousSpaceCount = 0; } else if ( yyCountingIndentation && ( c == 32 || c == 9 ) ) { yyContinuousSpaceCount++; } else { if ( yyIndentationSize == 1 && yyContinuousSpaceCount > yyIndentationSize ) yyIndentationSize = yyContinuousSpaceCount; if ( yyCountingIndentation && yyContextStack.count() > 1 ) { ContextPair& top = yyContextStack.top(); if ( top.second == 0 && yyContinuousSpaceCount > 0 ) { top.second = yyContinuousSpaceCount; yyContinuousSpaceCount = 0; } else if ( yyContinuousSpaceCount < top.second ) { yyContextPops = (top.second - yyContinuousSpaceCount) / yyIndentationSize; } } yyCountingIndentation = false; } return c; } static int peekCharFromFile() { int c = getc( yyInFile ); buf = c; return c; } static void startTokenizer( const char *fileName, int (*getCharFunc)(), int (*peekCharFunc)(), QTextCodec *codecForTr, QTextCodec *codecForSource ) { yyInPos = 0; buf = -1; getChar = getCharFunc; peekChar = peekCharFunc; yyFileName = fileName; yyCh = getChar(); yySavedParenDepth.clear(); yyParenDepth = 0; yyCurLineNo = 1; yyParenLineNo = 1; yyCodecForTr = codecForTr; if (!yyCodecForTr) yyCodecForTr = QTextCodec::codecForName("ISO-8859-1"); Q_ASSERT(yyCodecForTr); yyCodecForSource = codecForSource; yyParsingUtf8 = false; yyIndentationSize = 1; yyContinuousSpaceCount = 0; yyCountingIndentation = false; yyContextStack.clear(); yyContextPops = 0; } static int getToken() { const char tab[] = "abfnrtv"; const char backTab[] = "\a\b\f\n\r\t\v"; uint n; bool quiet; yyIdentLen = 0; yyCommentLen = 0; yyStringLen = 0; while ( yyCh != EOF ) { yyLineNo = yyCurLineNo; if ( isalpha(yyCh) || yyCh == '_' ) { do { if ( yyIdentLen < sizeof(yyIdent) - 1 ) yyIdent[yyIdentLen++] = (char) yyCh; yyCh = getChar(); } while ( isalnum(yyCh) || yyCh == '_' ); yyIdent[yyIdentLen] = '\0'; switch ( yyIdent[0] ) { case 'N': if ( strcmp(yyIdent + 1, "one") == 0 ) return Tok_None; break; case 'Q': if ( strcmp(yyIdent + 1, "T_TR_NOOP") == 0 ) { yyParsingUtf8 = false; return Tok_tr; } else if ( strcmp(yyIdent + 1, "T_TRANSLATE_NOOP") == 0 ) { yyParsingUtf8 = false; return Tok_translate; } break; case 'c': if ( strcmp(yyIdent + 1, "lass") == 0 ) return Tok_class; break; case 'f': /* QTranslator::findMessage() has the same parameters as QApplication::translate(). */ if ( strcmp(yyIdent + 1, "indMessage") == 0 ) return Tok_translate; break; case 'r': if ( strcmp(yyIdent + 1, "eturn") == 0 ) return Tok_return; break; case 't': if ( strcmp(yyIdent + 1, "r") == 0 ) { yyParsingUtf8 = false; return Tok_tr; } else if ( qstrcmp(yyIdent + 1, "rUtf8") == 0 ) { yyParsingUtf8 = true; return Tok_trUtf8; } else if ( qstrcmp(yyIdent + 1, "ranslate") == 0 ) { yyParsingUtf8 = false; return Tok_translate; } break; case '_': if ( strcmp(yyIdent + 1, "_tr") == 0 ) { yyParsingUtf8 = false; return Tok_tr; } else if ( strcmp(yyIdent + 1, "_trUtf8") == 0 ) { yyParsingUtf8 = true; return Tok_trUtf8; } break; } return Tok_Ident; } else { switch ( yyCh ) { case '#': yyCh = getChar(); do { yyCh = getChar(); } while ( yyCh != EOF && yyCh != '\n' ); break; case '"': case '\'': int quoteChar; int trippelQuote, singleQuote; int in; quoteChar = yyCh; trippelQuote = 0; singleQuote = 1; in = 0; yyCh = getChar(); quiet = false; while ( yyCh != EOF ) { if ( singleQuote && (yyCh == '\n' || (in && yyCh == quoteChar)) ) break; if ( yyCh == quoteChar ) { if (peekChar() == quoteChar) { yyCh = getChar(); if (!trippelQuote) { trippelQuote = 1; singleQuote = 0; in = 1; yyCh = getChar(); } else { yyCh = getChar(); if (yyCh == quoteChar) { trippelQuote = 0; break; } } } else if (trippelQuote) { if ( yyStringLen < sizeof(yyString) - 1 ) yyString[yyStringLen++] = (char) yyCh; yyCh = getChar(); continue; } else break; } else in = 1; if ( yyCh == '\\' ) { yyCh = getChar(); if ( yyCh == 'x' ) { QByteArray hex = "0"; yyCh = getChar(); while ( isxdigit(yyCh) ) { hex += (char) yyCh; yyCh = getChar(); } #if defined(_MSC_VER) && _MSC_VER >= 1400 sscanf_s( hex, "%x", &n ); #else sscanf( hex, "%x", &n ); #endif if ( yyStringLen < sizeof(yyString) - 1 ) yyString[yyStringLen++] = (char) n; } else if ( yyCh >= '0' && yyCh < '8' ) { QByteArray oct = ""; int n = 0; do { oct += (char) yyCh; ++n; yyCh = getChar(); } while ( yyCh >= '0' && yyCh < '8' && n < 3 ); #if defined(_MSC_VER) && _MSC_VER >= 1400 sscanf_s( oct, "%o", &n ); #else sscanf( oct, "%o", &n ); #endif if ( yyStringLen < sizeof(yyString) - 1 ) yyString[yyStringLen++] = (char) n; } else { const char *p = strchr( tab, yyCh ); if ( yyStringLen < sizeof(yyString) - 1 ) yyString[yyStringLen++] = ( p == 0 ) ? (char) yyCh : backTab[p - tab]; yyCh = getChar(); } } else { if (!yyCodecForSource) { if ( yyParsingUtf8 && yyCh >= 0x80 && !quiet) { qWarning( "%s:%d: Non-ASCII character detected in trUtf8 string", (const char *) yyFileName, yyLineNo ); quiet = true; } // common case: optimized if ( yyStringLen < sizeof(yyString) - 1 ) yyString[yyStringLen++] = (char) yyCh; yyCh = getChar(); } else { QByteArray originalBytes; while ( yyCh != EOF && (trippelQuote || yyCh != '\n') && yyCh != quoteChar && yyCh != '\\' ) { if ( yyParsingUtf8 && yyCh >= 0x80 && !quiet) { qWarning( "%s:%d: Non-ASCII character detected in trUtf8 string", (const char *) yyFileName, yyLineNo ); quiet = true; } originalBytes += (char)yyCh; yyCh = getChar(); } QString unicodeStr = yyCodecForSource->toUnicode(originalBytes); QByteArray convertedBytes; if (!yyCodecForTr->canEncode(unicodeStr) && !quiet) { qWarning( "%s:%d: Cannot convert Python string from %s to %s", (const char *) yyFileName, yyLineNo, yyCodecForSource->name().constData(), yyCodecForTr->name().constData() ); quiet = true; } convertedBytes = yyCodecForTr->fromUnicode(unicodeStr); size_t len = qMin((size_t)convertedBytes.size(), sizeof(yyString) - yyStringLen - 1); memcpy(yyString + yyStringLen, convertedBytes.constData(), len); yyStringLen += len; } } } yyString[yyStringLen] = '\0'; if ( yyCh != quoteChar ) { printf("%c\n", yyCh); qWarning( "%s:%d: Unterminated string", (const char *) yyFileName, yyLineNo ); } if ( yyCh == EOF ) { return Tok_Eof; } else { yyCh = getChar(); return Tok_String; } break; case '(': if (yyParenDepth == 0) yyParenLineNo = yyCurLineNo; yyParenDepth++; yyCh = getChar(); return Tok_LeftParen; case ')': if (yyParenDepth == 0) yyParenLineNo = yyCurLineNo; yyParenDepth--; yyCh = getChar(); return Tok_RightParen; case ',': yyCh = getChar(); return Tok_Comma; case '.': yyCh = getChar(); return Tok_Dot; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { QByteArray ba; ba+=yyCh; yyCh = getChar(); bool hex = yyCh == 'x'; if ( hex ) { ba+=yyCh; yyCh = getChar(); } while ( (hex ? isxdigit(yyCh) : isdigit(yyCh)) ) { ba+=yyCh; yyCh = getChar(); } bool ok; yyInteger = ba.toLongLong(&ok); if (ok) return Tok_Integer; break; } default: yyCh = getChar(); } } } return Tok_Eof; } /* The second part of this source file is the parser. It accomplishes a very easy task: It finds all strings inside a tr() or translate() call, and possibly finds out the context of the call. It supports three cases: (1) the context is specified, as in FunnyDialog.tr("Hello") or translate("FunnyDialog", "Hello"); (2) the call appears within an inlined function; (3) the call appears within a function defined outside the class definition. */ static int yyTok; static bool match( int t ) { bool matches = ( yyTok == t ); if ( matches ) yyTok = getToken(); return matches; } static bool matchString( QByteArray *s ) { bool matches = ( yyTok == Tok_String ); *s = ""; while ( yyTok == Tok_String ) { *s += yyString; yyTok = getToken(); } return matches; } static bool matchEncoding( bool *utf8 ) { // Remove any leading module paths. if (yyTok == Tok_Ident && strcmp(yyIdent, "PySide") == 0) { yyTok = getToken(); if (yyTok != Tok_Dot) return false; yyTok = getToken(); } if (yyTok == Tok_Ident && (strcmp(yyIdent, "QtGui") == 0 || strcmp(yyIdent, "QtCore") == 0)) { yyTok = getToken(); if (yyTok != Tok_Dot) return false; yyTok = getToken(); } if ( yyTok == Tok_Ident ) { if (strcmp(yyIdent, "QApplication") == 0 || strcmp(yyIdent, "QCoreApplication") == 0) { yyTok = getToken(); if (yyTok == Tok_Dot) yyTok = getToken(); } *utf8 = QString( yyIdent ).endsWith( QString("UTF8") ); yyTok = getToken(); return true; } else { return false; } } static bool matchStringOrNone(QByteArray *s) { bool matches = matchString(s); if (!matches) matches = match(Tok_None); return matches; } /* * match any expression that can return a number, which can be * 1. Literal number (e.g. '11') * 2. simple identifier (e.g. 'm_count') * 3. simple function call (e.g. 'size()' ) * 4. function call on an object (e.g. 'list.size()') * * Other cases: * size(2,4) * list().size() * list(a,b).size(2,4) * etc... */ static bool matchExpression() { if (match(Tok_Integer)) { return true; } int parenlevel = 0; while (match(Tok_Ident) || parenlevel > 0) { if (yyTok == Tok_RightParen) { if (parenlevel == 0) break; --parenlevel; yyTok = getToken(); } else if (yyTok == Tok_LeftParen) { yyTok = getToken(); if (yyTok == Tok_RightParen) { yyTok = getToken(); } else { ++parenlevel; } } else if (yyTok == Tok_Ident) { continue; } else if (parenlevel == 0) { return false; } } return true; } static void parse( MetaTranslator *tor, const char *initialContext, const char *defaultContext ) { QByteArray context; QByteArray text; QByteArray com; QByteArray prefix; bool utf8 = false; yyContextStack.push(ContextPair(initialContext, 0)); yyTok = getToken(); while ( yyTok != Tok_Eof ) { if (yyContextPops > 0) { for ( int i = 0; i < yyContextPops; i++) yyContextStack.pop(); yyContextPops = 0; } switch ( yyTok ) { case Tok_class: yyTok = getToken(); yyContextStack.push(ContextPair(yyIdent, 0)); yyContinuousSpaceCount = 0; yyTok = getToken(); break; case Tok_tr: case Tok_trUtf8: utf8 = (yyTok == Tok_trUtf8 || (yyCodecForTr && strcmp(yyCodecForTr->name(), "UTF-8") == 0)); yyTok = getToken(); if (match(Tok_LeftParen) && matchString(&text)) { com = ""; bool plural = false; if (match(Tok_RightParen)) { // There is no comment or plural arguments. } else if (match(Tok_Comma) && matchStringOrNone(&com)) { // There is a comment argument. if (match(Tok_RightParen)) { // There is no plural argument. } else if (match(Tok_Comma)) { // There is a plural argument. plural = true; } } if (prefix.isNull()) context = defaultContext; else if (qstrcmp(prefix, "self") == 0) context = yyContextStack.top().first; else context = prefix; prefix = (const char *) 0; if (!text.isEmpty()) { tor->insert(MetaTranslatorMessage(context, text, com, yyFileName, yyLineNo, QStringList(), utf8, MetaTranslatorMessage::Unfinished, plural)); } } break; case Tok_translate: utf8 = false; yyTok = getToken(); if ( match(Tok_LeftParen) && matchString(&context) && match(Tok_Comma) && matchString(&text) ) { com = ""; bool plural = false; if (!match(Tok_RightParen)) { // look for comment if ( match(Tok_Comma) && matchStringOrNone(&com)) { if (!match(Tok_RightParen)) { // look for encoding if (match(Tok_Comma)) { if (matchEncoding(&utf8)) { if (!match(Tok_RightParen)) { // look for the plural quantifier, // this can be a number, an identifier or a function call, // so for simplicity we mark it as plural if we know we have a comma instead of an // right parentheses. plural = match(Tok_Comma); } } else { // This can be a QTranslator::translate("context", "source", "comment", n) plural translation if (matchExpression() && match(Tok_RightParen)) { plural = true; } else { break; } } } else { break; } } } else { break; } } if (!text.isEmpty()) { tor->insert( MetaTranslatorMessage(context, text, com, yyFileName, yyLineNo, QStringList(), utf8, MetaTranslatorMessage::Unfinished, plural) ); } } break; case Tok_Ident: if ( !prefix.isNull() ) prefix += "."; prefix += yyIdent; yyTok = getToken(); if ( yyTok != Tok_Dot ) prefix = (const char *) 0; break; case Tok_Comment: com = yyComment; com = com.simplified(); if ( com.left(sizeof(MagicComment) - 1) == MagicComment ) { com.remove( 0, sizeof(MagicComment) - 1 ); int k = com.indexOf( ' ' ); if ( k == -1 ) { context = com; } else { context = com.left( k ); com.remove( 0, k + 1 ); tor->insert( MetaTranslatorMessage(context, "", com, yyFileName, yyLineNo, QStringList(), false) ); } } yyTok = getToken(); break; default: yyTok = getToken(); } } if ( yyParenDepth != 0 ) qWarning( "%s: Unbalanced parentheses in Python code", (const char *) yyFileName ); } void fetchtr_py( const char *fileName, MetaTranslator *tor, const char *defaultContext, bool mustExist, const QByteArray &codecForSource ) { #if defined(_MSC_VER) && _MSC_VER >= 1400 if (fopen_s(&yyInFile, fileName, "r")) { if ( mustExist ) { char buf[100]; strerror_s(buf, sizeof(buf), errno); fprintf( stderr, "pyside-lupdate error: Cannot open Python source file '%s': %s\n", fileName, buf ); } #else yyInFile = fopen( fileName, "r" ); if ( yyInFile == 0 ) { if ( mustExist ) fprintf( stderr, "pyside-lupdate error: Cannot open Python source file '%s': %s\n", fileName, strerror(errno) ); #endif return; } startTokenizer( fileName, getCharFromFile, peekCharFromFile, tor->codecForTr(), QTextCodec::codecForName(codecForSource) ); parse( tor, 0, defaultContext ); fclose( yyInFile ); } class UiHandler : public QXmlDefaultHandler { public: UiHandler( MetaTranslator *translator, const char *fileName ) : tor( translator ), fname( fileName ), comment( "" ) { } virtual bool startElement( const QString& namespaceURI, const QString& localName, const QString& qName, const QXmlAttributes& atts ); virtual bool endElement( const QString& namespaceURI, const QString& localName, const QString& qName ); virtual bool characters( const QString& ch ); virtual bool fatalError( const QXmlParseException& exception ); virtual void setDocumentLocator(QXmlLocator *locator) { m_locator = locator; } QXmlLocator *m_locator; private: void flush(); MetaTranslator *tor; QByteArray fname; QString context; QString source; QString comment; QString accum; int m_lineNumber; bool trString; }; bool UiHandler::startElement( const QString& /* namespaceURI */, const QString& /* localName */, const QString& qName, const QXmlAttributes& atts ) { if ( qName == QString("item") ) { flush(); if ( !atts.value(QString("text")).isEmpty() ) source = atts.value( QString("text") ); } else if ( qName == QString("string") ) { flush(); if (atts.value(QString("notr")).isEmpty() || atts.value(QString("notr")) != QString("true")) { trString = true; comment = atts.value(QString("comment")); } else { trString = false; } } if (trString) m_lineNumber = m_locator->lineNumber(); accum.truncate( 0 ); return true; } bool UiHandler::endElement( const QString& /* namespaceURI */, const QString& /* localName */, const QString& qName ) { accum.replace( QRegExp(QString("\r\n")), "\n" ); if ( qName == QString("class") ) { if ( context.isEmpty() ) context = accum; } else if ( qName == QString("string") && trString ) { source = accum; } else if ( qName == QString("comment") ) { comment = accum; flush(); } else { flush(); } return true; } bool UiHandler::characters( const QString& ch ) { accum += ch; return true; } bool UiHandler::fatalError( const QXmlParseException& exception ) { QString msg; msg.sprintf( "Parse error at line %d, column %d (%s).", exception.lineNumber(), exception.columnNumber(), exception.message().toLatin1().data() ); fprintf( stderr, "XML error: %s\n", msg.toLatin1().data() ); return false; } void UiHandler::flush() { if ( !context.isEmpty() && !source.isEmpty() ) tor->insert( MetaTranslatorMessage(context.toUtf8(), source.toUtf8(), comment.toUtf8(), QString(fname), m_lineNumber, QStringList(), true) ); source.truncate( 0 ); comment.truncate( 0 ); } void fetchtr_ui( const char *fileName, MetaTranslator *tor, const char * /* defaultContext */, bool mustExist ) { QFile f( fileName ); if ( !f.open(QIODevice::ReadOnly) ) { if ( mustExist ) { #if defined(_MSC_VER) && _MSC_VER >= 1400 char buf[100]; strerror_s(buf, sizeof(buf), errno); fprintf( stderr, "pyside-lupdate error: cannot open UI file '%s': %s\n", fileName, buf ); #else fprintf( stderr, "pyside-lupdate error: cannot open UI file '%s': %s\n", fileName, strerror(errno) ); #endif } return; } QXmlInputSource in( &f ); QXmlSimpleReader reader; reader.setFeature( "http://xml.org/sax/features/namespaces", false ); reader.setFeature( "http://xml.org/sax/features/namespace-prefixes", true ); reader.setFeature( "http://trolltech.com/xml/features/report-whitespace" "-only-CharData", false ); QXmlDefaultHandler *hand = new UiHandler( tor, fileName ); reader.setContentHandler( hand ); reader.setErrorHandler( hand ); if ( !reader.parse(in) ) fprintf( stderr, "%s: Parse error in UI file\n", fileName ); reader.setContentHandler( 0 ); reader.setErrorHandler( 0 ); delete hand; f.close(); } Tools-0.2.15/pylupdate/main.cpp000066400000000000000000000215441220335231500163400ustar00rootroot00000000000000/* * This file is part of the PySide Tools project. * * Copyright (C) 1992-2005 Trolltech AS. All rights reserved. * Copyright (C) 2002-2007 Detlev Offenbach * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). * * Contact: PySide team * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #include #include #include #include #include #include #include #include #include #include #include // defined in fetchtr.cpp extern void fetchtr_py( const char *fileName, MetaTranslator *tor, const char *defaultContext, bool mustExist, const QByteArray &codecForSource ); extern void fetchtr_ui( const char *fileName, MetaTranslator *tor, const char *defaultContext, bool mustExist ); // defined in merge.cpp extern void merge( const MetaTranslator *tor, const MetaTranslator *virginTor, MetaTranslator *out, bool verbose, bool noObsolete ); typedef QList TML; static void printUsage() { fprintf( stderr, "Usage:\n" " pyside-lupdate [options] project-file\n" " pyside-lupdate [options] source-files -ts ts-files\n" "Options:\n" " -help Display this information and exit\n" " -noobsolete\n" " Drop all obsolete strings\n" " -verbose\n" " Explain what is being done\n" " -version\n" " Display the version of pyside-lupdate and exit\n" ); } static void updateTsFiles( const MetaTranslator& fetchedTor, const QStringList& tsFileNames, const QString& codecForTr, bool noObsolete, bool verbose ) { QStringList::ConstIterator t = tsFileNames.begin(); QDir dir; while ( t != tsFileNames.end() ) { QString fn = dir.relativeFilePath(*t); MetaTranslator tor; MetaTranslator out; tor.load( *t ); if ( !codecForTr.isEmpty() ) tor.setCodec( codecForTr.toLatin1() ); if ( verbose ) fprintf( stderr, "Updating '%s'...\n", fn.toLatin1().constData() ); merge( &tor, &fetchedTor, &out, verbose, noObsolete ); if ( noObsolete ) out.stripObsoleteMessages(); out.stripEmptyContexts(); if ( !out.save(*t) ) { #if defined(_MSC_VER) && _MSC_VER >= 1400 char buf[100]; strerror_s(buf, sizeof(buf), errno); fprintf( stderr, "pyside-lupdate error: Cannot save '%s': %s\n", fn.toLatin1().constData(), buf ); #else fprintf( stderr, "pyside-lupdate error: Cannot save '%s': %s\n", fn.toLatin1().constData(), strerror(errno) ); #endif } ++t; } } int main( int argc, char **argv ) { QString defaultContext = "@default"; MetaTranslator fetchedTor; QByteArray codecForTr; QByteArray codecForSource; QStringList tsFileNames; QStringList uiFileNames; bool verbose = false; bool noObsolete = false; bool metSomething = false; int numFiles = 0; bool standardSyntax = true; bool metTsFlag = false; int i; for ( i = 1; i < argc; i++ ) { if ( qstrcmp(argv[i], "-ts") == 0 ) standardSyntax = false; } for ( i = 1; i < argc; i++ ) { if ( qstrcmp(argv[i], "-help") == 0 ) { printUsage(); return 0; } else if ( qstrcmp(argv[i], "-noobsolete") == 0 ) { noObsolete = true; continue; } else if ( qstrcmp(argv[i], "-verbose") == 0 ) { verbose = true; continue; } else if ( qstrcmp(argv[i], "-version") == 0 ) { fprintf( stderr, "pyside-lupdate version %s\n", QT_VERSION_STR ); return 0; } else if ( qstrcmp(argv[i], "-ts") == 0 ) { metTsFlag = true; continue; } numFiles++; QString fullText; if ( !metTsFlag ) { QFile f( argv[i] ); if ( !f.open(QIODevice::ReadOnly) ) { #if defined(_MSC_VER) && _MSC_VER >= 1400 char buf[100]; strerror_s(buf, sizeof(buf), errno); fprintf( stderr, "pyside-lupdate error: Cannot open file '%s': %s\n", argv[i], buf ); #else fprintf( stderr, "pyside-lupdate error: Cannot open file '%s': %s\n", argv[i], strerror(errno) ); #endif return 1; } QTextStream t( &f ); fullText = t.readAll(); f.close(); } QString oldDir = QDir::currentPath(); QDir::setCurrent( QFileInfo(argv[i]).path() ); if ( standardSyntax ) { fetchedTor = MetaTranslator(); codecForTr.clear(); codecForSource.clear(); tsFileNames.clear(); uiFileNames.clear(); QMap tagMap = proFileTagMap( fullText ); QMap::Iterator it; for ( it = tagMap.begin(); it != tagMap.end(); ++it ) { QStringList toks = it.value().split(' '); QStringList::Iterator t; for ( t = toks.begin(); t != toks.end(); ++t ) { if ( it.key() == "SOURCES" ) { fetchtr_py( (*t).toAscii(), &fetchedTor, defaultContext.toAscii(), true, codecForSource ); metSomething = true; } else if ( it.key() == "TRANSLATIONS" ) { tsFileNames.append( *t ); metSomething = true; } else if ( it.key() == "CODEC" || it.key() == "DEFAULTCODEC" || it.key() == "CODECFORTR" ) { codecForTr = (*t).toLatin1(); fetchedTor.setCodecForTr(codecForTr); } else if ( it.key() == "CODECFORSRC" ) { codecForSource = (*t).toLatin1(); } else if ( it.key() == "FORMS" ) { fetchtr_ui( (*t).toAscii(), &fetchedTor, defaultContext.toAscii(), true); } } } updateTsFiles( fetchedTor, tsFileNames, codecForTr, noObsolete, verbose ); if ( !metSomething ) { fprintf( stderr, "pyside-lupdate warning: File '%s' does not look like a" " project file\n", argv[i] ); } else if ( tsFileNames.isEmpty() ) { fprintf( stderr, "pyside-lupdate warning: Met no 'TRANSLATIONS' entry in" " project file '%s'\n", argv[i] ); } } else { if ( metTsFlag ) { if ( QString(argv[i]).toLower().endsWith(".ts") ) { QFileInfo fi( argv[i] ); if ( !fi.exists() || fi.isWritable() ) { tsFileNames.append( argv[i] ); } else { fprintf( stderr, "pyside-lupdate warning: For some reason, I cannot" " save '%s'\n", argv[i] ); } } else { fprintf( stderr, "pyside-lupdate error: File '%s' lacks .ts extension\n", argv[i] ); } } else { QFileInfo fi(argv[i]); if ( fi.suffix() == "py" || fi.suffix() == "pyw" ) { fetchtr_py( fi.fileName().toAscii(), &fetchedTor, defaultContext.toAscii(), true, codecForSource ); } else { fetchtr_ui( fi.fileName().toAscii(), &fetchedTor, defaultContext.toAscii(), true); } } } QDir::setCurrent( oldDir ); } if ( !standardSyntax ) updateTsFiles( fetchedTor, tsFileNames, codecForTr, noObsolete, verbose ); if ( numFiles == 0 ) { printUsage(); return 1; } return 0; } Tools-0.2.15/pylupdate/merge.cpp000066400000000000000000000202111220335231500165010ustar00rootroot00000000000000/* * This file is part of the PySide Tools project. * * Copyright (C) 1992-2006 Trolltech AS. All rights reserved. * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). * * Contact: PySide team * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #include "metatranslator.h" #include "simtexth.h" #include // defined in numberh.cpp extern int applyNumberHeuristic( MetaTranslator *tor ); // defined in sametexth.cpp extern int applySameTextHeuristic( MetaTranslator *tor ); typedef QList TML; /* Merges two MetaTranslator objects into the first one. The first one is a set of source texts and translations for a previous version of the internationalized program; the second one is a set of fresh source texts newly extracted from the source code, without any translation yet. */ void merge( const MetaTranslator *tor, const MetaTranslator *virginTor, MetaTranslator *outTor, bool verbose, bool noObsolete ) { int known = 0; int neww = 0; int obsoleted = 0; int UntranslatedObsoleted = 0; int similarTextHeuristicCount = 0; TML all = tor->messages(); TML::Iterator it; outTor->setLanguageCode(tor->languageCode()); /* The types of all the messages from the vernacular translator are updated according to the virgin translator. */ for ( it = all.begin(); it != all.end(); ++it ) { MetaTranslatorMessage::Type newType = MetaTranslatorMessage::Finished; MetaTranslatorMessage m = *it; // skip context comment if ( !QByteArray(m.sourceText()).isEmpty() ) { MetaTranslatorMessage mv = virginTor->find(m.context(), m.sourceText(), m.comment()); if ( mv.isNull() ) { mv = virginTor->find(m.context(), m.comment(), m.fileName(), m.lineNumber()); if ( mv.isNull() ) { // did not find it in the virgin, mark it as obsolete newType = MetaTranslatorMessage::Obsolete; if ( m.type() != MetaTranslatorMessage::Obsolete ) obsoleted++; } else { // Do not just accept it if its on the same line number, but different source text. // Also check if the texts are more or less similar before we consider them to represent the same message... // ### The QString() cast is evil if (getSimilarityScore(QString(m.sourceText()), mv.sourceText()) >= textSimilarityThreshold) { // It is just slightly modified, assume that it is the same string m = MetaTranslatorMessage(m.context(), mv.sourceText(), m.comment(), m.fileName(), m.lineNumber(), m.translations()); m.setPlural(mv.isPlural()); // Mark it as unfinished. (Since the source text was changed it might require re-translating...) newType = MetaTranslatorMessage::Unfinished; ++similarTextHeuristicCount; } else { // The virgin and vernacular sourceTexts are so different that we could not find it. newType = MetaTranslatorMessage::Obsolete; if ( m.type() != MetaTranslatorMessage::Obsolete ) obsoleted++; } neww++; } } else { switch ( m.type() ) { case MetaTranslatorMessage::Finished: default: if (m.isPlural() == mv.isPlural()) { newType = MetaTranslatorMessage::Finished; } else { newType = MetaTranslatorMessage::Unfinished; } known++; break; case MetaTranslatorMessage::Unfinished: newType = MetaTranslatorMessage::Unfinished; known++; break; case MetaTranslatorMessage::Obsolete: newType = MetaTranslatorMessage::Unfinished; neww++; } // Always get the filename and linenumber info from the virgin Translator, in case it has changed location. // This should also enable us to read a file that does not have the element. m.setFileName(mv.fileName()); m.setLineNumber(mv.lineNumber()); m.setPlural(mv.isPlural()); // ### why not use operator=? } if (newType == MetaTranslatorMessage::Obsolete && !m.isTranslated()) { ++UntranslatedObsoleted; } m.setType(newType); outTor->insert(m); } } /* Messages found only in the virgin translator are added to the vernacular translator. Among these are all the context comments. */ all = virginTor->messages(); for ( it = all.begin(); it != all.end(); ++it ) { MetaTranslatorMessage mv = *it; bool found = tor->contains(mv.context(), mv.sourceText(), mv.comment()); if (!found) { MetaTranslatorMessage m = tor->find(mv.context(), mv.comment(), mv.fileName(), mv.lineNumber()); if (!m.isNull()) { if (getSimilarityScore(QString(m.sourceText()), mv.sourceText()) >= textSimilarityThreshold) { found = true; } } else { found = false; } } if ( !found ) { outTor->insert( mv ); if ( !QByteArray(mv.sourceText()).isEmpty() ) neww++; } } /* The same-text heuristic handles cases where a message has an obsolete counterpart with a different context or comment. */ int sameTextHeuristicCount = applySameTextHeuristic( outTor ); /* The number heuristic handles cases where a message has an obsolete counterpart with mostly numbers differing in the source text. */ int sameNumberHeuristicCount = applyNumberHeuristic( outTor ); if ( verbose ) { int totalFound = neww + known; fprintf( stderr, " Found %d source text%s (%d new and %d already existing)\n", totalFound, totalFound == 1 ? "" : "s", neww, known); if (obsoleted) { if (noObsolete) { fprintf( stderr, " Removed %d obsolete entr%s\n", obsoleted, obsoleted == 1 ? "y" : "ies" ); } else { int total = obsoleted - UntranslatedObsoleted; fprintf( stderr, " Kept %d obsolete translation%s\n", total, total == 1 ? "" : "s" ); fprintf( stderr, " Removed %d obsolete untranslated entr%s\n", UntranslatedObsoleted, UntranslatedObsoleted == 1 ? "y" : "ies" ); } } if (sameNumberHeuristicCount) fprintf( stderr, " Number heuristic provided %d translation%s\n", sameNumberHeuristicCount, sameNumberHeuristicCount == 1 ? "" : "s" ); if (sameTextHeuristicCount) fprintf( stderr, " Same-text heuristic provided %d translation%s\n", sameTextHeuristicCount, sameTextHeuristicCount == 1 ? "" : "s" ); if (similarTextHeuristicCount) fprintf( stderr, " Similar-text heuristic provided %d translation%s\n", similarTextHeuristicCount, similarTextHeuristicCount == 1 ? "" : "s" ); } } Tools-0.2.15/pylupdate/metatranslator.cpp000066400000000000000000000621511220335231500204530ustar00rootroot00000000000000/* * This file is part of the PySide Tools project. * * Copyright (C) 1992-2005 Trolltech AS. All rights reserved. * Copyright (C) 2002-2007 Detlev Offenbach * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). * * Contact: PySide team * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #include "metatranslator.h" #include #include #include #include #include #include #include #include static bool encodingIsUtf8( const QXmlAttributes& atts ) { for ( int i = 0; i < atts.length(); i++ ) { // utf8="true" is a pre-3.0 syntax if ( atts.qName(i) == QString("utf8") ) { return ( atts.value(i) == QString("true") ); } else if ( atts.qName(i) == QString("encoding") ) { return ( atts.value(i) == QString("UTF-8") ); } } return false; } class TsHandler : public QXmlDefaultHandler { public: TsHandler( MetaTranslator *translator ) : tor( translator ), type( MetaTranslatorMessage::Finished ), inMessage( false ), ferrorCount( 0 ), contextIsUtf8( false ), messageIsUtf8( false ), m_isPlural(false) { } virtual bool startElement( const QString& namespaceURI, const QString& localName, const QString& qName, const QXmlAttributes& atts ); virtual bool endElement( const QString& namespaceURI, const QString& localName, const QString& qName ); virtual bool characters( const QString& ch ); virtual bool fatalError( const QXmlParseException& exception ); QString language() const { return m_language; } private: MetaTranslator *tor; MetaTranslatorMessage::Type type; bool inMessage; QString m_language; QString context; QString source; QString comment; QStringList translations; QString m_fileName; int m_lineNumber; QString accum; int ferrorCount; bool contextIsUtf8; bool messageIsUtf8; bool m_isPlural; }; bool TsHandler::startElement( const QString& /* namespaceURI */, const QString& /* localName */, const QString& qName, const QXmlAttributes& atts ) { if ( qName == QString("byte") ) { for ( int i = 0; i < atts.length(); i++ ) { if ( atts.qName(i) == QString("value") ) { QString value = atts.value( i ); int base = 10; if ( value.startsWith("x") ) { base = 16; value = value.mid( 1 ); } int n = value.toUInt( 0, base ); if ( n != 0 ) accum += QChar( n ); } } } else { if ( qName == QString("TS") ) { m_language = atts.value(QLatin1String("language")); } else if ( qName == QString("context") ) { context.truncate( 0 ); source.truncate( 0 ); comment.truncate( 0 ); translations.clear(); contextIsUtf8 = encodingIsUtf8( atts ); } else if ( qName == QString("message") ) { inMessage = true; type = MetaTranslatorMessage::Finished; source.truncate( 0 ); comment.truncate( 0 ); translations.clear(); messageIsUtf8 = encodingIsUtf8( atts ); m_isPlural = atts.value(QLatin1String("numerus")).compare(QLatin1String("yes")) == 0; } else if (qName == QString("location") && inMessage) { bool bOK; int lineNo = atts.value(QString("line")).toInt(&bOK); if (!bOK) lineNo = -1; m_fileName = atts.value(QString("filename")); m_lineNumber = lineNo; } else if ( qName == QString("translation") ) { for ( int i = 0; i < atts.length(); i++ ) { if ( atts.qName(i) == QString("type") ) { if ( atts.value(i) == QString("unfinished") ) type = MetaTranslatorMessage::Unfinished; else if ( atts.value(i) == QString("obsolete") ) type = MetaTranslatorMessage::Obsolete; else type = MetaTranslatorMessage::Finished; } } } accum.truncate( 0 ); } return true; } bool TsHandler::endElement( const QString& /* namespaceURI */, const QString& /* localName */, const QString& qName ) { if ( qName == QString("codec") || qName == QString("defaultcodec") ) { // "codec" is a pre-3.0 syntax tor->setCodec( accum.toLatin1() ); } else if ( qName == QString("name") ) { context = accum; } else if ( qName == QString("source") ) { source = accum; } else if ( qName == QString("comment") ) { if ( inMessage ) { comment = accum; } else { if ( contextIsUtf8 ) tor->insert( MetaTranslatorMessage(context.toUtf8(), ContextComment, accum.toUtf8(), QString(), 0, QStringList(), true, MetaTranslatorMessage::Unfinished) ); else tor->insert( MetaTranslatorMessage(context.toAscii(), ContextComment, accum.toAscii(), QString(), 0, QStringList(), false, MetaTranslatorMessage::Unfinished) ); } } else if ( qName == QString("numerusform") ) { translations.append(accum); m_isPlural = true; } else if ( qName == QString("translation") ) { if (translations.isEmpty()) translations.append(accum); } else if ( qName == QString("message") ) { if ( messageIsUtf8 ) tor->insert( MetaTranslatorMessage(context.toUtf8(), source.toUtf8(), comment.toUtf8(), m_fileName, m_lineNumber, translations, true, type, m_isPlural) ); else tor->insert( MetaTranslatorMessage(context.toAscii(), source.toAscii(), comment.toAscii(), m_fileName, m_lineNumber, translations, false, type, m_isPlural) ); inMessage = false; } return true; } bool TsHandler::characters( const QString& ch ) { QString t = ch; t.replace( "\r", "" ); accum += t; return true; } bool TsHandler::fatalError( const QXmlParseException& exception ) { if ( ferrorCount++ == 0 ) { QString msg; msg.sprintf( "Parse error at line %d, column %d (%s).", exception.lineNumber(), exception.columnNumber(), exception.message().toLatin1().data() ); if ( qApp == 0 ) fprintf( stderr, "XML error: %s\n", msg.toLatin1().data() ); else QMessageBox::information(0, QObject::tr("Qt Linguist"), msg ); } return false; } static QString numericEntity( int ch ) { return QString( ch <= 0x20 ? "" : "&#x%1;" ) .arg( ch, 0, 16 ); } static QString protect( const QByteArray& str ) { QString result; int len = (int) str.length(); for ( int k = 0; k < len; k++ ) { switch( str[k] ) { case '\"': result += QString( """ ); break; case '&': result += QString( "&" ); break; case '>': result += QString( ">" ); break; case '<': result += QString( "<" ); break; case '\'': result += QString( "'" ); break; default: if ( (uchar) str[k] < 0x20 && str[k] != '\n' ) result += numericEntity( (uchar) str[k] ); else result += str[k]; } } return result; } static QString evilBytes( const QByteArray& str, bool utf8 ) { if ( utf8 ) { return protect( str ); } else { QString result; QByteArray t = protect( str ).toLatin1(); int len = (int) t.length(); for ( int k = 0; k < len; k++ ) { if ( (uchar) t[k] >= 0x7f ) result += numericEntity( (uchar) t[k] ); else result += QChar( t[k] ); } return result; } } MetaTranslatorMessage::MetaTranslatorMessage() : utfeight( false ), ty( Unfinished ), m_plural(false) { } MetaTranslatorMessage::MetaTranslatorMessage( const char *context, const char *sourceText, const char *comment, const QString &fileName, int lineNumber, const QStringList& translations, bool utf8, Type type, bool plural ) : TranslatorMessage( context, sourceText, comment, fileName, lineNumber, translations ), utfeight( false ), ty( type ), m_plural(plural) { /* Don't use UTF-8 if it makes no difference. UTF-8 should be reserved for the real problematic case: non-ASCII (possibly non-Latin1) characters in .ui files. */ if ( utf8 ) { if ( sourceText != 0 ) { int i = 0; while ( sourceText[i] != '\0' ) { if ( (uchar) sourceText[i] >= 0x80 ) { utfeight = true; break; } i++; } } if ( !utfeight && comment != 0 ) { int i = 0; while ( comment[i] != '\0' ) { if ( (uchar) comment[i] >= 0x80 ) { utfeight = true; break; } i++; } } } } MetaTranslatorMessage::MetaTranslatorMessage( const MetaTranslatorMessage& m ) : TranslatorMessage( m ), utfeight( m.utfeight ), ty( m.ty ), m_plural(m.m_plural) { } MetaTranslatorMessage& MetaTranslatorMessage::operator=( const MetaTranslatorMessage& m ) { TranslatorMessage::operator=( m ); utfeight = m.utfeight; ty = m.ty; m_plural = m.m_plural; return *this; } bool MetaTranslatorMessage::operator==( const MetaTranslatorMessage& m ) const { return qstrcmp( context(), m.context() ) == 0 && qstrcmp( sourceText(), m.sourceText() ) == 0 && qstrcmp( comment(), m.comment() ) == 0; } bool MetaTranslatorMessage::operator<( const MetaTranslatorMessage& m ) const { int delta = qstrcmp( context(), m.context() ); if ( delta == 0 ) { delta = qstrcmp( sourceText(), m.sourceText() ); if ( delta == 0 ) delta = qstrcmp( comment(), m.comment() ); } return delta < 0; } MetaTranslator::MetaTranslator() { clear(); } MetaTranslator::MetaTranslator( const MetaTranslator& tor ) : mm( tor.mm ), codecName( tor.codecName ), codec( tor.codec ) { } MetaTranslator& MetaTranslator::operator=( const MetaTranslator& tor ) { mm = tor.mm; codecName = tor.codecName; codec = tor.codec; return *this; } void MetaTranslator::clear() { mm.clear(); codecName = "ISO-8859-1"; codec = 0; } bool MetaTranslator::load( const QString& filename ) { QFile f( filename ); if ( !f.open(QIODevice::ReadOnly) ) return false; QXmlInputSource in( &f ); QXmlSimpleReader reader; reader.setFeature( "http://xml.org/sax/features/namespaces", false ); reader.setFeature( "http://xml.org/sax/features/namespace-prefixes", true ); TsHandler *hand = new TsHandler( this ); reader.setContentHandler( static_cast(hand) ); reader.setErrorHandler( static_cast(hand) ); bool ok = reader.parse( in ); reader.setContentHandler( 0 ); reader.setErrorHandler( 0 ); m_language = hand->language(); makeFileNamesAbsolute(QFileInfo(filename).absoluteDir()); delete hand; f.close(); return ok; } bool MetaTranslator::save( const QString& filename ) const { QFile f( filename ); if ( !f.open(QIODevice::WriteOnly) ) return false; QTextStream t( &f ); t.setCodec( QTextCodec::codecForName("ISO-8859-1") ); //### The xml prolog allows processors to easily detect the correct encoding t << "\n\n"; if ( codecName != "ISO-8859-1" ) t << "" << codecName << "\n"; TMM::ConstIterator m = mm.begin(); while ( m != mm.end() ) { TMMInv inv; TMMInv::Iterator i; bool contextIsUtf8 = m.key().utf8(); QByteArray context = m.key().context(); QByteArray comment = ""; do { if (QByteArray(m.key().sourceText()) == ContextComment) { if ( m.key().type() != MetaTranslatorMessage::Obsolete ) { contextIsUtf8 = m.key().utf8(); comment = QByteArray(m.key().comment()); } } else { inv.insert( *m, m.key() ); } } while ( ++m != mm.end() && QByteArray(m.key().context()) == context ); if ( inv.isEmpty() ) continue; t << "\n"; t << " " << evilBytes( context, contextIsUtf8 ) << "\n"; if ( !comment.isEmpty() ) t << " " << evilBytes( comment, contextIsUtf8 ) << "\n"; for ( i = inv.begin(); i != inv.end(); ++i ) { MetaTranslatorMessage msg = *i; // no need for such noise if ( msg.type() == MetaTranslatorMessage::Obsolete && msg.translation().isEmpty() ) continue; t << " \n"; if (!msg.fileName().isEmpty() && msg.lineNumber() >= 0) { QDir tsPath = QFileInfo(filename).absoluteDir(); QString fn = tsPath.relativeFilePath(msg.fileName()).replace('\\','/'); t << " \n"; } t << " " << evilBytes( msg.sourceText(), msg.utf8() ) << "\n"; if ( !QByteArray(msg.comment()).isEmpty() ) t << " " << evilBytes( msg.comment(), msg.utf8() ) << "\n"; t << " "; if (msg.isPlural()) { t << "\n"; QLocale::Language l; QLocale::Country c; languageAndCountry(m_language, &l, &c); QStringList translns = normalizedTranslations(msg, l, c); for (int j = 0; j < qMax(1, translns.count()); ++j) t << " " << protect( translns.value(j).toUtf8() ) << "\n"; t << " "; } else { t << protect( msg.translation().toUtf8() ); } t << "\n"; t << " \n"; } t << "\n"; } t << "\n"; f.close(); return true; } void MetaTranslator::languageAndCountry(const QString &languageCode, QLocale::Language *lang, QLocale::Country *country) { QLocale locale(languageCode); if (lang) *lang = locale.language(); if (country) { if (languageCode.indexOf(QLatin1Char('_')) != -1) { *country = locale.country(); } else { *country = QLocale::AnyCountry; } } } bool MetaTranslator::release( const QString& filename, bool verbose, bool ignoreUnfinished, Translator::SaveMode mode ) const { Translator tor( 0 ); int finished = 0; int unfinished = 0; int untranslated = 0; TMM::ConstIterator m; for ( m = mm.begin(); m != mm.end(); ++m ) { if ( m.key().type() != MetaTranslatorMessage::Obsolete ) { if ( m.key().translation().isEmpty() ) { untranslated++; } else { if ( m.key().type() == MetaTranslatorMessage::Unfinished ) unfinished++; else finished++; QByteArray context = m.key().context(); QByteArray sourceText = m.key().sourceText(); QByteArray comment = m.key().comment(); QStringList translations = m.key().translations(); if ( !ignoreUnfinished || m.key().type() != MetaTranslatorMessage::Unfinished ) { /* Drop the comment in (context, sourceText, comment), unless the context is empty, unless (context, sourceText, "") already exists or unless we already dropped the comment of (context, sourceText, comment0). */ if ( comment.isEmpty() || context.isEmpty() || contains(context, sourceText, "") || !tor.findMessage(context, sourceText, "").translation() .isNull() ) { tor.insert( m.key() ); } else { tor.insert( TranslatorMessage(context, sourceText, "", QString(), -1, translations) ); //filename and lineNumbers will be ignored from now. } } } } } bool saved = tor.save( filename, mode ); if ( saved && verbose ) fprintf( stderr, " %d finished, %d unfinished and %d untranslated messages\n", finished, unfinished, untranslated ); return saved; } QString MetaTranslator::languageCode() const { return m_language; } void MetaTranslator::setLanguageCode(const QString &languageCode) { m_language = languageCode; } bool MetaTranslator::contains( const char *context, const char *sourceText, const char *comment ) const { return mm.contains(MetaTranslatorMessage(context, sourceText, comment, QString(), 0)); } MetaTranslatorMessage MetaTranslator::find( const char *context, const char *sourceText, const char *comment ) const { QMap::const_iterator it = mm.constFind(MetaTranslatorMessage(context, sourceText, comment, QString(), 0)); return (it == mm.constEnd() ? MetaTranslatorMessage() : it.key()); } MetaTranslatorMessage MetaTranslator::find(const char *context, const char *comment, const QString &fileName, int lineNumber) const { if (lineNumber >= 0 && !fileName.isEmpty()) { MetaTranslatorMessage m; for (QMap::const_iterator it = mm.constBegin(); it != mm.constEnd(); ++it) { m = it.key(); int delta = qstrcmp(m.context(), context); if (delta == 0) { delta = qstrcmp(m.comment(), comment); if (delta == 0) { delta = QString::compare(m.fileName(), fileName); if (delta == 0) { delta = m.lineNumber() - lineNumber; if (delta == 0) return m; } } } } } return MetaTranslatorMessage(); } void MetaTranslator::insert( const MetaTranslatorMessage& m ) { int pos = mm.count(); if (mm.contains(m)) { pos = mm.value(m); mm.remove(m); } mm.insert(m, pos); } void MetaTranslator::stripObsoleteMessages() { TMM newmm; TMM::Iterator m = mm.begin(); while ( m != mm.end() ) { if ( m.key().type() != MetaTranslatorMessage::Obsolete ) newmm.insert( m.key(), *m ); ++m; } mm = newmm; } void MetaTranslator::stripEmptyContexts() { TMM newmm; TMM::Iterator m = mm.begin(); while ( m != mm.end() ) { if ( QByteArray(m.key().sourceText()) == ContextComment ) { TMM::Iterator n = m; ++n; // the context comment is followed by other messages if ( n != newmm.end() && qstrcmp(m.key().context(), n.key().context()) == 0 ) newmm.insert( m.key(), *m ); } else { newmm.insert( m.key(), *m ); } ++m; } mm = newmm; } void MetaTranslator::makeFileNamesAbsolute(const QDir &oldPath) { TMM newmm; for (TMM::iterator m = mm.begin(); m != mm.end(); ++m) { MetaTranslatorMessage msg = m.key(); QString fileName = m.key().fileName(); QFileInfo fi (fileName); if (fi.isRelative()) { fileName = oldPath.absoluteFilePath(fileName); } msg.setFileName(fileName); newmm.insert(msg, m.value()); } mm = newmm; } void MetaTranslator::setCodec( const char *name ) { const int latin1 = 4; codecName = name; codec = QTextCodec::codecForName( name ); if ( codec == 0 || codec->mibEnum() == latin1 ) codec = 0; } QString MetaTranslator::toUnicode( const char *str, bool utf8 ) const { if ( utf8 ) return QString::fromUtf8( str ); else if ( codec == 0 ) return QString( str ); else return codec->toUnicode( str ); } QList MetaTranslator::messages() const { int n = mm.count(); TMM::ConstIterator *t = new TMM::ConstIterator[n + 1]; TMM::ConstIterator m; for ( m = mm.begin(); m != mm.end(); ++m ) t[*m] = m; QList val; for ( int i = 0; i < n; i++ ) val.append( t[i].key() ); delete[] t; return val; } QList MetaTranslator::translatedMessages() const { QList val; TMM::ConstIterator m; for ( m = mm.begin(); m != mm.end(); ++m ) { if ( m.key().type() == MetaTranslatorMessage::Finished ) val.append( m.key() ); } return val; } // the grammatical numerus is the number of plural forms + singular forms. // i.e english has two forms: singular og plural. // and polish has three forms: // 1. singular (1), // 2. plural form 1 (numbers that ends with 2,3,4 except 12,13,14) // 3. plural form 2 (all others) // Thus, english returns 2, polish returns 3 int MetaTranslator::grammaticalNumerus(QLocale::Language language, QLocale::Country country) { QStringList forms; getNumerusInfo(language, country, &forms); return forms.count(); } QStringList MetaTranslator::normalizedTranslations(const MetaTranslatorMessage& m, QLocale::Language language, QLocale::Country country) { QStringList translations = m.translations(); int numTranslations = 1; if (m.isPlural()) { numTranslations = grammaticalNumerus(language, country); } // make sure that the stringlist always have the size of the language's current numerus, or 1 if its not plural if (translations.count() > numTranslations) { for (int i = translations.count(); i > numTranslations; --i) translations.removeLast(); } else if (translations.count() < numTranslations) { for (int i = translations.count(); i < numTranslations; ++i) translations << QString(); } return translations; } Tools-0.2.15/pylupdate/metatranslator.h000066400000000000000000000126241220335231500201200ustar00rootroot00000000000000/* * This file is part of the PySide Tools project. * * Copyright (C) 1992-2005 Trolltech AS. All rights reserved. * Copyright (C) 2002-2007 Detlev Offenbach * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). * * Contact: PySide team * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #ifndef METATRANSLATOR_H #define METATRANSLATOR_H #include #include #include #include #include #include class QTextCodec; class MetaTranslatorMessage : public TranslatorMessage { public: enum Type { Unfinished, Finished, Obsolete }; MetaTranslatorMessage(); MetaTranslatorMessage( const char *context, const char *sourceText, const char *comment, const QString &fileName, int lineNumber, const QStringList& translations = QStringList(), bool utf8 = false, Type type = Unfinished, bool plural = false ); MetaTranslatorMessage( const MetaTranslatorMessage& m ); MetaTranslatorMessage& operator=( const MetaTranslatorMessage& m ); void setType( Type nt ) { ty = nt; } Type type() const { return ty; } bool utf8() const { return utfeight; } bool isPlural() const { return m_plural; } void setPlural(bool isplural) { m_plural = isplural; } bool operator==( const MetaTranslatorMessage& m ) const; bool operator!=( const MetaTranslatorMessage& m ) const { return !operator==( m ); } bool operator<( const MetaTranslatorMessage& m ) const; bool operator<=( const MetaTranslatorMessage& m ) { return !operator>( m ); } bool operator>( const MetaTranslatorMessage& m ) const { return this->operator<( m ); } bool operator>=( const MetaTranslatorMessage& m ) const { return !operator<( m ); } private: bool utfeight; Type ty; bool m_plural; }; class MetaTranslator { public: MetaTranslator(); MetaTranslator( const MetaTranslator& tor ); MetaTranslator& operator=( const MetaTranslator& tor ); void clear(); bool load( const QString& filename ); bool save( const QString& filename ) const; bool release( const QString& filename, bool verbose = false, bool ignoreUnfinished = false, Translator::SaveMode mode = Translator::Stripped ) const; bool contains( const char *context, const char *sourceText, const char *comment ) const; MetaTranslatorMessage find( const char *context, const char *sourceText, const char *comment ) const; MetaTranslatorMessage find(const char *context, const char *comment, const QString &fileName, int lineNumber) const; void insert( const MetaTranslatorMessage& m ); void stripObsoleteMessages(); void stripEmptyContexts(); void setCodec( const char *name ); // kill me void setCodecForTr( const char *name ) { setCodec(name); } QTextCodec *codecForTr() const { return codec; } QString toUnicode( const char *str, bool utf8 ) const; QString languageCode() const; static void languageAndCountry(const QString &languageCode, QLocale::Language *lang, QLocale::Country *country); void setLanguageCode(const QString &languageCode); QList messages() const; QList translatedMessages() const; static int grammaticalNumerus(QLocale::Language language, QLocale::Country country); static QStringList normalizedTranslations(const MetaTranslatorMessage& m, QLocale::Language lang, QLocale::Country country); private: void makeFileNamesAbsolute(const QDir &oldPath); typedef QMap TMM; typedef QMap TMMInv; TMM mm; QByteArray codecName; QTextCodec *codec; QString m_language; // A string beginning with a 2 or 3 letter language code (ISO 639-1 or ISO-639-2), // followed by the optional country variant to distinguist between country-specific variations // of the language. The language code and country code are always separated by '_' // Note that the language part can also be a 3-letter ISO 639-2 code. // Legal examples: // 'pt' portuguese, assumes portuguese from portugal // 'pt_BR' Brazilian portuguese (ISO 639-1 language code) // 'por_BR' Brazilian portuguese (ISO 639-2 language code) }; /* This is a quick hack. The proper way to handle this would be to extend MetaTranslator's interface. */ #define ContextComment "QT_LINGUIST_INTERNAL_CONTEXT_COMMENT" #endif Tools-0.2.15/pylupdate/numberh.cpp000066400000000000000000000173641220335231500170610ustar00rootroot00000000000000/* * This file is part of the PySide Tools project. * * Copyright (C) 1992-2006 Trolltech AS. All rights reserved. * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). * * Contact: PySide team * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #include "metatranslator.h" #include #include #include #include #include typedef QMap TMM; typedef QList TML; static bool isDigitFriendly( int c ) { return ispunct((uchar)c) || isspace((uchar)c); } static int numberLength( const char *s ) { int i = 0; if ( isdigit((uchar)s[0]) ) { do { i++; } while (isdigit((uchar)s[i]) || (isDigitFriendly(s[i]) && (isdigit((uchar)s[i + 1]) || (isDigitFriendly(s[i + 1]) && isdigit((uchar)s[i + 2]))))); } return i; } /* Returns a version of 'key' where all numbers have been replaced by zeroes. If there were none, returns "". */ static QByteArray zeroKey( const char *key ) { QByteArray zeroed; zeroed.resize( int(strlen(key)) + 1 ); char *z = zeroed.data(); int i = 0, j = 0; int len; bool metSomething = false; while ( key[i] != '\0' ) { len = numberLength( key + i ); if ( len > 0 ) { i += len; z[j++] = '0'; metSomething = true; } else { z[j++] = key[i++]; } } z[j] = '\0'; if ( metSomething ) return zeroed; else return ""; } static QString translationAttempt( const QString& oldTranslation, const char *oldSource, const char *newSource ) { int p = zeroKey( oldSource ).count( '0' ); int oldSourceLen = qstrlen( oldSource ); QString attempt; QStringList oldNumbers; QStringList newNumbers; QVector met( p ); QVector matchedYet( p ); int i, j; int k = 0, ell, best; int m, n; int pass; /* This algorithm is hard to follow, so we'll consider an example all along: oldTranslation is "XeT 3.0", oldSource is "TeX 3.0" and newSource is "XeT 3.1". First, we set up two tables: oldNumbers and newNumbers. In our example, oldNumber[0] is "3.0" and newNumber[0] is "3.1". */ for ( i = 0, j = 0; i < oldSourceLen; i++, j++ ) { m = numberLength( oldSource + i ); n = numberLength( newSource + j ); if ( m > 0 ) { oldNumbers.append( QByteArray(oldSource + i, m + 1) ); newNumbers.append( QByteArray(newSource + j, n + 1) ); i += m; j += n; met[k] = false; matchedYet[k] = 0; k++; } } /* We now go over the old translation, "XeT 3.0", one letter at a time, looking for numbers found in oldNumbers. Whenever such a number is met, it is replaced with its newNumber equivalent. In our example, the "3.0" of "XeT 3.0" becomes "3.1". */ for ( i = 0; i < (int) oldTranslation.length(); i++ ) { attempt += oldTranslation[i]; for ( k = 0; k < p; k++ ) { if ( oldTranslation[i] == oldNumbers[k][matchedYet[k]] ) matchedYet[k]++; else matchedYet[k] = 0; } /* Let's find out if the last character ended a match. We make two passes over the data. In the first pass, we try to match only numbers that weren't matched yet; if that fails, the second pass does the trick. This is useful in some suspicious cases, flagged below. */ for ( pass = 0; pass < 2; pass++ ) { best = p; // an impossible value for ( k = 0; k < p; k++ ) { if ( (!met[k] || pass > 0) && matchedYet[k] == (int) oldNumbers[k].length() && numberLength(oldTranslation.toLatin1().constData() + (i + 1) - matchedYet[k]) == matchedYet[k] ) { // the longer the better if ( best == p || matchedYet[k] > matchedYet[best] ) best = k; } } if ( best != p ) { attempt.truncate( attempt.length() - matchedYet[best] ); attempt += newNumbers[best]; met[best] = true; for ( k = 0; k < p; k++ ) matchedYet[k] = 0; break; } } } /* We flag two kinds of suspicious cases. They are identified as such with comments such as "{2000?}" at the end. Example of the first kind: old source text "TeX 3.0" translated as "XeT 2.0" is flagged "TeX 2.0 {3.0?}", no matter what the new text is. */ for ( k = 0; k < p; k++ ) { if ( !met[k] ) attempt += QString( " {" ) + newNumbers[k] + QString( "?}" ); } /* Example of the second kind: "1 of 1" translated as "1 af 1", with new source text "1 of 2", generates "1 af 2 {1 or 2?}" because it's not clear which of "1 af 2" and "2 af 1" is right. */ for ( k = 0; k < p; k++ ) { for ( ell = 0; ell < p; ell++ ) { if ( k != ell && oldNumbers[k] == oldNumbers[ell] && newNumbers[k] < newNumbers[ell] ) attempt += QString( " {" ) + newNumbers[k] + QString( " or " ) + newNumbers[ell] + QString( "?}" ); } } return attempt; } /* Augments a MetaTranslator with translations easily derived from similar existing (probably obsolete) translations. For example, if "TeX 3.0" is translated as "XeT 3.0" and "TeX 3.1" has no translation, "XeT 3.1" is added to the translator and is marked Unfinished. Returns the number of additional messages that this heuristic translated. */ int applyNumberHeuristic( MetaTranslator *tor ) { TMM translated, untranslated; TMM::Iterator t, u; TML all = tor->messages(); TML::Iterator it; int inserted = 0; for ( it = all.begin(); it != all.end(); ++it ) { bool hasTranslation = (*it).isTranslated(); if ( (*it).type() == MetaTranslatorMessage::Unfinished ) { if ( !hasTranslation ) untranslated.insert(QByteArray((*it).context()) + "\n" + (*it).sourceText() + "\n" + (*it).comment(), *it); } else if ( hasTranslation && (*it).translations().count() == 1 ) { translated.insert( zeroKey((*it).sourceText()), *it ); } } for ( u = untranslated.begin(); u != untranslated.end(); ++u ) { t = translated.find( zeroKey((*u).sourceText()) ); if ( t != translated.end() && !t.key().isEmpty() && qstrcmp((*t).sourceText(), (*u).sourceText()) != 0 ) { MetaTranslatorMessage m( *u ); m.setTranslation(translationAttempt((*t).translation(), (*t).sourceText(), (*u).sourceText())); tor->insert( m ); inserted++; } } return inserted; } Tools-0.2.15/pylupdate/proparser.cpp000066400000000000000000000165241220335231500174330ustar00rootroot00000000000000/* * This file is part of the PySide Tools project. * * Copyright (C) 1992-2005 Trolltech AS. All rights reserved. * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). * * Contact: PySide team * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #include "proparser.h" #include #include #include #include #include #include #ifdef Q_OS_UNIX #include #endif #ifdef Q_OS_WIN32 #define QT_POPEN _popen #else #define QT_POPEN popen #endif QString loadFile( const QString &fileName ) { QFile file( fileName ); if ( !file.open(QIODevice::ReadOnly) ) { fprintf( stderr, "error: Cannot load '%s': %s\n", file.fileName().toLatin1().constData(), file.errorString().toLatin1().constData() ); return QString(); } QTextStream in( &file ); return in.readAll(); } QMap proFileTagMap( const QString& text ) { QString t = text; QMap tagMap; bool stillProcess = true; // If include() has a $$tag then we need to reprocess while (stillProcess) { /* Strip any commments before we try to include. We still need to do it after we include to make sure the included file does not have comments */ t.replace( QRegExp(QString("#[^\n]*\n")), QString(" ") ); /* Process include() commands. $$PWD is a special case so we have to change it while we know where the included file is. */ QRegExp callToInclude("include\\s*\\(\\s*([^()\\s]+)\\s*\\)"); int i = 0; while ( (i = callToInclude.indexIn(t, i)) != -1 ) { bool doneWithVar = false; QString fileName = callToInclude.cap(1); QString after = fileName.replace("$$PWD", QDir::currentPath()); if (!tagMap.isEmpty() && after.contains("$$")) { QRegExp var( "\\$\\$[({]?([a-zA-Z0-9_]+)[)}]?" ); int ii = 0; while ((ii = after.indexOf(var, ii)) != -1) { if (tagMap.contains(var.cap(1))) { after.replace(ii, var.cap(0).length(), tagMap[var.cap(1)]); } else { // Couldn't find it doneWithVar = true; break; } } } if (doneWithVar || !after.contains("$$")) { after = loadFile(after); QFileInfo fi(callToInclude.cap(1)); after.replace("$$PWD", fi.path()); t.replace( i, callToInclude.matchedLength(), after ); } i += after.length(); } /* Strip comments, merge lines ending with backslash, add spaces around '=' and '+=', replace '\n' with ';', and simplify white spaces. */ t.replace( QRegExp(QString("#[^\n]*\n")), QString(" ") ); t.replace( QRegExp(QString("\\\\[^\n\\S]*\n")), QString(" ") ); t.replace( "=", QString(" = ") ); t.replace( "+ =", QString(" += ") ); t.replace( "\n", QString(";") ); t.replace( "\r", QString("") ); // remove carriage return t = t.simplified(); /* Populate tagMap with 'key = value' entries. */ QStringList lines = t.split(';', QString::SkipEmptyParts); QStringList::Iterator line; for ( line = lines.begin(); line != lines.end(); ++line ) { QStringList toks = (*line).split(' ', QString::SkipEmptyParts); if ( toks.count() >= 3 && (toks[1] == QString("=") || toks[1] == QString("+=") || toks[1] == QString("*=")) ) { QString tag = toks.first(); int k = tag.lastIndexOf( QChar(':') ); // as in 'unix:' if ( k != -1 ) tag = tag.mid( k + 1 ); toks.erase( toks.begin() ); QString action = toks.first(); toks.erase( toks.begin() ); if ( tagMap.contains(tag) ) { if ( action == QString("=") ) tagMap.insert( tag, toks.join(" ") ); else tagMap[tag] += QChar( ' ' ) + toks.join( " " ); } else { tagMap[tag] = toks.join( " " ); } } } /* Expand $$variables within the 'value' part of a 'key = value' pair. */ QRegExp var( "\\$\\$[({]?([a-zA-Z0-9_]+)[)}]?" ); QMap::Iterator it; for ( it = tagMap.begin(); it != tagMap.end(); ++it ) { int i = 0; while ( (i = var.indexIn((*it), i)) != -1 ) { int len = var.matchedLength(); QString invocation = var.cap(1); QString after; if ( invocation == "system" ) { // skip system(); it will be handled in the next pass ++i; } else { if ( tagMap.contains(invocation) ) after = tagMap[invocation]; else if (invocation.toLower() == "pwd") after = QDir::currentPath(); (*it).replace( i, len, after ); i += after.length(); } } } /* Execute system() calls. */ QRegExp callToSystem( "\\$\\$system\\s*\\(([^()]*)\\)" ); for ( it = tagMap.begin(); it != tagMap.end(); ++it ) { int i = 0; while ( (i = callToSystem.indexIn((*it), i)) != -1 ) { /* This code is stolen from qmake's project.cpp file. Ideally we would use the same parser, so we wouldn't have this code duplication. */ QString after; char buff[256]; FILE *proc = QT_POPEN( callToSystem.cap(1).toLatin1().constData(), "r" ); while ( proc && !feof(proc) ) { int read_in = int(fread( buff, 1, 255, proc )); if ( !read_in ) break; for ( int i = 0; i < read_in; i++ ) { if ( buff[i] == '\n' || buff[i] == '\t' ) buff[i] = ' '; } buff[read_in] = '\0'; after += buff; } (*it).replace( i, callToSystem.matchedLength(), after ); i += after.length(); } } stillProcess = callToInclude.indexIn(t) != -1; } return tagMap; } Tools-0.2.15/pylupdate/proparser.h000066400000000000000000000021371220335231500170730ustar00rootroot00000000000000/* * This file is part of the PySide Tools project. * * Copyright (C) 1992-2005 Trolltech AS. All rights reserved. * Copyright (C) 2002-2007 Detlev Offenbach * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). * * Contact: PySide team * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #ifndef PROPARSER_H #define PROPARSER_H #include #include QMap proFileTagMap( const QString& text ); #endif Tools-0.2.15/pylupdate/pyside-lupdate.1000066400000000000000000000013121220335231500177120ustar00rootroot00000000000000.TH PYSIDE-LUPDATE "1" "December 2010" "pyside-lupdate" "User Commands" .SH NAME pyside\-lupdate \- extracts translatable messages from Qt UI files and Python source code. .SH DESCRIPTION .SS "Usage:" .IP pyside\-lupdate [options] project\-file .IP pyside\-lupdate [options] source\-files \-ts ts\-files .SS "Options:" .TP \fB\-noobsolete Drop all obsolete strings .TP \fB\-verbose Explain what is being done .TP \fB\-version Display the version of pyside-lupdate and exit .TP \fB\-help Display this information and exit .SH COPYRIGHT Copyright \(co 2010 Nokia Corporation and/or its subsidiary(\fB\-ies\fR) .SH AUTHOR .PP This manpage was written by Marcelo Lira , on the 29. December 2010. Tools-0.2.15/pylupdate/sametexth.cpp000066400000000000000000000054771220335231500174250ustar00rootroot00000000000000/* * This file is part of the PySide Tools project. * * Copyright (C) 1992-2006 Trolltech AS. All rights reserved. * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). * * Contact: PySide team * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #include "metatranslator.h" #include #include typedef QMap TMM; typedef QList TML; /* Augments a MetaTranslator with trivially derived translations. For example, if "Enabled:" is consistendly translated as "Eingeschaltet:" no matter the context or the comment, "Eingeschaltet:" is added as the translation of any untranslated "Enabled:" text and is marked Unfinished. Returns the number of additional messages that this heuristic translated. */ int applySameTextHeuristic( MetaTranslator *tor ) { TMM translated; TMM avoid; TMM::Iterator t; TML untranslated; TML::Iterator u; TML all = tor->messages(); TML::Iterator it; int inserted = 0; for ( it = all.begin(); it != all.end(); ++it ) { if ( (*it).type() == MetaTranslatorMessage::Unfinished ) { if ( !(*it).isTranslated() ) untranslated.append( *it ); } else { QByteArray key = (*it).sourceText(); t = translated.find( key ); if ( t != translated.end() ) { /* The same source text is translated at least two different ways. Do nothing then. */ if ( (*t).translations() != (*it).translations() ) { translated.remove( key ); avoid.insert( key, *it ); } } else if ( !avoid.contains(key) && (*it).isTranslated() ) { translated.insert( key, *it ); } } } for ( u = untranslated.begin(); u != untranslated.end(); ++u ) { QByteArray key = (*u).sourceText(); t = translated.find( key ); if ( t != translated.end() ) { MetaTranslatorMessage m( *u ); m.setTranslations( (*t).translations() ); tor->insert( m ); inserted++; } } return inserted; } Tools-0.2.15/pylupdate/simtexth.cpp000066400000000000000000000215311220335231500172550ustar00rootroot00000000000000/* * This file is part of the PySide Tools project. * * Copyright (C) 1992-2006 Trolltech AS. All rights reserved. * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). * * Contact: PySide team * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #include "simtexth.h" #include "metatranslator.h" #include #include #include typedef QList TML; /* How similar are two texts? The approach used here relies on co-occurrence matrices and is very efficient. Let's see with an example: how similar are "here" and "hither"? The co-occurrence matrix M for "here" is M[h,e] = 1, M[e,r] = 1, M[r,e] = 1, and 0 elsewhere; the matrix N for "hither" is N[h,i] = 1, N[i,t] = 1, ..., N[h,e] = 1, N[e,r] = 1, and 0 elsewhere. The union U of both matrices is the matrix U[i,j] = max { M[i,j], N[i,j] }, and the intersection V is V[i,j] = min { M[i,j], N[i,j] }. The score for a pair of texts is score = (sum of V[i,j] over all i, j) / (sum of U[i,j] over all i, j), a formula suggested by Arnt Gulbrandsen. Here we have score = 2 / 6, or one third. The implementation differs from this in a few details. Most importantly, repetitions are ignored; for input "xxx", M[x,x] equals 1, not 2. */ /* Every character is assigned to one of 20 buckets so that the co-occurrence matrix requires only 20 * 20 = 400 bits, not 256 * 256 = 65536 bits or even more if we want the whole Unicode. Which character falls in which bucket is arbitrary. The second half of the table is a replica of the first half, because of laziness. */ static const int indexOf[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // ! " # $ % & ' ( ) * + , - . / 0, 2, 6, 7, 10, 12, 15, 19, 2, 6, 7, 10, 12, 15, 19, 0, // 0 1 2 3 4 5 6 7 8 9 : ; < = > ? 1, 3, 4, 5, 8, 9, 11, 13, 14, 16, 2, 6, 7, 10, 12, 15, // @ A B C D E F G H I J K L M N O 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 6, 10, 11, 12, 13, 14, // P Q R S T U V W X Y Z [ \ ] ^ _ 15, 12, 16, 17, 18, 19, 2, 10, 15, 7, 19, 2, 6, 7, 10, 0, // ` a b c d e f g h i j k l m n o 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 6, 10, 11, 12, 13, 14, // p q r s t u v w x y z { | } ~ 15, 12, 16, 17, 18, 19, 2, 10, 15, 7, 19, 2, 6, 7, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 6, 7, 10, 12, 15, 19, 2, 6, 7, 10, 12, 15, 19, 0, 1, 3, 4, 5, 8, 9, 11, 13, 14, 16, 2, 6, 7, 10, 12, 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 6, 10, 11, 12, 13, 14, 15, 12, 16, 17, 18, 19, 2, 10, 15, 7, 19, 2, 6, 7, 10, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 6, 10, 11, 12, 13, 14, 15, 12, 16, 17, 18, 19, 2, 10, 15, 7, 19, 2, 6, 7, 10, 0 }; /* The entry bitCount[i] (for i between 0 and 255) is the number of bits used to represent i in binary. */ static const int bitCount[256] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8 }; struct CoMatrix { /* The matrix has 20 * 20 = 400 entries. This requires 50 bytes, or 13 words. Some operations are performed on words for more efficiency. */ union { quint8 b[52]; quint32 w[13]; }; CoMatrix() { memset( b, 0, 52 ); } CoMatrix( const char *text ) { char c = '\0', d; memset( b, 0, 52 ); /* The Knuth books are not in the office only for show; they help make loops 30% faster and 20% as readable. */ while ( (d = *text) != '\0' ) { setCoocc( c, d ); if ( (c = *++text) != '\0' ) { setCoocc( d, c ); text++; } } } void setCoocc( char c, char d ) { int k = indexOf[(uchar) c] + 20 * indexOf[(uchar) d]; b[k >> 3] |= k & 0x7; } int worth() const { int w = 0; for ( int i = 0; i < 50; i++ ) w += bitCount[b[i]]; return w; } }; static inline CoMatrix reunion( const CoMatrix& m, const CoMatrix& n ) { CoMatrix p; for ( int i = 0; i < 13; i++ ) p.w[i] = m.w[i] | n.w[i]; return p; } static inline CoMatrix intersection( const CoMatrix& m, const CoMatrix& n ) { CoMatrix p; for ( int i = 0; i < 13; i++ ) p.w[i] = m.w[i] & n.w[i]; return p; } StringSimilarityMatcher::StringSimilarityMatcher(const QString &stringToMatch) { m_cm = new CoMatrix( stringToMatch.toLatin1().constData() ); m_length = stringToMatch.length(); } int StringSimilarityMatcher::getSimilarityScore(const QString &strCandidate) { CoMatrix cmTarget( strCandidate.toLatin1().constData() ); int targetLen = strCandidate.length(); int delta = qAbs( m_length - targetLen ); int score = ( (intersection(*m_cm, cmTarget).worth() + 1) << 10 ) / ( reunion(*m_cm, cmTarget).worth() + (delta << 1) + 1 ); return score; } StringSimilarityMatcher::~StringSimilarityMatcher() { delete m_cm; } /** * Checks how similar two strings are. * The return value is the score, and a higher score is more similar than one with a low score. * Linguist considers a score over 190 to be a good match. * \sa StringSimilarityMatcher */ int getSimilarityScore(const QString &str1, const char* str2) { CoMatrix cmTarget( str2 ); int targetLen = qstrlen( str2 ); CoMatrix cm( str1.toLatin1().constData() ); int delta = qAbs( (int) str1.length() - targetLen ); int score = ( (intersection(cm, cmTarget).worth() + 1) << 10 ) / ( reunion(cm, cmTarget).worth() + (delta << 1) + 1 ); return score; } CandidateList similarTextHeuristicCandidates( const MetaTranslator *tor, const char *text, int maxCandidates ) { QList scores; CandidateList candidates; TML all = tor->translatedMessages(); foreach ( MetaTranslatorMessage mtm, all ) { if ( mtm.type() == MetaTranslatorMessage::Unfinished || mtm.translation().isEmpty() ) continue; QString s = tor->toUnicode( mtm.sourceText(), mtm.utf8() ); int score = getSimilarityScore(s, text); if ( (int) candidates.count() == maxCandidates && score > scores[maxCandidates - 1] ) candidates.removeAt( candidates.size()-1 ); if ( (int) candidates.count() < maxCandidates && score >= textSimilarityThreshold ) { Candidate cand( s, mtm.translation() ); int i; for ( i = 0; i < (int) candidates.size(); i++ ) { if ( score >= scores.at(i) ) { if ( score == scores.at(i) ) { if ( candidates.at(i) == cand ) goto continue_outer_loop; } else { break; } } } scores.insert( i, score ); candidates.insert( i, cand ); } continue_outer_loop: ; } return candidates; } Tools-0.2.15/pylupdate/simtexth.h000066400000000000000000000043251220335231500167240ustar00rootroot00000000000000/* * This file is part of the PySide Tools project. * * Copyright (C) 1992-2006 Trolltech AS. All rights reserved. * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). * * Contact: PySide team * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #ifndef SIMTEXTH_H #define SIMTEXTH_H const int textSimilarityThreshold = 190; #include #include class MetaTranslator; struct Candidate { QString source; QString target; Candidate() { } Candidate( const QString& source0, const QString& target0 ) : source( source0 ), target( target0 ) { } }; inline bool operator==( const Candidate& c, const Candidate& d ) { return c.target == d.target && c.source == d.source; } inline bool operator!=( const Candidate& c, const Candidate& d ) { return !operator==( c, d ); } typedef QList CandidateList; struct CoMatrix; /** * This class is more efficient for searching through a large array of candidate strings, since we only * have to construct the CoMatrix for the \a stringToMatch once, * after that we just call getSimilarityScore(strCandidate). * \sa getSimilarityScore */ class StringSimilarityMatcher { public: StringSimilarityMatcher(const QString &stringToMatch); ~StringSimilarityMatcher(); int getSimilarityScore(const QString &strCandidate); private: CoMatrix *m_cm; int m_length; }; int getSimilarityScore(const QString &str1, const char* str2); CandidateList similarTextHeuristicCandidates( const MetaTranslator *tor, const char *text, int maxCandidates ); #endif Tools-0.2.15/pylupdate/translator.cpp000066400000000000000000001035541220335231500176070ustar00rootroot00000000000000/* * This file is part of the PySide Tools project. * * Copyright (C) 1992-2005 Trolltech AS. All rights reserved. * Copyright (C) 2002-2007 Detlev Offenbach * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). * * Contact: PySide team * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #include "translator.h" #ifndef QT_NO_TRANSLATION #include "qfileinfo.h" #include "qstring.h" #include "qcoreapplication.h" #include "qdatastream.h" #include "qfile.h" #include "qmap.h" #include "qalgorithms.h" #include "qhash.h" #include "qglobal.h" // most of the headers below are already included in qplatformdefs.h // also this lacks Large File support but that's probably irrelevant #if defined(QT_USE_MMAP) // for mmap #include #include #endif #include /* $ mcookie 3cb86418caef9c95cd211cbf60a1bddd $ */ // magic number for the file static const int MagicLength = 16; static const uchar magic[MagicLength] = { 0x3c, 0xb8, 0x64, 0x18, 0xca, 0xef, 0x9c, 0x95, 0xcd, 0x21, 0x1c, 0xbf, 0x60, 0xa1, 0xbd, 0xdd }; static uint elfHash(const char * name) { const uchar *k; uint h = 0; uint g; if (name) { k = (const uchar *) name; while (*k) { h = (h << 4) + *k++; if ((g = (h & 0xf0000000)) != 0) h ^= g >> 24; h &= ~g; } } if (!h) h = 1; return h; } extern bool qt_detectRTLLanguage(); class TranslatorPrivate { public: struct Offset { Offset() : h(0), o(0) { } Offset(const TranslatorMessage& m, int offset) : h(m.hash()), o(offset) { } bool operator<(const Offset &other) const { return (h != other.h) ? h < other.h : o < other.o; } bool operator==(const Offset &other) const { return h == other.h && o == other.o; } uint h; uint o; }; enum { Contexts = 0x2f, Hashes = 0x42, Messages = 0x69 }; TranslatorPrivate(Translator *qq) : q(qq), unmapPointer(0), unmapLength(0) {} // Translator must finalize this before deallocating it Translator *q; // for mmap'ed files, this is what needs to be unmapped. char *unmapPointer; unsigned int unmapLength; // for squeezed but non-file data, this is what needs to be deleted QByteArray messageArray; QByteArray offsetArray; QByteArray contextArray; #ifndef QT_NO_TRANSLATION_BUILDER QMap messages; #endif bool do_load(const uchar *data, int len); }; /*! \class Translator \brief The Translator class provides internationalization support for text output. \ingroup i18n \ingroup environment \mainclass An object of this class contains a set of TranslatorMessage objects, each of which specifies a translation from a source language to a target language. Translator provides functions to look up translations, add new ones, remove them, load and save them, etc. The most common use of Translator is to: load a translator file created with \l{Qt Linguist Manual}, install it using QApplication::installTranslator(), and use it via QObject::tr(). For example: \code int main(int argc, char ** argv) { QApplication app(argc, argv); Translator translator(0); translator.load("french.qm", "."); app.installTranslator(&translator); MyWidget m; app.setMainWidget(&m); m.show(); return app.exec(); } \endcode Note that the translator must be created \e before the application's main window. Most applications will never need to do anything else with this class. The other functions provided by this class are useful for applications that work on translator files. We call a translation a "messsage". For this reason, translation files are sometimes referred to as "message files". It is possible to lookup a translation using findMessage() (as tr() and QApplication::translate() do) and contains(), to insert a new translation messsage using insert(), and to remove one using remove(). Translation tools often need more information than the bare source text and translation, for example, context information to help the translator. But end-user programs that are using translations usually only need lookup. To cater for these different needs, Translator can use stripped translator files that use the minimum of memory and which support little more functionality than findMessage(). Thus, load() may not load enough information to make anything more than findMessage() work. save() has an argument indicating whether to save just this minimum of information or to save everything. "Everything" means that for each translation item the following information is kept: \list \i The \e {translated text} - the return value from tr(). \i The input key: \list \i The \e {source text} - usually the argument to tr(). \i The \e context - usually the class name for the tr() caller. \i The \e comment - a comment that helps disambiguate different uses of the same text in the same context. \endlist \endlist The minimum for each item is just the information necessary for findMessage() to return the right text. This may include the source, context and comment, but usually it is just a hash value and the translated text. For example, the "Cancel" in a dialog might have "Anuluj" when the program runs in Polish (in this case the source text would be "Cancel"). The context would (normally) be the dialog's class name; there would normally be no comment, and the translated text would be "Anuluj". But it's not always so simple. The Spanish version of a printer dialog with settings for two-sided printing and binding would probably require both "Activado" and "Activada" as translations for "Enabled". In this case the source text would be "Enabled" in both cases, and the context would be the dialog's class name, but the two items would have disambiguating comments such as "two-sided printing" for one and "binding" for the other. The comment enables the translator to choose the appropriate gender for the Spanish version, and enables Qt to distinguish between translations. Note that when Translator loads a stripped file, most functions do not work. The functions that do work with stripped files are explicitly documented as such. \sa TranslatorMessage QApplication::installTranslator() QApplication::removeTranslator() QObject::tr() QApplication::translate() */ /*! \enum Translator::SaveMode This enum type defines how Translator writes translation files. There are two modes: \value Everything files are saved with all available information \value Stripped files are saved with just enough information for end-user applications Note that when Translator loads a stripped file, most functions do not work. The functions that do work with stripped files are explicitly documented as such. */ /*! Constructs an empty message file object with parent \a parent that is not connected to any file. */ Translator::Translator(QObject * parent) : QTranslator(parent) { d = new TranslatorPrivate(this); } /*! Destroys the object and frees any allocated resources. */ Translator::~Translator() { if (QCoreApplication::instance()) QCoreApplication::instance()->removeTranslator(this); clear(); delete d; } /*! Loads \a filename + \a suffix (".qm" if the \a suffix is not specified), which may be an absolute file name or relative to \a directory. The previous contents of this translator object is discarded. If the file name does not exist, other file names are tried in the following order: \list 1 \i File name without \a suffix appended. \i File name with text after a character in \a search_delimiters stripped ("_." is the default for \a search_delimiters if it is an empty string) and \a suffix. \i File name stripped without \a suffix appended. \i File name stripped further, etc. \endlist For example, an application running in the fr_CA locale (French-speaking Canada) might call load("foo.fr_ca", "/opt/foolib"). load() would then try to open the first existing readable file from this list: \list 1 \i /opt/foolib/foo.fr_ca.qm \i /opt/foolib/foo.fr_ca \i /opt/foolib/foo.fr.qm \i /opt/foolib/foo.fr \i /opt/foolib/foo.qm \i /opt/foolib/foo \endlist \sa save() */ bool Translator::load(const QString & filename, const QString & directory, const QString & search_delimiters, const QString & suffix) { clear(); QString prefix; if (filename[0] == QLatin1Char('/') #ifdef Q_WS_WIN || (filename[0].isLetter() && filename[1] == QLatin1Char(':')) || filename[0] == QLatin1Char('\\') #endif ) prefix = QLatin1String(""); else prefix = directory; if (prefix.length()) { if (prefix[int(prefix.length()-1)] != QLatin1Char('/')) prefix += QLatin1Char('/'); } QString fname = filename; QString realname; QString delims; delims = search_delimiters.isNull() ? QString::fromLatin1("_.") : search_delimiters; for (;;) { QFileInfo fi; realname = prefix + fname + (suffix.isNull() ? QString::fromLatin1(".qm") : suffix); fi.setFile(realname); if (fi.isReadable()) break; realname = prefix + fname; fi.setFile(realname); if (fi.isReadable()) break; int rightmost = 0; for (int i = 0; i < (int)delims.length(); i++) { int k = fname.lastIndexOf(delims[i]); if (k > rightmost) rightmost = k; } // no truncations? fail if (rightmost == 0) return false; fname.truncate(rightmost); } // realname is now the fully qualified name of a readable file. bool ok = false; #ifdef QT_USE_MMAP #ifndef MAP_FILE #define MAP_FILE 0 #endif #ifndef MAP_FAILED #define MAP_FAILED -1 #endif int fd = -1; if (!realname.startsWith(QLatin1String(":"))) fd = QT_OPEN(QFile::encodeName(realname), O_RDONLY, #if defined(Q_OS_WIN) _S_IREAD | _S_IWRITE #else 0666 #endif ); if (fd >= 0) { struct stat st; if (!fstat(fd, &st)) { char *ptr; ptr = reinterpret_cast( mmap(0, st.st_size, // any address, whole file PROT_READ, // read-only memory MAP_FILE | MAP_PRIVATE, // swap-backed map from file fd, 0)); // from offset 0 of fd if (ptr && ptr != reinterpret_cast(MAP_FAILED)) { d->unmapPointer = ptr; d->unmapLength = st.st_size; ok = true; } } ::close(fd); } #endif // QT_USE_MMAP if (!ok) { QFile file(realname); if (!file.exists()) return false; d->unmapLength = file.size(); d->unmapPointer = new char[d->unmapLength]; if (file.open(QIODevice::ReadOnly)) ok = (d->unmapLength == (uint)file.read(d->unmapPointer, d->unmapLength)); if (!ok) { delete [] d->unmapPointer; d->unmapPointer = 0; d->unmapLength = 0; return false; } } return d->do_load(reinterpret_cast(d->unmapPointer), d->unmapLength); } /*! \overload \fn bool Translator::load(const uchar *data, int len) Loads the .qm file data \a data of length \a len into the translator. The data is not copied. The caller must be able to guarantee that \a data will not be deleted or modified. */ bool Translator::load(const uchar *data, int len) { clear(); return d->do_load(data, len); } bool TranslatorPrivate::do_load(const uchar *data, int len) { if (len < MagicLength || memcmp(data, magic, MagicLength) != 0) { q->clear(); return false; } QByteArray array = QByteArray::fromRawData((const char *) data, len); QDataStream s(&array, QIODevice::ReadOnly); bool ok = true; s.device()->seek(MagicLength); quint8 tag = 0; quint32 blockLen = 0; s >> tag >> blockLen; while (tag && blockLen) { if ((quint32) s.device()->pos() + blockLen > (quint32) len) { ok = false; break; } if (tag == TranslatorPrivate::Contexts) { contextArray = QByteArray(array.constData() + s.device()->pos(), blockLen); } else if (tag == TranslatorPrivate::Hashes) { offsetArray = QByteArray(array.constData() + s.device()->pos(), blockLen); } else if (tag == TranslatorPrivate::Messages) { messageArray = QByteArray(array.constData() + s.device()->pos(), blockLen); } if (!s.device()->seek(s.device()->pos() + blockLen)) { ok = false; break; } tag = 0; blockLen = 0; if (!s.atEnd()) s >> tag >> blockLen; } return ok; } #ifndef QT_NO_TRANSLATION_BUILDER /*! Saves this message file to \a filename, overwriting the previous contents of \a filename. If \a mode is \c Everything (the default), all the information is preserved. If \a mode is \c Stripped, any information that is not necessary for findMessage() is stripped away. \sa load() */ bool Translator::save(const QString & filename, SaveMode mode) { QFile file(filename); if (file.open(QIODevice::WriteOnly)) { squeeze(mode); QDataStream s(&file); s.writeRawData((const char *)magic, MagicLength); quint8 tag; if (!d->offsetArray.isEmpty()) { tag = (quint8)TranslatorPrivate::Hashes; quint32 oas = (quint32)d->offsetArray.size(); s << tag << oas; s.writeRawData(d->offsetArray, oas); } if (!d->messageArray.isEmpty()) { tag = (quint8)TranslatorPrivate::Messages; quint32 mas = (quint32)d->messageArray.size(); s << tag << mas; s.writeRawData(d->messageArray, mas); } if (!d->contextArray.isEmpty()) { tag = (quint8)TranslatorPrivate::Contexts; quint32 cas = (quint32)d->contextArray.size(); s << tag << cas; s.writeRawData(d->contextArray, cas); } return true; } return false; } #endif /*! Empties this translator of all contents. This function works with stripped translator files. */ void Translator::clear() { if (d->unmapPointer && d->unmapLength) { #if defined(QT_USE_MMAP) munmap(d->unmapPointer, d->unmapLength); #else delete [] d->unmapPointer; #endif d->unmapPointer = 0; d->unmapLength = 0; } d->messageArray.clear(); d->offsetArray.clear(); d->contextArray.clear(); #ifndef QT_NO_TRANSLATION_BUILDER d->messages.clear(); #endif QEvent ev(QEvent::LanguageChange); QCoreApplication::sendEvent(QCoreApplication::instance(), &ev); } #ifndef QT_NO_TRANSLATION_BUILDER /*! Converts this message file to the compact format used to store message files on disk. You should never need to call this directly; save() and other functions call it as necessary. \a mode is for internal use. \sa save() unsqueeze() */ void Translator::squeeze(SaveMode mode) { if (d->messages.isEmpty()) { if (mode == Stripped) unsqueeze(); else return; } QMap messages = d->messages; clear(); QMap offsets; QDataStream ms(&d->messageArray, QIODevice::WriteOnly); QMap::const_iterator it, next; int cpPrev = 0, cpNext = 0; for (it = messages.constBegin(); it != messages.constEnd(); ++it) { cpPrev = cpNext; next = it; ++next; if (next == messages.constEnd()) cpNext = 0; else cpNext = (int) it.key().commonPrefix(next.key()); offsets.insert(TranslatorPrivate::Offset(it.key(), ms.device()->pos()), (void *)0); it.key().write(ms, mode == Stripped, (TranslatorMessage::Prefix)qMax(cpPrev, cpNext + 1)); } QMap::Iterator offset; offset = offsets.begin(); QDataStream ds(&d->offsetArray, QIODevice::WriteOnly); while (offset != offsets.end()) { TranslatorPrivate::Offset k = offset.key(); ++offset; ds << (quint32)k.h << (quint32)k.o; } if (mode == Stripped) { QMap contextSet; for (it = messages.constBegin(); it != messages.constEnd(); ++it) ++contextSet[it.key().context()]; quint16 hTableSize; if (contextSet.size() < 200) hTableSize = (contextSet.size() < 60) ? 151 : 503; else if (contextSet.size() < 2500) hTableSize = (contextSet.size() < 750) ? 1511 : 5003; else hTableSize = (contextSet.size() < 10000) ? 15013 : 3 * contextSet.size() / 2; QMultiMap hashMap; QMap::const_iterator c; for (c = contextSet.constBegin(); c != contextSet.constEnd(); ++c) hashMap.insert(elfHash(c.key()) % hTableSize, c.key()); /* The contexts found in this translator are stored in a hash table to provide fast lookup. The context array has the following format: quint16 hTableSize; quint16 hTable[hTableSize]; quint8 contextPool[...]; The context pool stores the contexts as Pascal strings: quint8 len; quint8 data[len]; Let's consider the look-up of context "FunnyDialog". A hash value between 0 and hTableSize - 1 is computed, say h. If hTable[h] is 0, "FunnyDialog" is not covered by this translator. Else, we check in the contextPool at offset 2 * hTable[h] to see if "FunnyDialog" is one of the contexts stored there, until we find it or we meet the empty string. */ d->contextArray.resize(2 + (hTableSize << 1)); QDataStream t(&d->contextArray, QIODevice::WriteOnly); quint16 *hTable = new quint16[hTableSize]; memset(hTable, 0, hTableSize * sizeof(quint16)); t << hTableSize; t.device()->seek(2 + (hTableSize << 1)); t << (quint16)0; // the entry at offset 0 cannot be used uint upto = 2; QMap::const_iterator entry = hashMap.constBegin(); while (entry != hashMap.constEnd()) { int i = entry.key(); hTable[i] = (quint16)(upto >> 1); do { const char *con = entry.value(); uint len = (uint)qstrlen(con); len = qMin(len, 255u); t << (quint8)len; t.writeRawData(con, len); upto += 1 + len; ++entry; } while (entry != hashMap.constEnd() && entry.key() == i); do { t << (quint8) 0; // empty string ++upto; } while ((upto & 0x1) != 0); // offsets have to be even } t.device()->seek(2); for (int j = 0; j < hTableSize; j++) t << hTable[j]; delete [] hTable; if (upto > 131072) { qWarning("Translator::squeeze: Too many contexts"); d->contextArray.clear(); } } } /*! Converts this message file into an easily modifiable data structure, less compact than the format used in the files. You should never need to call this function; it is called by insert() and friends as necessary. \sa squeeze() */ void Translator::unsqueeze() { if (!d->messages.isEmpty() || d->messageArray.isEmpty()) return; qFatal("Cannot unsqueeze (bug in Linguist?)"); } /*! Returns true if this message file contains a message with the key (\a context, \a sourceText, \a comment); otherwise returns false. This function works with stripped translator files. (This is is a one-liner that calls findMessage().) */ bool Translator::contains(const char* context, const char* sourceText, const char* comment) const { return !findMessage(context, sourceText, comment).translation().isNull(); } bool Translator::contains(const char *context, const char *comment, const QString &fileName, int lineNumber) const { return !findMessage(context, 0, comment, fileName, lineNumber).isNull(); } /*! Inserts \a message into this message file. This function does \e not work with stripped translator files. It may appear to, but that is not dependable. \sa remove() */ void Translator::insert(const TranslatorMessage& message) { unsqueeze(); d->messages.remove(message); // safer d->messages.insert(message, (void *) 0); } /*! \fn void Translator::insert(const char *context, const char *sourceText, const QString &translation) \overload \obsolete Inserts the \a sourceText and \a translation into the translator with the given \a context. */ /*! Removes \a message from this translator. This function works with stripped translator files. \sa insert() */ void Translator::remove(const TranslatorMessage& message) { unsqueeze(); d->messages.remove(message); } /*! \fn void Translator::remove(const char *, const char *) \overload \obsolete Removes the translation associated to the key (\a context, \a sourceText, "") from this translator. */ #endif /*! Returns the TranslatorMessage for the key (\a context, \a sourceText, \a comment). If none is found, also tries (\a context, \a sourceText, ""). */ TranslatorMessage Translator::findMessage(const char *context, const char *sourceText, const char *comment, const QString &fileName, int lineNumber) const { if (context == 0) context = ""; if (sourceText == 0) sourceText = ""; if (comment == 0) comment = ""; QString myFilename = fileName; int myLineNumber = lineNumber; if (!d->messages.isEmpty()) { QMap::const_iterator it; // Either we want to find an item that matches context, sourcetext (and optionally comment) // Or we want to find an item that matches context, filename, linenumber (and optionally comment) it = d->messages.find(TranslatorMessage(context, sourceText, comment, myFilename, myLineNumber)); if (it != d->messages.constEnd()) return it.key(); if (comment[0]) { it = d->messages.find(TranslatorMessage(context, sourceText, "", myFilename, myLineNumber)); if (it != d->messages.constEnd()) return it.key(); } it = d->messages.find(TranslatorMessage(context, "", comment, myFilename, myLineNumber)); if (it != d->messages.constEnd()) return it.key(); if (comment[0]) { it = d->messages.find(TranslatorMessage(context, "", "", myFilename, myLineNumber)); if (it != d->messages.constEnd()) return it.key(); } return TranslatorMessage(); } return TranslatorMessage(); } /*! Returns true if this translator is empty, otherwise returns false. This function works with stripped and unstripped translation files. */ bool Translator::isEmpty() const { return !d->unmapPointer && !d->unmapLength && d->messageArray.isEmpty() && d->offsetArray.isEmpty() && d->contextArray.isEmpty() && d->messages.isEmpty(); } #ifndef QT_NO_TRANSLATION_BUILDER /*! Returns a list of the messages in the translator. This function is rather slow. Because it is seldom called, it's optimized for simplicity and small size, rather than speed. If you want to iterate over the list, you should iterate over a copy, e.g. \code QList list = myTranslator.messages(); QList::Iterator it = list.begin(); while (it != list.end()) { process_message(*it); ++it; } \endcode */ QList Translator::messages() const { ((Translator *) this)->unsqueeze(); return d->messages.keys(); } #endif /*! \class TranslatorMessage \brief The TranslatorMessage class contains a translator message and its properties. \ingroup i18n \ingroup environment This class is of no interest to most applications. It is useful for translation tools such as \l{Qt Linguist Manual}{Qt Linguist}. It is provided simply to make the API complete and regular. For a Translator object, a lookup key is a triple (\e context, \e {source text}, \e comment) that uniquely identifies a message. An extended key is a quadruple (\e hash, \e context, \e {source text}, \e comment), where \e hash is computed from the source text and the comment. Unless you plan to read and write messages yourself, you need not worry about the hash value. TranslatorMessage stores this triple or quadruple and the relevant translation if there is any. \sa Translator */ /*! Constructs a translator message with the extended key (0, 0, 0, 0) and an empty string as translation. */ TranslatorMessage::TranslatorMessage() : h(0), m_fileName(), m_lineNumber(-1) { } /*! Constructs an translator message with the extended key (\e h, \a context, \a sourceText, \a comment), where \e h is computed from \a sourceText and \a comment, and possibly with a \a translation. */ TranslatorMessage::TranslatorMessage(const char * context, const char * sourceText, const char * comment, const QString &fileName, int lineNumber, const QStringList& translations) : cx(context), st(sourceText), cm(comment), m_translations(translations), m_fileName(fileName), m_lineNumber(lineNumber) { // 0 means we don't know, "" means empty if (cx == (const char*)0) cx = ""; if (st == (const char*)0) st = ""; if (cm == (const char*)0) cm = ""; h = elfHash(st + cm); } /*! Constructs a copy of translator message \a m. */ TranslatorMessage::TranslatorMessage(const TranslatorMessage & m) : cx(m.cx), st(m.st), cm(m.cm), m_translations(m.m_translations), m_fileName(m.m_fileName), m_lineNumber(m.m_lineNumber) { h = m.h; } /*! Assigns message \a m to this translator message and returns a reference to this translator message. */ TranslatorMessage & TranslatorMessage::operator=( const TranslatorMessage & m) { h = m.h; cx = m.cx; st = m.st; cm = m.cm; m_translations = m.m_translations; m_fileName = m.m_fileName; m_lineNumber = m.m_lineNumber; return *this; } /*! \fn uint TranslatorMessage::hash() const Returns the hash value used internally to represent the lookup key. This value is zero only if this translator message was constructed from a stream containing invalid data. The hashing function is unspecified, but it will remain unchanged in future versions of Qt. */ /*! \fn const char *TranslatorMessage::context() const Returns the context for this message (e.g. "MyDialog"). */ /*! \fn const char *TranslatorMessage::sourceText() const Returns the source text of this message (e.g. "&Save"). */ /*! \fn const char *TranslatorMessage::comment() const Returns the comment for this message (e.g. "File|Save"). */ /*! \fn void TranslatorMessage::setTranslation(const QString & translation) Sets the translation of the source text to \a translation. \sa translation() */ /*! \fn QString TranslatorMessage::translation() const Returns the translation of the source text (e.g., "&Sauvegarder"). \sa setTranslation() */ /*! \enum TranslatorMessage::Prefix Let (\e h, \e c, \e s, \e m) be the extended key. The possible prefixes are \value NoPrefix no prefix \value Hash only (\e h) \value HashContext only (\e h, \e c) \value HashContextSourceText only (\e h, \e c, \e s) \value HashContextSourceTextComment the whole extended key, (\e h, \e c, \e s, \e m) \sa write() commonPrefix() */ /*! Writes this translator message to the \a stream. If \a strip is false (the default), all the information in the message is written. If \a strip is true, only the part of the extended key specified by \a prefix is written with the translation (\c HashContextSourceTextComment by default). \sa commonPrefix() */ void TranslatorMessage::write(QDataStream & stream, bool strip, Prefix prefix) const { for (int i = 0; i < m_translations.count(); ++i) stream << quint8(Tag_Translation) << m_translations.at(i); if (!strip) prefix = HashContextSourceTextComment; switch (prefix) { case HashContextSourceTextComment: stream << quint8(Tag_Comment) << cm; // fall through case HashContextSourceText: stream << quint8(Tag_SourceText) << st; // fall through case HashContext: stream << quint8(Tag_Context) << cx; default: ; } stream << quint8(Tag_End); } /*! Returns the widest lookup prefix that is common to this translator message and to message \a m. For example, if the extended key is for this message is (71, "PrintDialog", "Yes", "Print?") and that for \a m is (71, "PrintDialog", "No", "Print?"), this function returns \c HashContext. \sa write() */ TranslatorMessage::Prefix TranslatorMessage::commonPrefix( const TranslatorMessage& m) const { if (h != m.h) return NoPrefix; if (cx != m.cx) return Hash; if (st != m.st) return HashContext; if (cm != m.cm) return HashContextSourceText; return HashContextSourceTextComment; } /*! Returns true if the extended key of this object is equal to that of \a m; otherwise returns false. */ bool TranslatorMessage::operator==(const TranslatorMessage& m) const { bool isHashEq = (h == m.h ? true : false); bool isContextEq = (cx == m.cx ? true : false); bool isSourceEq = (st == m.st ? true : false); bool isCommentEq = (cm == m.cm ? true : false); bool isLocationEq = m_lineNumber == m.m_lineNumber && m_fileName == m.m_fileName; return (isHashEq && isContextEq && isSourceEq && isCommentEq) || // translation can be different, but treat the equal (st.isEmpty() && isContextEq && isCommentEq && isLocationEq); } /*! \fn bool TranslatorMessage::operator!=(const TranslatorMessage& m) const Returns true if the extended key of this object is different from that of \a m; otherwise returns false. */ /*! Returns true if the extended key of this object is lexicographically before than that of \a m; otherwise returns false. */ bool TranslatorMessage::operator<(const TranslatorMessage& m) const { return h != m.h ? h < m.h : (cx != m.cx ? cx < m.cx : (st != m.st ? st < m.st : cm < m.cm)); } /*! \fn bool TranslatorMessage::operator<=(const TranslatorMessage& m) const Returns true if the extended key of this object is lexicographically before that of \a m or if they are equal; otherwise returns false. */ /*! \fn bool TranslatorMessage::operator>(const TranslatorMessage& m) const Returns true if the extended key of this object is lexicographically after that of \a m; otherwise returns false. */ /*! \fn bool TranslatorMessage::operator>=(const TranslatorMessage& m) const Returns true if the extended key of this object is lexicographically after that of \a m or if they are equal; otherwise returns false. */ /*! \fn QString Translator::find(const char *context, const char *sourceText, const char * comment) const Use findMessage() instead. */ bool getNumerusInfo(QLocale::Language language, QLocale::Country country, QStringList *forms) { forever { for (int i = 0; i < NumerusTableSize; ++i) { const NumerusTableEntry &entry = numerusTable[i]; for (int j = 0; entry.languages[j] != EOL; ++j) { if (entry.languages[j] == language && ((!entry.countries && country == QLocale::AnyCountry) || (entry.countries && entry.countries[j] == country))) { if (forms) { forms->clear(); for (int k = 0; entry.forms[k]; ++k) forms->append(QLatin1String(entry.forms[k])); } return true; } } } if (country == QLocale::AnyCountry) break; country = QLocale::AnyCountry; } return false; } #endif // QT_NO_TRANSLATION Tools-0.2.15/pylupdate/translator.h000066400000000000000000000315151220335231500172510ustar00rootroot00000000000000/* * This file is part of the PySide Tools project. * * Copyright (C) 1992-2005 Trolltech AS. All rights reserved. * Copyright (C) 2002-2007 Detlev Offenbach * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). * * Contact: PySide team * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #ifndef TRANSLATOR_H #define TRANSLATOR_H #include "QtCore/qobject.h" #include "QtCore/qbytearray.h" #include "QtCore/qstringlist.h" #include "QtCore/qlocale.h" #include class TranslatorPrivate; template class QList; class TranslatorMessage { public: TranslatorMessage(); TranslatorMessage(const char * context, const char * sourceText, const char * comment, const QString &fileName, int lineNumber, const QStringList& translations = QStringList()); TranslatorMessage(const TranslatorMessage & m); TranslatorMessage & operator=(const TranslatorMessage & m); uint hash() const { return h; } const char *context() const { return cx.isNull() ? 0 : cx.constData(); } const char *sourceText() const { return st.isNull() ? 0 : st.constData(); } const char *comment() const { return cm.isNull() ? 0 : cm.constData(); } inline void setTranslations(const QStringList &translations); QStringList translations() const { return m_translations; } void setTranslation(const QString &translation) { m_translations = QStringList(translation); } QString translation() const { return m_translations.value(0); } bool isTranslated() const { return m_translations.count() > 1 || !m_translations.value(0).isEmpty(); } enum Prefix { NoPrefix, Hash, HashContext, HashContextSourceText, HashContextSourceTextComment }; void write(QDataStream & s, bool strip = false, Prefix prefix = HashContextSourceTextComment) const; Prefix commonPrefix(const TranslatorMessage&) const; bool operator==(const TranslatorMessage& m) const; bool operator!=(const TranslatorMessage& m) const { return !operator==(m); } bool operator<(const TranslatorMessage& m) const; bool operator<=(const TranslatorMessage& m) const { return !m.operator<(*this); } bool operator>(const TranslatorMessage& m) const { return m.operator<(*this); } bool operator>=(const TranslatorMessage& m) const { return !operator<(m); } QString fileName(void) const { return m_fileName; } void setFileName(const QString &fileName) { m_fileName = fileName; } int lineNumber(void) const { return m_lineNumber; } void setLineNumber(int lineNumber) { m_lineNumber = lineNumber; } bool isNull() const { return st.isNull() && m_lineNumber == -1 && m_translations.isEmpty(); } private: uint h; QByteArray cx; QByteArray st; QByteArray cm; QStringList m_translations; QString m_fileName; int m_lineNumber; enum Tag { Tag_End = 1, Tag_SourceText16, Tag_Translation, Tag_Context16, Tag_Hash, Tag_SourceText, Tag_Context, Tag_Comment, Tag_Obsolete1 }; }; Q_DECLARE_TYPEINFO(TranslatorMessage, Q_MOVABLE_TYPE); inline void TranslatorMessage::setTranslations(const QStringList &translations) { m_translations = translations; } class Translator : public QTranslator { Q_OBJECT public: explicit Translator(QObject *parent = 0); ~Translator(); virtual TranslatorMessage findMessage(const char *context, const char *sourceText, const char *comment = 0, const QString &fileName = 0, int lineNumber = -1) const; virtual QString translate(const char *context, const char *sourceText, const char *comment = 0) const { return findMessage(context, sourceText, comment).translation(); } bool load(const QString & filename, const QString & directory = QString(), const QString & search_delimiters = QString(), const QString & suffix = QString()); bool load(const uchar *data, int len); void clear(); enum SaveMode { Everything, Stripped }; bool save(const QString & filename, SaveMode mode = Everything); void insert(const TranslatorMessage&); inline void insert(const char *context, const char *sourceText, const QString &fileName, int lineNo, const QStringList &translations) { insert(TranslatorMessage(context, sourceText, "", fileName, lineNo, translations)); } void remove(const TranslatorMessage&); inline void remove(const char *context, const char *sourceText) { remove(TranslatorMessage(context, sourceText, "", QLatin1String(""), -1)); } bool contains(const char *context, const char *sourceText, const char * comment = 0) const; bool contains(const char *context, const char *comment, const QString &fileName, int lineNumber) const; void squeeze(SaveMode = Everything); void unsqueeze(); QList messages() const; bool isEmpty() const; private: Q_DISABLE_COPY(Translator) TranslatorPrivate *d; }; static const char * const japaneseStyleForms[] = { "Unique Form", 0 }; static const char * const englishStyleForms[] = { "Singular", "Plural", 0 }; static const char * const frenchStyleForms[] = { "Singular", "Plural", 0 }; static const char * const latvianForms[] = { "Singular", "Plural", "Nullar", 0 }; static const char * const irishStyleForms[] = { "Singular", "Dual", "Plural", 0 }; static const char * const czechForms[] = { "Singular", "Dual", "Plural", 0 }; static const char * const slovakForms[] = { "Singular", "Dual", "Plural", 0 }; static const char * const macedonianForms[] = { "Singular", "Dual", "Plural", 0 }; static const char * const lithuanianForms[] = { "Singular", "Dual", "Plural", 0 }; static const char * const russianStyleForms[] = { "Singular", "Dual", "Plural", 0 }; static const char * const polishForms[] = { "Singular", "Paucal", "Plural", 0 }; static const char * const romanianForms[] = { "Singular", "Plural Form for 2 to 19", "Plural", 0 }; static const char * const slovenianForms[] = { "Singular", "Dual", "Trial", "Plural", 0 }; static const char * const malteseForms[] = { "Singular", "Plural Form for 2 to 10", "Plural Form for 11 to 19", "Plural", 0 }; static const char * const welshForms[] = { "Nullar", "Singular", "Dual", "Sexal", "Plural", 0 }; static const char * const arabicForms[] = { "Nullar", "Singular", "Dual", "Minority Plural", "Plural", "Plural Form for 100, 200, ...", 0 }; #define EOL QLocale::C static const QLocale::Language japaneseStyleLanguages[] = { QLocale::Afan, QLocale::Armenian, QLocale::Bhutani, QLocale::Bislama, QLocale::Burmese, QLocale::Chinese, QLocale::FijiLanguage, QLocale::Guarani, QLocale::Hungarian, QLocale::Indonesian, QLocale::Japanese, QLocale::Javanese, QLocale::Korean, QLocale::Malay, QLocale::NauruLanguage, QLocale::Persian, QLocale::Sundanese, QLocale::Thai, QLocale::Tibetan, QLocale::Vietnamese, QLocale::Yoruba, QLocale::Zhuang, EOL }; static const QLocale::Language englishStyleLanguages[] = { QLocale::Abkhazian, QLocale::Afar, QLocale::Afrikaans, QLocale::Albanian, QLocale::Amharic, QLocale::Assamese, QLocale::Aymara, QLocale::Azerbaijani, QLocale::Bashkir, QLocale::Basque, QLocale::Bengali, QLocale::Bihari, // Missing: Bokmal, QLocale::Bulgarian, QLocale::Cambodian, QLocale::Catalan, QLocale::Cornish, QLocale::Corsican, QLocale::Danish, QLocale::Dutch, QLocale::English, QLocale::Esperanto, QLocale::Estonian, QLocale::Faroese, QLocale::Finnish, // Missing: Friulian, QLocale::Frisian, QLocale::Galician, QLocale::Georgian, QLocale::German, QLocale::Greek, QLocale::Greenlandic, QLocale::Gujarati, QLocale::Hausa, QLocale::Hebrew, QLocale::Hindi, QLocale::Icelandic, QLocale::Interlingua, QLocale::Interlingue, QLocale::Italian, QLocale::Kannada, QLocale::Kashmiri, QLocale::Kazakh, QLocale::Kinyarwanda, QLocale::Kirghiz, QLocale::Kurdish, QLocale::Kurundi, QLocale::Laothian, QLocale::Latin, // Missing: Letzeburgesch, QLocale::Lingala, QLocale::Malagasy, QLocale::Malayalam, QLocale::Marathi, QLocale::Mongolian, // Missing: Nahuatl, QLocale::Nepali, // Missing: Northern Sotho, QLocale::Norwegian, QLocale::Nynorsk, QLocale::Occitan, QLocale::Oriya, QLocale::Pashto, QLocale::Portuguese, QLocale::Punjabi, QLocale::Quechua, QLocale::RhaetoRomance, QLocale::Sesotho, QLocale::Setswana, QLocale::Shona, QLocale::Sindhi, QLocale::Singhalese, QLocale::Siswati, QLocale::Somali, QLocale::Spanish, QLocale::Swahili, QLocale::Swedish, QLocale::Tagalog, QLocale::Tajik, QLocale::Tamil, QLocale::Tatar, QLocale::Telugu, QLocale::TongaLanguage, QLocale::Tsonga, QLocale::Turkish, QLocale::Turkmen, QLocale::Twi, QLocale::Uigur, QLocale::Uzbek, QLocale::Volapuk, QLocale::Wolof, QLocale::Xhosa, QLocale::Yiddish, QLocale::Zulu, EOL }; static const QLocale::Language frenchStyleLanguages[] = { // keep synchronized with frenchStyleCountries QLocale::Breton, QLocale::French, QLocale::Portuguese, // Missing: Filipino, QLocale::Tigrinya, // Missing: Walloon EOL }; static const QLocale::Language latvianLanguage[] = { QLocale::Latvian, EOL }; static const QLocale::Language irishStyleLanguages[] = { QLocale::Divehi, QLocale::Gaelic, QLocale::Inuktitut, QLocale::Inupiak, QLocale::Irish, QLocale::Manx, QLocale::Maori, // Missing: Sami, QLocale::Samoan, QLocale::Sanskrit, EOL }; static const QLocale::Language czechLanguage[] = { QLocale::Czech, EOL }; static const QLocale::Language slovakLanguage[] = { QLocale::Slovak, EOL }; static const QLocale::Language macedonianLanguage[] = { QLocale::Macedonian, EOL }; static const QLocale::Language lithuanianLanguage[] = { QLocale::Lithuanian, EOL }; static const QLocale::Language russianStyleLanguages[] = { QLocale::Bosnian, QLocale::Byelorussian, QLocale::Croatian, QLocale::Russian, QLocale::Serbian, QLocale::SerboCroatian, QLocale::Ukrainian, EOL }; static const QLocale::Language polishLanguage[] = { QLocale::Polish, EOL }; static const QLocale::Language romanianLanguages[] = { QLocale::Moldavian, QLocale::Romanian, EOL }; static const QLocale::Language slovenianLanguage[] = { QLocale::Slovenian, EOL }; static const QLocale::Language malteseLanguage[] = { QLocale::Maltese, EOL }; static const QLocale::Language welshLanguage[] = { QLocale::Welsh, EOL }; static const QLocale::Language arabicLanguage[] = { QLocale::Arabic, EOL }; static const QLocale::Country frenchStyleCountries[] = { // keep synchronized with frenchStyleLanguages QLocale::AnyCountry, QLocale::AnyCountry, QLocale::Brazil, QLocale::AnyCountry }; struct NumerusTableEntry { const char * const *forms; const QLocale::Language *languages; const QLocale::Country *countries; }; static const NumerusTableEntry numerusTable[] = { { japaneseStyleForms, japaneseStyleLanguages, 0 }, { englishStyleForms, englishStyleLanguages, 0 }, { frenchStyleForms, frenchStyleLanguages, frenchStyleCountries }, { latvianForms, latvianLanguage, 0 }, { irishStyleForms, irishStyleLanguages, 0 }, { czechForms, czechLanguage, 0 }, { slovakForms, slovakLanguage, 0 }, { macedonianForms, macedonianLanguage, 0 }, { lithuanianForms, lithuanianLanguage, 0 }, { russianStyleForms, russianStyleLanguages, 0 }, { polishForms, polishLanguage, 0 }, { romanianForms, romanianLanguages, 0 }, { slovenianForms, slovenianLanguage, 0 }, { malteseForms, malteseLanguage, 0 }, { welshForms, welshLanguage, 0 }, { arabicForms, arabicLanguage, 0 } }; static const int NumerusTableSize = sizeof(numerusTable) / sizeof(numerusTable[0]); bool getNumerusInfo(QLocale::Language language, QLocale::Country country, QStringList *forms); #endif // TRANSLATOR_H Tools-0.2.15/pyrcc/000077500000000000000000000000001220335231500140135ustar00rootroot00000000000000Tools-0.2.15/pyrcc/CMakeLists.txt000066400000000000000000000010731220335231500165540ustar00rootroot00000000000000 add_executable(pyside-rcc main.cpp rcc.cpp) include_directories(pyside-rcc ${QT_INCLUDE_DIR} ${QT_QT_INCLUDE_DIR} ${QT_QTXML_INCLUDE_DIR} ${QT_QTCORE_INCLUDE_DIR}) target_link_libraries(pyside-rcc ${QT_QTCORE_LIBRARY} ${QT_QTXML_LIBRARY}) install(TARGETS pyside-rcc RUNTIME DESTINATION bin) # Man pages if (NOT win32) file(GLOB manpages "${CMAKE_CURRENT_SOURCE_DIR}/*.1") install(FILES ${manpages} DESTINATION share/man/man1) endif() Tools-0.2.15/pyrcc/main.cpp000066400000000000000000000150301220335231500154420ustar00rootroot00000000000000/* * This file is part of the PySide Tools project. * * Copyright (C) 1992-2005 Trolltech AS. All rights reserved. * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). * * Contact: PySide team * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #include #include #include #include #include #include #include #include #include #include "rcc.h" // Some static globals static QString initName; static bool verbose = false; static int py_version = 2; static int compressLevel = CONSTANT_COMPRESSLEVEL_DEFAULT; static int compressThreshold = CONSTANT_COMPRESSTHRESHOLD_DEFAULT; static QString resourceRoot; bool processResourceFile(const QStringList &filenamesIn, const QString &filenameOut, bool list) { if (verbose) fprintf(stderr, "PySide resource compiler\n"); //setup RCCResourceLibrary library; library.setInputFiles(filenamesIn); library.setInitName(initName); library.setVerbose(verbose); library.setPythonVersion(py_version); library.setCompressLevel(compressLevel); library.setCompressThreshold(compressThreshold); library.setResourceRoot(resourceRoot); if(!library.readFiles()) return false; //open output FILE *out_fd = stdout; if (!filenameOut.isEmpty() && filenameOut != QLatin1String("-")) { #if defined(_MSC_VER) && _MSC_VER >= 1400 if (fopen_s(&out_fd, filenameOut.toLocal8Bit().constData(), "w")) { #else out_fd = fopen(filenameOut.toLocal8Bit().constData(), "w"); if(!out_fd) { #endif fprintf(stderr, "Unable to open %s for writing\n", filenameOut.toLatin1().constData()); return false; } } //do the task bool ret = true; if(list) { const QStringList data = library.dataFiles(); for(int i = 0; i < data.size(); ++i) fprintf(out_fd, "%s\n", QDir::cleanPath(data.at(i)).toLatin1().constData()); } else { ret = library.output(out_fd); } if(out_fd != stdout) fclose(out_fd); //done return ret; } int showHelp(const char *argv0, const QString &error) { fprintf(stderr, "PySide resource compiler\n"); if (!error.isEmpty()) fprintf(stderr, "%s: %s\n", argv0, error.toLatin1().constData()); fprintf(stderr, "Usage: %s [options] \n\n" "Options:\n" " -o file Write output to file rather than stdout\n" " -py2 Generate code for any Python v2.x version (default)\n" " -py3 Generate code for any Python v3.x version\n" " -name name Create an external initialization function with name\n" " -threshold level Threshold to consider compressing files\n" " -compress level Compress input files by level\n" " -root path Prefix resource access path with root path\n" " -no-compress Disable all compression\n" " -version Display version\n" " -help Display this information\n", argv0); return 1; } int main(int argc, char *argv[]) { QString outFilename; bool helpRequested = false, list = false; QStringList files; //parse options QString errorMsg; for (int i = 1; i < argc && errorMsg.isEmpty(); i++) { if (argv[i][0] == '-') { // option QByteArray opt = argv[i] + 1; if (opt == "o") { if (!(i < argc-1)) { errorMsg = QLatin1String("Missing output name"); break; } outFilename = argv[++i]; } else if(opt == "name") { if (!(i < argc-1)) { errorMsg = QLatin1String("Missing target name"); break; } initName = argv[++i]; } else if(opt == "root") { if (!(i < argc-1)) { errorMsg = QLatin1String("Missing root path"); break; } resourceRoot = QDir::cleanPath(argv[++i]); if(resourceRoot.isEmpty() || resourceRoot[0] != '/') errorMsg = QLatin1String("Root must start with a /"); } else if(opt == "compress") { if (!(i < argc-1)) { errorMsg = QLatin1String("Missing compression level"); break; } compressLevel = QString(argv[++i]).toInt(); } else if(opt == "threshold") { if (!(i < argc-1)) { errorMsg = QLatin1String("Missing compression threshold"); break; } compressThreshold = QString(argv[++i]).toInt(); } else if(opt == "verbose") { verbose = true; } else if(opt == "py2") { py_version = 2; } else if(opt == "py3") { py_version = 3; } else if(opt == "list") { list = true; } else if(opt == "version") { fprintf(stderr, "Resource Compiler for Qt version %s\n", QT_VERSION_STR); return 1; } else if(opt == "help" || opt == "h") { helpRequested = true; } else if(opt == "no-compress") { compressLevel = -2; } else { errorMsg = QString(QLatin1String("Unknown option: '%1'")).arg(argv[i]); } } else { if(!QFile::exists(argv[i])) { qWarning("%s: File does not exist '%s'", argv[0], argv[i]); return 1; } files.append(argv[i]); } } if (!files.size() || !errorMsg.isEmpty() || helpRequested) return showHelp(argv[0], errorMsg); return int(!processResourceFile(files, outFilename, list)); } Tools-0.2.15/pyrcc/pyside-rcc.1000066400000000000000000000016741220335231500161470ustar00rootroot00000000000000.TH PYSIDE\-RCC "1" "December 2010" "pyside\-rcc" "User Commands" .SH NAME pyside\-rcc \- PySide resource compiler .SH DESCRIPTION .SS "Usage:" .IP pyside\-rcc [options] .SS "Options:" .TP \fB\-o\fR file Write output to file rather than stdout .TP \fB\-py2\fR Generate code for any Python v2.x version (default) .TP \fB\-py3\fR Generate code for any Python v3.x version .TP \fB\-name\fR name Create an external initialization function with name .TP \fB\-threshold\fR level Threshold to consider compressing files .TP \fB\-compress\fR level Compress input files by level .TP \fB\-root\fR path Prefix resource access path with root path .TP \fB\-no\-compress Disable all compression .TP \fB\-version Display version .TP \fB\-help Display this information .SH COPYRIGHT Copyright \(co 2010 Nokia Corporation and/or its subsidiary(\fB\-ies\fR) .SH AUTHOR .PP This manpage was written by Marcelo Lira , on the 29. December 2010. Tools-0.2.15/pyrcc/rcc.cpp000066400000000000000000000417151220335231500152760ustar00rootroot00000000000000/* * This file is part of the PySide Tools project. * * Copyright (C) 1992-2005 Trolltech AS. All rights reserved. * Copyright (C) 2009-2011 Nokia Corporation and/or its subsidiary(-ies). * * Contact: PySide team * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #include #include #include #include #include #include #include #include #include #include #include #include #include "rcc.h" static bool qt_rcc_write_number(FILE *out, quint32 number, int width) { int dividend = 1; switch (width) { case 2: dividend = 256; break; case 3: dividend = 65536; break; case 4: dividend = 16777216; break; default: break; } // Write bytes while (dividend >= 1) { const quint8 tmp = number / dividend; if (tmp >= 32 && tmp < 127 && tmp != '"' && tmp != '\\') { /* Optimization for printable characters */ fprintf(out, "%c", tmp); } else { fprintf(out, "\\x%02x", tmp); } number -= tmp * dividend; dividend /= 256; } return true; } bool RCCFileInfo::writeDataInfo(FILE *out) { //pointer data if(flags & RCCFileInfo::Directory) { //name offset qt_rcc_write_number(out, nameOffset, 4); //flags qt_rcc_write_number(out, flags, 2); //child count qt_rcc_write_number(out, children.size(), 4); //first child offset qt_rcc_write_number(out, childOffset, 4); } else { //name offset qt_rcc_write_number(out, nameOffset, 4); //flags qt_rcc_write_number(out, flags, 2); //locale qt_rcc_write_number(out, locale.country(), 2); qt_rcc_write_number(out, locale.language(), 2); //data offset qt_rcc_write_number(out, dataOffset, 4); } return true; } qint64 RCCFileInfo::writeDataBlob(FILE *out, qint64 offset) { //capture the offset dataOffset = offset; //find the data to be written QFile file(fileInfo.absoluteFilePath()); if (!file.open(QFile::ReadOnly)) { fprintf(stderr, "Couldn't open %s\n", fileInfo.absoluteFilePath().toLatin1().constData()); return false; } QByteArray data = file.readAll(); #ifndef QT_NO_COMPRESS // Check if compression is useful for this file if (mCompressLevel != 0 && data.size() != 0) { QByteArray compressed = qCompress(reinterpret_cast(data.data()), data.size(), mCompressLevel); int compressRatio = int(100.0f * (float(data.size() - compressed.size()) / float(data.size()))); if (compressRatio >= mCompressThreshold) { data = compressed; flags |= Compressed; } } #endif // QT_NO_COMPRESS //write the length qt_rcc_write_number(out, data.size(), 4); offset += 4; //write the payload for (int i=0; iroot == 0) { fprintf(stderr, "No resources in resource description.\n"); return false; } return true; } bool RCCResourceLibrary::addFile(const QString &alias, const RCCFileInfo &file) { if (file.fileInfo.size() > 0xffffffff) { fprintf(stderr, "File too big: %s", file.fileInfo.absoluteFilePath().toLatin1().constData()); return false; } if(!root) root = new RCCFileInfo("", QFileInfo(), QLocale(), RCCFileInfo::Directory); RCCFileInfo *parent = root; const QStringList nodes = alias.split('/'); for(int i = 1; i < nodes.size()-1; ++i) { const QString node = nodes.at(i); if(!parent->children.contains(node)) { RCCFileInfo *s = new RCCFileInfo(node, QFileInfo(), QLocale(), RCCFileInfo::Directory); s->parent = parent; parent->children.insert(node, s); parent = s; } else { parent = parent->children[node]; } } const QString filename = nodes.at(nodes.size()-1); RCCFileInfo *s = new RCCFileInfo(file); s->parent = parent; parent->children.insertMulti(filename, s); return true; } bool RCCResourceLibrary::readFiles() { //read in data if (mVerbose) fprintf(stderr, "Processing %d files\n", mFileNames.size()); for (int i=0; i pending; if (!root) return ret; pending.push(root); while(!pending.isEmpty()) { RCCFileInfo *file = pending.pop(); for(QHash::iterator it = file->children.begin(); it != file->children.end(); ++it) { RCCFileInfo *child = it.value(); if(child->flags & RCCFileInfo::Directory) pending.push(child); ret.append(child->fileInfo.filePath()); } } return ret; } bool RCCResourceLibrary::output(FILE *out) { //write out if (mVerbose) fprintf(stderr, "Outputting code\n"); if (!writeHeader(out)) { fprintf(stderr, "Couldn't write header\n"); return false; } if (!writeDataBlobs(out)) { fprintf(stderr, "Couldn't write data blob\n"); return false; } if (!writeDataNames(out)) { fprintf(stderr, "Couldn't write file names\n"); return false; } if (!writeDataStructure(out)) { fprintf(stderr, "Couldn't write data tree\n"); return false; } if (!writeInitializer(out)) { fprintf(stderr, "Couldn't write footer\n"); return false; } return true; } bool RCCResourceLibrary::writeHeader(FILE *out) { fprintf(out, "# -*- coding: utf-8 -*-\n\n"); fprintf(out, "# Resource object code\n"); fprintf(out, "#\n"); fprintf(out, "# Created: %s\n", QDateTime::currentDateTime().toString().toUtf8().constData()); fprintf(out, "# by: The Resource Compiler for PySide (Qt v%s)\n", QT_VERSION_STR); fprintf(out, "#\n"); fprintf(out, "# WARNING! All changes made in this file will be lost!\n"); fprintf(out, "\n"); fprintf(out, "from PySide import QtCore\n\n"); return true; } bool RCCResourceLibrary::writeDataBlobs(FILE *out) { fprintf(out, "qt_resource_data = %s\"", mPrefix); QStack pending; if (!root) return false; pending.push(root); qint64 offset = 0; while(!pending.isEmpty()) { RCCFileInfo *file = pending.pop(); for(QHash::iterator it = file->children.begin(); it != file->children.end(); ++it) { RCCFileInfo *child = it.value(); if(child->flags & RCCFileInfo::Directory) pending.push(child); else offset = child->writeDataBlob(out, offset); } } fprintf(out, "\"\n"); return true; } bool RCCResourceLibrary::writeDataNames(FILE *out) { fprintf(out, "qt_resource_name = %s\"", mPrefix); QHash names; QStack pending; if (!root) return false; pending.push(root); qint64 offset = 0; while(!pending.isEmpty()) { RCCFileInfo *file = pending.pop(); for(QHash::iterator it = file->children.begin(); it != file->children.end(); ++it) { RCCFileInfo *child = it.value(); if(child->flags & RCCFileInfo::Directory) pending.push(child); if(names.contains(child->name)) { child->nameOffset = names.value(child->name); } else { names.insert(child->name, offset); offset = child->writeDataName(out, offset); } } } fprintf(out, "\"\n"); return true; } static bool qt_rcc_compare_hash(const RCCFileInfo *left, const RCCFileInfo *right) { return qHash(left->name) < qHash(right->name); } bool RCCResourceLibrary::writeDataStructure(FILE *out) { fprintf(out, "qt_resource_struct = %s\"", mPrefix); QStack pending; if (!root) return false; //calculate the child offsets (flat) pending.push(root); int offset = 1; while(!pending.isEmpty()) { RCCFileInfo *file = pending.pop(); file->childOffset = offset; //sort by hash value for binary lookup QList children = file->children.values(); qSort(children.begin(), children.end(), qt_rcc_compare_hash); //write out the actual data now for(int i = 0; i < children.size(); ++i) { RCCFileInfo *child = children.at(i); ++offset; if(child->flags & RCCFileInfo::Directory) pending.push(child); } } //write out the structure (ie iterate again!) pending.push(root); root->writeDataInfo(out); while(!pending.isEmpty()) { RCCFileInfo *file = pending.pop(); //sort by hash value for binary lookup QList children = file->children.values(); qSort(children.begin(), children.end(), qt_rcc_compare_hash); //write out the actual data now for(int i = 0; i < children.size(); ++i) { RCCFileInfo *child = children.at(i); child->writeDataInfo(out); if(child->flags & RCCFileInfo::Directory) pending.push(child); } } fprintf(out, "\"\n"); return true; } bool RCCResourceLibrary::writeInitializer(FILE *out) { fprintf(out, "def qInitResources():\n"); fprintf(out, " QtCore.qRegisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data)\n"); fprintf(out, "\n"); fprintf(out, "def qCleanupResources():\n"); fprintf(out, " QtCore.qUnregisterResourceData(0x01, qt_resource_struct, qt_resource_name, qt_resource_data)\n"); fprintf(out, "\n"); fprintf(out, "qInitResources()\n"); return true; } Tools-0.2.15/pyrcc/rcc.h000066400000000000000000000111251220335231500147330ustar00rootroot00000000000000/* * This file is part of the PySide Tools project. * * Copyright (C) 1992-2005 Trolltech AS. All rights reserved. * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). * * Contact: PySide team * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ #ifndef RCC_H #define RCC_H #define TAG_RCC "RCC" #define TAG_RESOURCE "qresource" #define TAG_FILE "file" #define ATTRIBUTE_LANG "lang" #define ATTRIBUTE_PREFIX "prefix" #define ATTRIBUTE_ALIAS "alias" #define ATTRIBUTE_THRESHOLD "threshold" #define ATTRIBUTE_COMPRESS "compress" #define CONSTANT_HEADER_SIZE 8 #define CONSTANT_COMPRESSLEVEL_DEFAULT 0 #define CONSTANT_COMPRESSTHRESHOLD_DEFAULT 70 struct RCCFileInfo; class RCCResourceLibrary { public: inline RCCResourceLibrary(); ~RCCResourceLibrary(); bool output(FILE *out); bool readFiles(); inline void setInputFiles(QStringList files) { mFileNames = files; } inline QStringList inputFiles() const { return mFileNames; } QStringList dataFiles() const; inline void setVerbose(bool b) { mVerbose = b; } inline bool verbose() const { return mVerbose; } inline void setPythonVersion(int v) { mPrefix = (v == 2 ? "" : "b"); } inline void setInitName(const QString &n) { mInitName = n; } inline QString initName() const { return mInitName; } inline void setCompressLevel(int c) { mCompressLevel = c; } inline int compressLevel() const { return mCompressLevel; } inline void setCompressThreshold(int t) { mCompressThreshold = t; } inline int compressThreshold() const { return mCompressThreshold; } inline void setResourceRoot(QString str) { mResourceRoot = str; } inline QString resourceRoot() const { return mResourceRoot; } private: RCCFileInfo *root; bool addFile(const QString &alias, const RCCFileInfo &file); bool interpretResourceFile(QIODevice *inputDevice, QString file, QString currentPath = QString()); bool writeHeader(FILE *out); bool writeDataBlobs(FILE *out); bool writeDataNames(FILE *out); bool writeDataStructure(FILE *out); bool writeInitializer(FILE *out); QStringList mFileNames; QString mResourceRoot, mInitName; bool mVerbose; int mCompressLevel; int mCompressThreshold; int mTreeOffset, mNamesOffset, mDataOffset; const char *mPrefix; }; inline RCCResourceLibrary::RCCResourceLibrary() { root = 0; mVerbose = false; mCompressLevel = -1; mCompressThreshold = 70; mTreeOffset = mNamesOffset = mDataOffset = 0; } struct RCCFileInfo { enum Flags { NoFlags = 0x00, Compressed = 0x01, Directory = 0x02 }; inline RCCFileInfo(QString name = QString(), QFileInfo fileInfo = QFileInfo(), QLocale locale = QLocale(), uint flags = NoFlags, int compressLevel = CONSTANT_COMPRESSLEVEL_DEFAULT, int compressThreshold = CONSTANT_COMPRESSTHRESHOLD_DEFAULT); ~RCCFileInfo() { qDeleteAll(children); } inline QString resourceName() { QString resource = name; for(RCCFileInfo *p = parent; p; p = p->parent) resource = resource.prepend(p->name + "/"); return ":" + resource; } int flags; QString name; QLocale locale; QFileInfo fileInfo; RCCFileInfo *parent; QHash children; int mCompressLevel; int mCompressThreshold; qint64 nameOffset, dataOffset, childOffset; qint64 writeDataBlob(FILE *out, qint64 offset); qint64 writeDataName(FILE *out, qint64 offset); bool writeDataInfo(FILE *out); }; inline RCCFileInfo::RCCFileInfo(QString name, QFileInfo fileInfo, QLocale locale, uint flags, int compressLevel, int compressThreshold) { this->name = name; this->fileInfo = fileInfo; this->locale = locale; this->flags = flags; this->parent = 0; this->nameOffset = this->dataOffset = this->childOffset = 0; this->mCompressLevel = compressLevel; this->mCompressThreshold = compressThreshold; } #endif Tools-0.2.15/pyside-uic000066400000000000000000000053611220335231500146760ustar00rootroot00000000000000#!/usr/bin/env python # This file is part of the PySide project. # # Copyright (C) 2009-2011 Nokia Corporation and/or its subsidiary(-ies). # Copyright (C) 2010 Riverbank Computing Limited. # Copyright (C) 2009 Torsten Marek # # Contact: PySide team # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # version 2 as published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA # 02110-1301 USA import sys import optparse from PySide import QtCore from pysideuic.driver import Driver from PySide import __version__ as PySideVersion from pysideuic import __version__ as PySideUicVersion Version = "PySide User Interface Compiler version %s, running on PySide %s." % (PySideUicVersion, PySideVersion) def main(): if sys.hexversion >= 0x03000000: from pysideuic.port_v3.invoke import invoke else: from pysideuic.port_v2.invoke import invoke parser = optparse.OptionParser(usage="pyside-uic [options] ", version=Version) parser.add_option("-p", "--preview", dest="preview", action="store_true", default=False, help="show a preview of the UI instead of generating code") parser.add_option("-o", "--output", dest="output", default="-", metavar="FILE", help="write generated code to FILE instead of stdout") parser.add_option("-x", "--execute", dest="execute", action="store_true", default=False, help="generate extra code to test and display the class") parser.add_option("-d", "--debug", dest="debug", action="store_true", default=False, help="show debug output") parser.add_option("-i", "--indent", dest="indent", action="store", type="int", default=4, metavar="N", help="set indent width to N spaces, tab if N is 0 (default: 4)") g = optparse.OptionGroup(parser, title="Code generation options") g.add_option("--from-imports", dest="from_imports", action="store_true", default=False, help="generate imports relative to '.'") parser.add_option_group(g) opts, args = parser.parse_args() if len(args) != 1: sys.stderr.write("Error: one input ui-file must be specified\n") sys.exit(1) sys.exit(invoke(Driver(opts, args[0]))) if __name__ == "__main__": main() Tools-0.2.15/pysideuic/000077500000000000000000000000001220335231500146715ustar00rootroot00000000000000Tools-0.2.15/pysideuic/Compiler/000077500000000000000000000000001220335231500164435ustar00rootroot00000000000000Tools-0.2.15/pysideuic/Compiler/__init__.py000066400000000000000000000015661220335231500205640ustar00rootroot00000000000000# This file is part of the PySide project. # # Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). # Copyright (C) 2009 Riverbank Computing Limited. # Copyright (C) 2009 Torsten Marek # # Contact: PySide team # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # version 2 as published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA # 02110-1301 USA Tools-0.2.15/pysideuic/Compiler/compiler.py000066400000000000000000000065521220335231500206370ustar00rootroot00000000000000# This file is part of the PySide project. # # Copyright (C) 2009-2011 Nokia Corporation and/or its subsidiary(-ies). # Copyright (C) 2010 Riverbank Computing Limited. # Copyright (C) 2009 Torsten Marek # # Contact: PySide team # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # version 2 as published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA # 02110-1301 USA import sys from pysideuic.properties import Properties from pysideuic.uiparser import UIParser from pysideuic.Compiler import qtproxies from pysideuic.Compiler.indenter import createCodeIndenter, getIndenter, \ write_code from pysideuic.Compiler.qobjectcreator import CompilerCreatorPolicy from pysideuic.Compiler.misc import write_import class UICompiler(UIParser): def __init__(self): UIParser.__init__(self, qtproxies.QtCore, qtproxies.QtGui, CompilerCreatorPolicy()) def reset(self): qtproxies.i18n_strings = [] UIParser.reset(self) def setContext(self, context): qtproxies.i18n_context = context def createToplevelWidget(self, classname, widgetname): indenter = getIndenter() indenter.level = 0 indenter.write("from PySide import QtCore, QtGui") indenter.write("") indenter.write("class Ui_%s(object):" % self.uiname) indenter.indent() indenter.write("def setupUi(self, %s):" % widgetname) indenter.indent() w = self.factory.createQObject(classname, widgetname, (), is_attribute = False, no_instantiation = True) w.baseclass = classname w.uiclass = "Ui_%s" % self.uiname return w def setDelayedProps(self): write_code("") write_code("self.retranslateUi(%s)" % self.toplevelWidget) UIParser.setDelayedProps(self) def finalize(self): indenter = getIndenter() indenter.level = 1 indenter.write("") indenter.write("def retranslateUi(self, %s):" % self.toplevelWidget) indenter.indent() if qtproxies.i18n_strings: for s in qtproxies.i18n_strings: indenter.write(s) else: indenter.write("pass") indenter.dedent() indenter.dedent() # Make a copy of the resource modules to import because the parser will # reset() before returning. self._resources = self.resources def compileUi(self, input_stream, output_stream, from_imports): createCodeIndenter(output_stream) w = self.parse(input_stream) indenter = getIndenter() indenter.write("") self.factory._cpolicy._writeOutImports() for res in self._resources: write_import(res, from_imports) return {"widgetname": str(w), "uiclass" : w.uiclass, "baseclass" : w.baseclass} Tools-0.2.15/pysideuic/Compiler/indenter.py000066400000000000000000000032121220335231500206230ustar00rootroot00000000000000# This file is part of the PySide project. # # Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). # Copyright (C) 2009 Riverbank Computing Limited. # Copyright (C) 2009 Torsten Marek # # Contact: PySide team # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # version 2 as published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA # 02110-1301 USA indentwidth = 4 _indenter = None class _IndentedCodeWriter(object): def __init__(self, output): self.level = 0 self.output = output def indent(self): self.level += 1 def dedent(self): self.level -= 1 def write(self, line): if line.strip(): if indentwidth > 0: indent = " " * indentwidth line = line.replace("\t", indent) else: indent = "\t" self.output.write("%s%s\n" % (indent * self.level, line)) else: self.output.write("\n") def createCodeIndenter(output): global _indenter _indenter = _IndentedCodeWriter(output) def getIndenter(): return _indenter def write_code(string): _indenter.write(string) Tools-0.2.15/pysideuic/Compiler/misc.py000066400000000000000000000030061220335231500177470ustar00rootroot00000000000000# This file is part of the PySide project. # # Copyright (C) 2009-2011 Nokia Corporation and/or its subsidiary(-ies). # Copyright (C) 2010 Riverbank Computing Limited. # Copyright (C) 2009 Torsten Marek # # Contact: PySide team # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # version 2 as published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA # 02110-1301 USA from pysideuic.Compiler.indenter import write_code def write_import(module_name, from_imports): if from_imports: write_code("from . import %s" % module_name) else: write_code("import %s" % module_name) def moduleMember(module, name): if module: return "%s.%s" % (module, name) return name class Literal(object): """Literal(string) -> new literal string will not be quoted when put into an argument list""" def __init__(self, string): self.string = string def __str__(self): return self.string def __or__(self, r_op): return Literal("%s|%s" % (self, r_op)) Tools-0.2.15/pysideuic/Compiler/proxy_type.py000066400000000000000000000041301220335231500212350ustar00rootroot00000000000000# This file is part of the PySide project. # # Copyright (C) 2009-2011 Nokia Corporation and/or its subsidiary(-ies). # Copyright (C) 2010 Riverbank Computing Limited. # Copyright (C) 2009 Torsten Marek # # Contact: PySide team # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # version 2 as published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA # 02110-1301 USA from pysideuic.Compiler.misc import Literal, moduleMember class ProxyType(type): def __init__(*args): type.__init__(*args) for cls in args[0].__dict__.values(): if type(cls) is ProxyType: cls.module = args[0].__name__ if not hasattr(args[0], "module"): args[0].module = "" def __getattribute__(cls, name): try: return type.__getattribute__(cls, name) except AttributeError: # Handle internal (ie. non-PySide) attributes as normal. if name == "module": raise # Avoid a circular import. from pysideuic.Compiler.qtproxies import LiteralProxyClass return type(name, (LiteralProxyClass, ), {"module": moduleMember(type.__getattribute__(cls, "module"), type.__getattribute__(cls, "__name__"))}) def __str__(cls): return moduleMember(type.__getattribute__(cls, "module"), type.__getattribute__(cls, "__name__")) def __or__(self, r_op): return Literal("%s|%s" % (self, r_op)) def __eq__(self, other): return str(self) == str(other) Tools-0.2.15/pysideuic/Compiler/qobjectcreator.py000066400000000000000000000106071220335231500220300ustar00rootroot00000000000000# This file is part of the PySide project. # # Copyright (C) 2009-2011 Nokia Corporation and/or its subsidiary(-ies). # Copyright (C) 2010 Riverbank Computing Limited. # Copyright (C) 2009 Torsten Marek # # Contact: PySide team # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # version 2 as published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA # 02110-1301 USA import logging try: set() except NameError: from sets import Set as set from pysideuic.Compiler.indenter import write_code from pysideuic.Compiler.qtproxies import QtGui, Literal, strict_getattr logger = logging.getLogger(__name__) DEBUG = logger.debug class _QtGuiWrapper(object): def search(clsname): try: return strict_getattr(QtGui, clsname) except AttributeError: return None search = staticmethod(search) class _ModuleWrapper(object): def __init__(self, name, classes): if "." in name: idx = name.rfind(".") self._package = name[:idx] self._module = name[idx + 1:] else: self._package = None self._module = name self._classes = set(classes) self._used = False def search(self, cls): if cls in self._classes: self._used = True return type(cls, (QtGui.QWidget,), {"module": self._module}) else: return None def _writeImportCode(self): if self._used: if self._package is None: write_code("import %s" % self._module) else: write_code("from %s import %s" % (self._package, self._module)) class _CustomWidgetLoader(object): def __init__(self): self._widgets = {} self._usedWidgets = set() def addCustomWidget(self, widgetClass, baseClass, module): assert widgetClass not in self._widgets self._widgets[widgetClass] = (baseClass, module) def _resolveBaseclass(self, baseClass): try: for x in range(0, 10): try: return strict_getattr(QtGui, baseClass) except AttributeError: pass baseClass = self._widgets[baseClass][0] else: raise ValueError("baseclass resolve took too long, check custom widgets") except KeyError: raise ValueError("unknown baseclass %s" % baseClass) def search(self, cls): try: self._usedWidgets.add(cls) baseClass = self._resolveBaseclass(self._widgets[cls][0]) DEBUG("resolved baseclass of %s: %s" % (cls, baseClass)) return type(cls, (baseClass,), {"module" : ""}) except KeyError: return None def _writeImportCode(self): imports = {} for widget in self._usedWidgets: _, module = self._widgets[widget] imports.setdefault(module, []).append(widget) for module, classes in imports.items(): write_code("from %s import %s" % (module, ", ".join(classes))) class CompilerCreatorPolicy(object): def __init__(self): self._modules = [] def createQtGuiWrapper(self): return _QtGuiWrapper def createModuleWrapper(self, name, classes): mw = _ModuleWrapper(name, classes) self._modules.append(mw) return mw def createCustomWidgetLoader(self): cw = _CustomWidgetLoader() self._modules.append(cw) return cw def instantiate(self, clsObject, objectname, ctor_args, is_attribute=True, no_instantiation=False): return clsObject(objectname, is_attribute, ctor_args, no_instantiation) def invoke(self, rname, method, args): return method(rname, *args) def getSlot(self, object, slotname): return Literal("%s.%s" % (object, slotname)) def _writeOutImports(self): for module in self._modules: module._writeImportCode() Tools-0.2.15/pysideuic/Compiler/qtproxies.py000066400000000000000000000331401220335231500210540ustar00rootroot00000000000000# This file is part of the PySide project. # # Copyright (C) 2009-2011 Nokia Corporation and/or its subsidiary(-ies). # Copyright (C) 2010 Riverbank Computing Limited. # Copyright (C) 2009 Torsten Marek # # Contact: PySide team # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # version 2 as published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA # 02110-1301 USA import sys import re from pysideuic.Compiler.indenter import write_code from pysideuic.Compiler.misc import Literal, moduleMember if sys.hexversion >= 0x03000000: from pysideuic.port_v3.proxy_base import ProxyBase from pysideuic.port_v3.as_string import as_string else: from pysideuic.port_v2.proxy_base import ProxyBase from pysideuic.port_v2.as_string import as_string i18n_strings = [] i18n_context = "" def i18n_print(string): i18n_strings.append(string) def i18n_void_func(name): def _printer(self, *args): i18n_print("%s.%s(%s)" % (self, name, ", ".join(map(as_string, args)))) return _printer def i18n_func(name): def _printer(self, rname, *args): i18n_print("%s = %s.%s(%s)" % (rname, self, name, ", ".join(map(as_string, args)))) return Literal(rname) return _printer def strict_getattr(module, clsname): cls = getattr(module, clsname) if issubclass(cls, LiteralProxyClass): raise AttributeError(cls) else: return cls class i18n_string(object): def __init__(self, string, disambig): self.string = string self.disambig = disambig def __str__(self): if self.disambig is None: disambig = "None" else: disambig = as_string(self.disambig, encode=False) return 'QtGui.QApplication.translate("%s", %s, %s, QtGui.QApplication.UnicodeUTF8)' % (i18n_context, as_string(self.string, encode=False), disambig) # Classes with this flag will be handled as literal values. If functions are # called on these classes, the literal value changes. # Example: # the code # >>> QSize(9,10).expandedTo(...) # will print just that code. AS_ARGUMENT = 2 # ATTENTION: currently, classes can either be literal or normal. If a class # should need both kinds of behaviour, the code has to be changed. class ProxyClassMember(object): def __init__(self, proxy, function_name, flags): self.proxy = proxy self.function_name = function_name self.flags = flags def __str__(self): return "%s.%s" % (self.proxy, self.function_name) def __call__(self, *args): func_call = "%s.%s(%s)" % (self.proxy, self.function_name, ", ".join(map(as_string, args))) if self.flags & AS_ARGUMENT: self.proxy._uic_name = func_call return self.proxy else: needs_translation = False for arg in args: if isinstance(arg, i18n_string): needs_translation = True if needs_translation: i18n_print(func_call) else: write_code(func_call) class ProxyClass(ProxyBase): flags = 0 def __init__(self, objectname, is_attribute, args=(), noInstantiation=False): if objectname: if is_attribute: objectname = "self." + objectname self._uic_name = objectname else: self._uic_name = "Unnamed" if not noInstantiation: funcall = "%s(%s)" % \ (moduleMember(self.module, self.__class__.__name__), ", ".join(map(str, args))) if objectname: funcall = "%s = %s" % (objectname, funcall) write_code(funcall) def __str__(self): return self._uic_name def __getattribute__(self, attribute): try: return object.__getattribute__(self, attribute) except AttributeError: return ProxyClassMember(self, attribute, self.flags) class LiteralProxyClass(ProxyClass): """LiteralObject(*args) -> new literal class a literal class can be used as argument in a function call >>> class Foo(LiteralProxyClass): pass >>> str(Foo(1,2,3)) == "Foo(1,2,3)" """ flags = AS_ARGUMENT def __init__(self, *args): self._uic_name = "%s(%s)" % \ (moduleMember(self.module, self.__class__.__name__), ", ".join(map(as_string, args))) class ProxyNamespace(ProxyBase): pass # These are all the Qt classes used by pyuic4 in their namespaces. If a class # is missing, the compiler will fail, normally with an AttributeError. # # For adding new classes: # - utility classes used as literal values do not need to be listed # because they are created on the fly as subclasses of LiteralProxyClass # - classes which are *not* QWidgets inherit from ProxyClass and they # have to be listed explicitly in the correct namespace. These classes # are created via a ProxyQObjectCreator # - new QWidget-derived classes have to inherit from qtproxies.QWidget # If the widget does not need any special methods, it can be listed # in _qwidgets class QtCore(ProxyNamespace): class Qt(ProxyNamespace): pass ## connectSlotsByName and connect have to be handled as class methods, ## otherwise they would be created as LiteralProxyClasses and never be ## printed class QMetaObject(ProxyClass): def connectSlotsByName(cls, *args): ProxyClassMember(cls, "connectSlotsByName", 0)(*args) connectSlotsByName = classmethod(connectSlotsByName) class QObject(ProxyClass): def metaObject(self): class _FakeMetaObject(object): def className(*args): return self.__class__.__name__ return _FakeMetaObject() def objectName(self): return self._uic_name.split(".")[-1] def connect(cls, *args): # Handle slots that have names corresponding to Python keywords. slot_name = str(args[-1]) if slot_name.endswith('.raise'): args = list(args[:-1]) args.append(Literal(slot_name + '_')) ProxyClassMember(cls, "connect", 0)(*args) connect = classmethod(connect) # These sub-class QWidget but aren't themselves sub-classed. _qwidgets = ("QCalendarWidget", "QDialogButtonBox", "QDockWidget", "QGroupBox", "QLineEdit", "QMainWindow", "QMenuBar", "QProgressBar", "QStatusBar", "QToolBar", "QWizardPage") class QtGui(ProxyNamespace): class QApplication(QtCore.QObject): def translate(uiname, text, disambig, encoding): return i18n_string(text or "", disambig) translate = staticmethod(translate) class QIcon(ProxyClass): pass class QConicalGradient(ProxyClass): pass class QLinearGradient(ProxyClass): pass class QRadialGradient(ProxyClass): pass class QBrush(ProxyClass): pass class QPainter(ProxyClass): pass class QPalette(ProxyClass): pass class QFont(ProxyClass): pass class QSpacerItem(ProxyClass): pass class QSizePolicy(ProxyClass): pass ## QActions inherit from QObject for the metaobject stuff ## and the hierarchy has to be correct since we have a ## isinstance(x, QtGui.QLayout) call in the ui parser class QAction(QtCore.QObject): pass class QActionGroup(QtCore.QObject): pass class QButtonGroup(QtCore.QObject): pass class QLayout(QtCore.QObject): def setMargin(self, v): ProxyClassMember(self, "setContentsMargins", 0)(v, v, v, v); class QGridLayout(QLayout): pass class QBoxLayout(QLayout): pass class QHBoxLayout(QBoxLayout): pass class QVBoxLayout(QBoxLayout): pass class QFormLayout(QLayout): pass class QWidget(QtCore.QObject): def font(self): return Literal("%s.font()" % self) def minimumSizeHint(self): return Literal("%s.minimumSizeHint()" % self) def sizePolicy(self): sp = LiteralProxyClass() sp._uic_name = "%s.sizePolicy()" % self return sp class QDialog(QWidget): pass class QWizard(QDialog): pass class QAbstractSlider(QWidget): pass class QDial(QAbstractSlider): pass class QScrollBar(QAbstractSlider): pass class QSlider(QAbstractSlider): pass class QMenu(QWidget): def menuAction(self): return Literal("%s.menuAction()" % self) class QTabWidget(QWidget): def addTab(self, *args): text = args[-1] if isinstance(text, i18n_string): i18n_print("%s.setTabText(%s.indexOf(%s), %s)" % \ (self._uic_name, self._uic_name, args[0], text)) args = args[:-1] + ("", ) ProxyClassMember(self, "addTab", 0)(*args) def indexOf(self, page): return Literal("%s.indexOf(%s)" % (self, page)) class QComboBox(QWidget): pass class QFontComboBox(QComboBox): pass class QAbstractSpinBox(QWidget): pass class QDoubleSpinBox(QAbstractSpinBox): pass class QSpinBox(QAbstractSpinBox): pass class QDateTimeEdit(QAbstractSpinBox): pass class QDateEdit(QDateTimeEdit): pass class QTimeEdit(QDateTimeEdit): pass class QFrame(QWidget): pass class QLabel(QFrame): pass class QLCDNumber(QFrame): pass class QSplitter(QFrame): pass class QStackedWidget(QFrame): pass class QToolBox(QFrame): def addItem(self, *args): text = args[-1] if isinstance(text, i18n_string): i18n_print("%s.setItemText(%s.indexOf(%s), %s)" % \ (self._uic_name, self._uic_name, args[0], text)) args = args[:-1] + ("", ) ProxyClassMember(self, "addItem", 0)(*args) def indexOf(self, page): return Literal("%s.indexOf(%s)" % (self, page)) def layout(self): return QtGui.QLayout("%s.layout()" % self, False, (), noInstantiation=True) class QAbstractScrollArea(QFrame): pass class QGraphicsView(QAbstractScrollArea): pass class QMdiArea(QAbstractScrollArea): pass class QPlainTextEdit(QAbstractScrollArea): pass class QScrollArea(QAbstractScrollArea): pass class QTextEdit(QAbstractScrollArea): pass class QTextBrowser(QTextEdit): pass class QAbstractItemView(QAbstractScrollArea): pass class QColumnView(QAbstractItemView): pass class QHeaderView(QAbstractItemView): pass class QListView(QAbstractItemView): pass class QTableView(QAbstractItemView): def horizontalHeader(self): return QtGui.QHeaderView("%s.horizontalHeader()" % self, False, (), noInstantiation=True) def verticalHeader(self): return QtGui.QHeaderView("%s.verticalHeader()" % self, False, (), noInstantiation=True) class QTreeView(QAbstractItemView): def header(self): return QtGui.QHeaderView("%s.header()" % self, False, (), noInstantiation=True) class QListWidgetItem(ProxyClass): pass class QListWidget(QListView): isSortingEnabled = i18n_func("isSortingEnabled") setSortingEnabled = i18n_void_func("setSortingEnabled") def item(self, row): return QtGui.QListWidgetItem("%s.item(%i)" % (self, row), False, (), noInstantiation=True) class QTableWidgetItem(ProxyClass): pass class QTableWidget(QTableView): isSortingEnabled = i18n_func("isSortingEnabled") setSortingEnabled = i18n_void_func("setSortingEnabled") def item(self, row, col): return QtGui.QTableWidgetItem("%s.item(%i, %i)" % (self, row, col), False, (), noInstantiation=True) def horizontalHeaderItem(self, col): return QtGui.QTableWidgetItem("%s.horizontalHeaderItem(%i)" % (self, col), False, (), noInstantiation=True) def verticalHeaderItem(self, row): return QtGui.QTableWidgetItem("%s.verticalHeaderItem(%i)" % (self, row), False, (), noInstantiation=True) class QTreeWidgetItem(ProxyClass): def child(self, index): return QtGui.QTreeWidgetItem("%s.child(%i)" % (self, index), False, (), noInstantiation=True) class QTreeWidget(QTreeView): isSortingEnabled = i18n_func("isSortingEnabled") setSortingEnabled = i18n_void_func("setSortingEnabled") def headerItem(self): return QtGui.QWidget("%s.headerItem()" % self, False, (), noInstantiation=True) def topLevelItem(self, index): return QtGui.QTreeWidgetItem("%s.topLevelItem(%i)" % (self, index), False, (), noInstantiation=True) class QAbstractButton(QWidget): pass class QCheckBox(QAbstractButton): pass class QRadioButton(QAbstractButton): pass class QToolButton(QAbstractButton): pass class QPushButton(QAbstractButton): pass class QCommandLinkButton(QPushButton): pass # Add all remaining classes. for _class in _qwidgets: if _class not in locals(): locals()[_class] = type(_class, (QWidget, ), {}) Tools-0.2.15/pysideuic/__init__.py.in000066400000000000000000000116201220335231500174070ustar00rootroot00000000000000# This file is part of the PySide project. # # Copyright (C) 2009-2011 Nokia Corporation and/or its subsidiary(-ies). # Copyright (C) 2010 Riverbank Computing Limited. # Copyright (C) 2009 Torsten Marek # # Contact: PySide team # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # version 2 as published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA # 02110-1301 USA __all__ = ("compileUi", "compileUiDir", "widgetPluginPath") __version__ = "@pyside_tools_VERSION@" from pysideuic.Compiler import indenter, compiler _header = """# -*- coding: utf-8 -*- # Form implementation generated from reading ui file '%s' # # Created: %s # by: pyside-uic %s running on PySide %s # # WARNING! All changes made in this file will be lost! """ _display_code = """ if __name__ == "__main__": \timport sys \tapp = QtGui.QApplication(sys.argv) \t%(widgetname)s = QtGui.%(baseclass)s() \tui = %(uiclass)s() \tui.setupUi(%(widgetname)s) \t%(widgetname)s.show() \tsys.exit(app.exec_()) """ def compileUiDir(dir, recurse=False, map=None, **compileUi_args): """compileUiDir(dir, recurse=False, map=None, **compileUi_args) Creates Python modules from Qt Designer .ui files in a directory or directory tree. dir is the name of the directory to scan for files whose name ends with '.ui'. By default the generated Python module is created in the same directory ending with '.py'. recurse is set if any sub-directories should be scanned. The default is False. map is an optional callable that is passed the name of the directory containing the '.ui' file and the name of the Python module that will be created. The callable should return a tuple of the name of the directory in which the Python module will be created and the (possibly modified) name of the module. The default is None. compileUi_args are any additional keyword arguments that are passed to the compileUi() function that is called to create each Python module. """ import os # Compile a single .ui file. def compile_ui(ui_dir, ui_file): # Ignore if it doesn't seem to be a .ui file. if ui_file.endswith('.ui'): py_dir = ui_dir py_file = ui_file[:-3] + '.py' # Allow the caller to change the name of the .py file or generate # it in a different directory. if map is not None: py_dir, py_file = map(py_dir, py_file) # Make sure the destination directory exists. try: os.makedirs(py_dir) except: pass ui_path = os.path.join(ui_dir, ui_file) py_path = os.path.join(py_dir, py_file) ui_file = open(ui_path, 'r') py_file = open(py_path, 'w') try: compileUi(ui_file, py_file, **compileUi_args) finally: ui_file.close() py_file.close() if recurse: for root, _, files in os.walk(dir): for ui in files: compile_ui(root, ui) else: for ui in os.listdir(dir): if os.path.isfile(os.path.join(dir, ui)): compile_ui(dir, ui) def compileUi(uifile, pyfile, execute=False, indent=4, from_imports=False): """compileUi(uifile, pyfile, execute=False, indent=4, from_imports=False) Creates a Python module from a Qt Designer .ui file. uifile is a file name or file-like object containing the .ui file. pyfile is the file-like object to which the Python code will be written to. execute is optionally set to generate extra Python code that allows the code to be run as a standalone application. The default is False. indent is the optional indentation width using spaces. If it is 0 then a tab is used. The default is 4. from_imports is optionally set to generate import statements that are relative to '.'. """ from time import ctime import PySide try: uifname = uifile.name except AttributeError: uifname = uifile indenter.indentwidth = indent global PySideToolsVersion pyfile.write(_header % (uifname, ctime(), __version__, PySide.__version__)) winfo = compiler.UICompiler().compileUi(uifile, pyfile, from_imports) if execute: indenter.write_code(_display_code % winfo) # The list of directories that are searched for widget plugins. from pysideuic.objcreator import widgetPluginPath Tools-0.2.15/pysideuic/driver.py000066400000000000000000000076261220335231500165510ustar00rootroot00000000000000# This file is part of the PySide project. # # Copyright (C) 2009-2011 Nokia Corporation and/or its subsidiary(-ies). # Copyright (C) 2010 Riverbank Computing Limited. # Copyright (C) 2009 Torsten Marek # # Contact: PySide team # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # version 2 as published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA # 02110-1301 USA import sys import logging from pysideuic import compileUi class Driver(object): """ This encapsulates access to the pyuic functionality so that it can be called by code that is Python v2/v3 specific. """ LOGGER_NAME = 'PySide.uic' def __init__(self, opts, ui_file): """ Initialise the object. opts is the parsed options. ui_file is the name of the .ui file. """ if opts.debug: logger = logging.getLogger(self.LOGGER_NAME) handler = logging.StreamHandler() handler.setFormatter(logging.Formatter("%(name)s: %(message)s")) logger.addHandler(handler) logger.setLevel(logging.DEBUG) self._opts = opts self._ui_file = ui_file def invoke(self): """ Invoke the action as specified by the parsed options. Returns 0 if there was no error. """ if self._opts.preview: return self._preview() self._generate() return 0 def _preview(self): """ Preview the .ui file. Return the exit status to be passed back to the parent process. """ from PySide import QtUiTools from PySide import QtGui app = QtGui.QApplication([self._ui_file]) widget = QtUiTools.QUiLoader().load(self._ui_file) widget.show() return app.exec_() def _generate(self): """ Generate the Python code. """ if sys.hexversion >= 0x03000000: if self._opts.output == '-': from io import TextIOWrapper pyfile = TextIOWrapper(sys.stdout.buffer, encoding='utf8') else: pyfile = open(self._opts.output, 'wt', encoding='utf8') else: if self._opts.output == '-': pyfile = sys.stdout else: pyfile = open(self._opts.output, 'wt') compileUi(self._ui_file, pyfile, self._opts.execute, self._opts.indent, self._opts.from_imports) def on_IOError(self, e): """ Handle an IOError exception. """ sys.stderr.write("Error: %s: \"%s\"\n" % (e.strerror, e.filename)) def on_SyntaxError(self, e): """ Handle a SyntaxError exception. """ sys.stderr.write("Error in input file: %s\n" % e) def on_NoSuchWidgetError(self, e): """ Handle a NoSuchWidgetError exception. """ if e.args[0].startswith("Q3"): sys.stderr.write("Error: Q3Support widgets are not supported by PySide.\n") else: sys.stderr.write(str(e) + "\n") def on_Exception(self, e): """ Handle a generic exception. """ if logging.getLogger(self.LOGGER_NAME).level == logging.DEBUG: import traceback traceback.print_exception(*sys.exc_info()) else: from PySide import QtCore sys.stderr.write("""An unexpected error occurred. Check that you are using the latest version of PySide and report the error to http://bugs.openbossa.org, including the ui file used to trigger the error. """) Tools-0.2.15/pysideuic/exceptions.py000066400000000000000000000021151220335231500174230ustar00rootroot00000000000000# This file is part of the PySide project. # # Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). # Copyright (C) 2009 Riverbank Computing Limited. # Copyright (C) 2009 Torsten Marek # # Contact: PySide team # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # version 2 as published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA # 02110-1301 USA class NoSuchWidgetError(Exception): def __str__(self): return "Unknown Qt widget: %s" % (self.args[0],) class UnsupportedPropertyError(Exception): pass class WidgetPluginError(Exception): pass Tools-0.2.15/pysideuic/icon_cache.py000066400000000000000000000106651220335231500173260ustar00rootroot00000000000000#!/usr/bin/env python # This file is part of the PySide project. # # Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). # Copyright (C) 2010 Riverbank Computing Limited. # Copyright (C) 2009 Torsten Marek # # Contact: PySide team # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # version 2 as published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA # 02110-1301 USA import os.path class IconCache(object): """Maintain a cache of icons. If an icon is used more than once by a GUI then ensure that only one copy is created. """ def __init__(self, object_factory, qtgui_module): """Initialise the cache.""" self._object_factory = object_factory self._qtgui_module = qtgui_module self._base_dir = '' self._cache = [] def set_base_dir(self, base_dir): """ Set the base directory to be used for all relative filenames. """ self._base_dir = base_dir def get_icon(self, iconset): """Return an icon described by the given iconset tag.""" iset = _IconSet(iconset, self._base_dir) try: idx = self._cache.index(iset) except ValueError: idx = -1 if idx >= 0: # Return the icon from the cache. iset = self._cache[idx] else: # Follow uic's naming convention. name = 'icon' idx = len(self._cache) if idx > 0: name += str(idx) icon = self._object_factory.createQObject("QIcon", name, (), is_attribute=False) iset.set_icon(icon, self._qtgui_module) self._cache.append(iset) return iset.icon class _IconSet(object): """An icon set, ie. the mode and state and the pixmap used for each.""" def __init__(self, iconset, base_dir): """Initialise the icon set from an XML tag.""" # Set the pre-Qt v4.4 fallback (ie. with no roles). self._fallback = self._file_name(iconset.text, base_dir) self._use_fallback = True # Parse the icon set. self._roles = {} for i in iconset: file_name = i.text if file_name is not None: file_name = self._file_name(file_name, base_dir) self._roles[i.tag] = file_name self._use_fallback = False # There is no real icon yet. self.icon = None @staticmethod def _file_name(fname, base_dir): """ Convert a relative filename if we have a base directory. """ fname = fname.replace("\\", "\\\\") if base_dir != '' and fname[0] != ':' and not os.path.isabs(fname): fname = os.path.join(base_dir, fname) return fname def set_icon(self, icon, qtgui_module): """Save the icon and set its attributes.""" if self._use_fallback: icon.addFile(self._fallback) else: for role, pixmap in self._roles.items(): if role.endswith("off"): mode = role[:-3] state = qtgui_module.QIcon.Off elif role.endswith("on"): mode = role[:-2] state = qtgui_module.QIcon.On else: continue mode = getattr(qtgui_module.QIcon, mode.title()) if pixmap: icon.addPixmap(qtgui_module.QPixmap(pixmap), mode, state) else: icon.addPixmap(qtgui_module.QPixmap(), mode, state) self.icon = icon def __eq__(self, other): """Compare two icon sets for equality.""" if not isinstance(other, type(self)): return NotImplemented if self._use_fallback: if other._use_fallback: return self._fallback == other._fallback return False if other._use_fallback: return False return self._roles == other._roles Tools-0.2.15/pysideuic/objcreator.py000066400000000000000000000075161220335231500174060ustar00rootroot00000000000000# This file is part of the PySide project. # # Copyright (C) 2009-2011 Nokia Corporation and/or its subsidiary(-ies). # Copyright (C) 2010 Riverbank Computing Limited. # Copyright (C) 2009 Torsten Marek # # Contact: PySide team # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # version 2 as published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA # 02110-1301 USA import sys import os.path from pysideuic.exceptions import NoSuchWidgetError, WidgetPluginError if sys.hexversion >= 0x03000000: from pysideuic.port_v3.load_plugin import load_plugin else: from pysideuic.port_v2.load_plugin import load_plugin # The list of directories that are searched for widget plugins. This is # exposed as part of the API. widgetPluginPath = [os.path.join(os.path.dirname(__file__), 'widget-plugins')] MATCH = True NO_MATCH = False MODULE = 0 CW_FILTER = 1 class QObjectCreator(object): def __init__(self, creatorPolicy): self._cpolicy = creatorPolicy self._cwFilters = [] self._modules = [self._cpolicy.createQtGuiWrapper()] # Get the optional plugins. for plugindir in widgetPluginPath: try: plugins = os.listdir(plugindir) except: plugins = [] for filename in plugins: if not filename.endswith('.py') or filename == '__init__.py': continue filename = os.path.join(plugindir, filename) plugin_globals = { "MODULE": MODULE, "CW_FILTER": CW_FILTER, "MATCH": MATCH, "NO_MATCH": NO_MATCH} plugin_locals = {} if load_plugin(open(filename), plugin_globals, plugin_locals): pluginType = plugin_locals["pluginType"] if pluginType == MODULE: modinfo = plugin_locals["moduleInformation"]() self._modules.append(self._cpolicy.createModuleWrapper(*modinfo)) elif pluginType == CW_FILTER: self._cwFilters.append(plugin_locals["getFilter"]()) else: raise WidgetPluginError("Unknown plugin type of %s" % filename) self._customWidgets = self._cpolicy.createCustomWidgetLoader() self._modules.append(self._customWidgets) def createQObject(self, classname, *args, **kwargs): classType = self.findQObjectType(classname) if classType: return self._cpolicy.instantiate(classType, *args, **kwargs) raise NoSuchWidgetError(classname) def invoke(self, rname, method, args=()): return self._cpolicy.invoke(rname, method, args) def findQObjectType(self, classname): for module in self._modules: w = module.search(classname) if w is not None: return w return None def getSlot(self, obj, slotname): return self._cpolicy.getSlot(obj, slotname) def addCustomWidget(self, widgetClass, baseClass, module): for cwFilter in self._cwFilters: match, result = cwFilter(widgetClass, baseClass, module) if match: widgetClass, baseClass, module = result break self._customWidgets.addCustomWidget(widgetClass, baseClass, module) Tools-0.2.15/pysideuic/port_v2/000077500000000000000000000000001220335231500162645ustar00rootroot00000000000000Tools-0.2.15/pysideuic/port_v2/__init__.py000066400000000000000000000015221220335231500203750ustar00rootroot00000000000000# This file is part of the PySide project. # # Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). # Copyright (C) 2010 Riverbank Computing Limited. # # Contact: PySide team # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # version 2 as published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA # 02110-1301 USA Tools-0.2.15/pysideuic/port_v2/as_string.py000066400000000000000000000024331220335231500206310ustar00rootroot00000000000000# This file is part of the PySide project. # # Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). # Copyright (C) 2010 Riverbank Computing Limited. # # Contact: PySide team # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # version 2 as published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA # 02110-1301 USA import re def as_string(obj, encode=True): if isinstance(obj, basestring): s = '"' + _escape(obj.encode('UTF-8')) + '"' return s return str(obj) _esc_regex = re.compile(r"(\"|\'|\\)") def _escape(text): # This escapes any escaped single or double quote or backslash. x = _esc_regex.sub(r"\\\1", text) # This replaces any '\n' with an escaped version and a real line break. return re.sub(r'\n', r'\\n"\n"', x) Tools-0.2.15/pysideuic/port_v2/ascii_upper.py000066400000000000000000000022221220335231500211370ustar00rootroot00000000000000# This file is part of the PySide project. # # Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). # Copyright (C) 2010 Riverbank Computing Limited. # # Contact: PySide team # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # version 2 as published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA # 02110-1301 USA import string # A translation table for converting ASCII lower case to upper case. _ascii_trans_table = string.maketrans(string.ascii_lowercase, string.ascii_uppercase) # Convert a string to ASCII upper case irrespective of the current locale. def ascii_upper(s): return s.translate(_ascii_trans_table) Tools-0.2.15/pysideuic/port_v2/invoke.py000066400000000000000000000026201220335231500201310ustar00rootroot00000000000000# This file is part of the PySide project. # # Copyright (C) 2009-2011 Nokia Corporation and/or its subsidiary(-ies). # Copyright (C) 2010 Riverbank Computing Limited. # Copyright (C) 2009 Torsten Marek # # Contact: PySide team # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # version 2 as published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA # 02110-1301 USA from pysideuic.exceptions import NoSuchWidgetError def invoke(driver): """ Invoke the given command line driver. Return the exit status to be passed back to the parent process. """ exit_status = 1 try: exit_status = driver.invoke() except IOError, e: driver.on_IOError(e) except SyntaxError, e: driver.on_SyntaxError(e) except NoSuchWidgetError, e: driver.on_NoSuchWidgetError(e) except Exception, e: driver.on_Exception(e) return exit_status Tools-0.2.15/pysideuic/port_v2/load_plugin.py000066400000000000000000000026041220335231500211350ustar00rootroot00000000000000# This file is part of the PySide project. # # Copyright (C) 2009-2011 Nokia Corporation and/or its subsidiary(-ies). # Copyright (C) 2010 Riverbank Computing Limited. # Copyright (C) 2009 Torsten Marek # # Contact: PySide team # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # version 2 as published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA # 02110-1301 USA from pysideuic.exceptions import WidgetPluginError def load_plugin(plugin, plugin_globals, plugin_locals): """ Load the given plugin (which is an open file). Return True if the plugin was loaded, or False if it wanted to be ignored. Raise an exception if there was an error. """ try: exec(plugin.read(), plugin_globals, plugin_locals) except ImportError: return False except Exception, e: raise WidgetPluginError("%s: %s" % (e.__class__, str(e))) return True Tools-0.2.15/pysideuic/port_v2/proxy_base.py000066400000000000000000000017501220335231500210140ustar00rootroot00000000000000# This file is part of the PySide project. # # Copyright (C) 2009-2011 Nokia Corporation and/or its subsidiary(-ies). # Copyright (C) 2010 Riverbank Computing Limited. # Copyright (C) 2009 Torsten Marek # # Contact: PySide team # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # version 2 as published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA # 02110-1301 USA from pysideuic.Compiler.proxy_type import ProxyType class ProxyBase(object): __metaclass__ = ProxyType Tools-0.2.15/pysideuic/port_v2/string_io.py000066400000000000000000000017201220335231500206330ustar00rootroot00000000000000# This file is part of the PySide project. # # Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). # Copyright (C) 2010 Riverbank Computing Limited. # # Contact: PySide team # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # version 2 as published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA # 02110-1301 USA # Import the StringIO object. try: from cStringIO import StringIO except ImportError: from StringIO import StringIO Tools-0.2.15/pysideuic/port_v3/000077500000000000000000000000001220335231500162655ustar00rootroot00000000000000Tools-0.2.15/pysideuic/port_v3/__init__.py000066400000000000000000000015221220335231500203760ustar00rootroot00000000000000# This file is part of the PySide project. # # Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). # Copyright (C) 2010 Riverbank Computing Limited. # # Contact: PySide team # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # version 2 as published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA # 02110-1301 USA Tools-0.2.15/pysideuic/port_v3/as_string.py000066400000000000000000000024151220335231500206320ustar00rootroot00000000000000# This file is part of the PySide project. # # Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). # Copyright (C) 2010 Riverbank Computing Limited. # # Contact: PySide team # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # version 2 as published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA # 02110-1301 USA import re def as_string(obj, encode=True): if isinstance(obj, str): s = '"' + _escape(obj) + '"' return s return str(obj) _esc_regex = re.compile(r"(\"|\'|\\)") def _escape(text): # This escapes any escaped single or double quote or backslash. x = _esc_regex.sub(r"\\\1", text) # This replaces any '\n' with an escaped version and a real line break. return re.sub(r'\n', r'\\n"\n"', x) Tools-0.2.15/pysideuic/port_v3/ascii_upper.py000066400000000000000000000022201220335231500211360ustar00rootroot00000000000000# This file is part of the PySide project. # # Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). # Copyright (C) 2010 Riverbank Computing Limited. # # Contact: PySide team # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # version 2 as published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA # 02110-1301 USA # A translation table for converting ASCII lower case to upper case. _ascii_trans_table = bytes.maketrans(b'abcdefghijklmnopqrstuvwxyz', b'ABCDEFGHIJKLMNOPQRSTUVWXYZ') # Convert a string to ASCII upper case irrespective of the current locale. def ascii_upper(s): return s.translate(_ascii_trans_table) Tools-0.2.15/pysideuic/port_v3/invoke.py000066400000000000000000000026301220335231500201330ustar00rootroot00000000000000# This file is part of the PySide project. # # Copyright (C) 2009-2011 Nokia Corporation and/or its subsidiary(-ies). # Copyright (C) 2010 Riverbank Computing Limited. # Copyright (C) 2009 Torsten Marek # # Contact: PySide team # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # version 2 as published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA # 02110-1301 USA from pysideuic.exceptions import NoSuchWidgetError def invoke(driver): """ Invoke the given command line driver. Return the exit status to be passed back to the parent process. """ exit_status = 1 try: exit_status = driver.invoke() except IOError as e: driver.on_IOError(e) except SyntaxError as e: driver.on_SyntaxError(e) except NoSuchWidgetError as e: driver.on_NoSuchWidgetError(e) except Exception as e: driver.on_Exception(e) return exit_status Tools-0.2.15/pysideuic/port_v3/load_plugin.py000066400000000000000000000026061220335231500211400ustar00rootroot00000000000000# This file is part of the PySide project. # # Copyright (C) 2009-2011 Nokia Corporation and/or its subsidiary(-ies). # Copyright (C) 2010 Riverbank Computing Limited. # Copyright (C) 2009 Torsten Marek # # Contact: PySide team # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # version 2 as published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA # 02110-1301 USA from pysideuic.exceptions import WidgetPluginError def load_plugin(plugin, plugin_globals, plugin_locals): """ Load the given plugin (which is an open file). Return True if the plugin was loaded, or False if it wanted to be ignored. Raise an exception if there was an error. """ try: exec(plugin.read(), plugin_globals, plugin_locals) except ImportError: return False except Exception as e: raise WidgetPluginError("%s: %s" % (e.__class__, str(e))) return True Tools-0.2.15/pysideuic/port_v3/proxy_base.py000066400000000000000000000017401220335231500210140ustar00rootroot00000000000000# This file is part of the PySide project. # # Copyright (C) 2009-2011 Nokia Corporation and/or its subsidiary(-ies). # Copyright (C) 2010 Riverbank Computing Limited. # Copyright (C) 2009 Torsten Marek # # Contact: PySide team # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # version 2 as published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA # 02110-1301 USA from pysideuic.Compiler.proxy_type import ProxyType class ProxyBase(metaclass=ProxyType): pass Tools-0.2.15/pysideuic/port_v3/string_io.py000066400000000000000000000016121220335231500206340ustar00rootroot00000000000000# This file is part of the PySide project. # # Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). # Copyright (C) 2010 Riverbank Computing Limited. # # Contact: PySide team # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # version 2 as published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA # 02110-1301 USA # Import the StringIO object. from io import StringIO Tools-0.2.15/pysideuic/properties.py000066400000000000000000000375221220335231500174500ustar00rootroot00000000000000# This file is part of the PySide project. # # Copyright (C) 2009-2011 Nokia Corporation and/or its subsidiary(-ies). # Copyright (C) 2010 Riverbank Computing Limited. # Copyright (C) 2009 Torsten Marek # # Contact: PySide team # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # version 2 as published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA # 02110-1301 USA import logging import os.path import sys from pysideuic.exceptions import UnsupportedPropertyError from pysideuic.icon_cache import IconCache if sys.hexversion >= 0x03000000: from pysideuic.port_v3.ascii_upper import ascii_upper else: from pysideuic.port_v2.ascii_upper import ascii_upper logger = logging.getLogger(__name__) DEBUG = logger.debug QtCore = None QtGui = None def int_list(prop): return [int(child.text) for child in prop] def float_list(prop): return [float(child.text) for child in prop] bool_ = lambda v: v == "true" def needsWidget(func): func.needsWidget = True return func class Properties(object): def __init__(self, factory, QtCore_mod, QtGui_mod): global QtGui, QtCore QtGui = QtGui_mod QtCore = QtCore_mod self.factory = factory self._base_dir = '' self.reset() def set_base_dir(self, base_dir): """ Set the base directory to be used for all relative filenames. """ self._base_dir = base_dir self.icon_cache.set_base_dir(base_dir) def reset(self): self.buddies = [] self.delayed_props = [] self.icon_cache = IconCache(self.factory, QtGui) def _pyEnumMember(self, cpp_name): try: prefix, membername = cpp_name.split("::") except ValueError: prefix = "Qt" membername = cpp_name if prefix == "Qt": return getattr(QtCore.Qt, membername) scope = self.factory.findQObjectType(prefix) if scope is None: raise AttributeError("unknown enum %s" % cpp_name) return getattr(scope, membername) def _set(self, prop): expr = [self._pyEnumMember(v) for v in prop.text.split('|')] value = expr[0] for v in expr[1:]: value |= v return value def _enum(self, prop): return self._pyEnumMember(prop.text) def _number(self, prop): return int(prop.text) _uInt = _longLong = _uLongLong = _number def _double(self, prop): return float(prop.text) def _bool(self, prop): return prop.text == 'true' def _stringlist(self, prop): return [self._string(p, notr='true') for p in prop] def _string(self, prop, notr=None): text = prop.text if text is None: return "" if prop.get('notr', notr) == 'true': return text return QtGui.QApplication.translate(self.uiname, text, prop.get('comment'), QtGui.QApplication.UnicodeUTF8) _char = _string def _cstring(self, prop): return str(prop.text) def _color(self, prop): args = int_list(prop) # Handle the optional alpha component. alpha = int(prop.get("alpha", "255")) if alpha != 255: args.append(alpha) return QtGui.QColor(*args) def _point(self, prop): return QtCore.QPoint(*int_list(prop)) def _pointf(self, prop): return QtCore.QPointF(*float_list(prop)) def _rect(self, prop): return QtCore.QRect(*int_list(prop)) def _rectf(self, prop): return QtCore.QRectF(*float_list(prop)) def _size(self, prop): return QtCore.QSize(*int_list(prop)) def _sizef(self, prop): return QtCore.QSizeF(*float_list(prop)) def _pixmap(self, prop): if prop.text: fname = prop.text.replace("\\", "\\\\") if self._base_dir != '' and fname[0] != ':' and not os.path.isabs(fname): fname = os.path.join(self._base_dir, fname) return QtGui.QPixmap(fname) # Don't bother to set the property if the pixmap is empty. return None def _iconset(self, prop): return self.icon_cache.get_icon(prop) def _url(self, prop): return QtCore.QUrl(prop[0].text) def _locale(self, prop): lang = getattr(QtCore.QLocale, prop.attrib['language']) country = getattr(QtCore.QLocale, prop.attrib['country']) return QtCore.QLocale(lang, country) def _cursor(self, prop): return QtGui.QCursor(QtCore.Qt.CursorShape(int(prop.text))) def _date(self, prop): return QtCore.QDate(*int_list(prop)) def _datetime(self, prop): args = int_list(prop) return QtCore.QDateTime(QtCore.QDate(*args[-3:]), QtCore.QTime(*args[:-3])) def _time(self, prop): return QtCore.QTime(*int_list(prop)) def _gradient(self, prop): name = 'gradient' # Create the specific gradient. gtype = prop.get('type', '') if gtype == 'LinearGradient': startx = float(prop.get('startx')) starty = float(prop.get('starty')) endx = float(prop.get('endx')) endy = float(prop.get('endy')) gradient = self.factory.createQObject('QLinearGradient', name, (startx, starty, endx, endy), is_attribute=False) elif gtype == 'ConicalGradient': centralx = float(prop.get('centralx')) centraly = float(prop.get('centraly')) angle = float(prop.get('angle')) gradient = self.factory.createQObject('QConicalGradient', name, (centralx, centraly, angle), is_attribute=False) elif gtype == 'RadialGradient': centralx = float(prop.get('centralx')) centraly = float(prop.get('centraly')) radius = float(prop.get('radius')) focalx = float(prop.get('focalx')) focaly = float(prop.get('focaly')) gradient = self.factory.createQObject('QRadialGradient', name, (centralx, centraly, radius, focalx, focaly), is_attribute=False) else: raise UnsupportedPropertyError(prop.tag) # Set the common values. spread = prop.get('spread') if spread: gradient.setSpread(getattr(QtGui.QGradient, spread)) cmode = prop.get('coordinatemode') if cmode: gradient.setCoordinateMode(getattr(QtGui.QGradient, cmode)) # Get the gradient stops. for gstop in prop: if gstop.tag != 'gradientstop': raise UnsupportedPropertyError(gstop.tag) position = float(gstop.get('position')) color = self._color(gstop[0]) gradient.setColorAt(position, color) return name def _palette(self, prop): palette = self.factory.createQObject("QPalette", "palette", (), is_attribute=False) for palette_elem in prop: sub_palette = getattr(QtGui.QPalette, palette_elem.tag.title()) for role, color in enumerate(palette_elem): if color.tag == 'color': # Handle simple colour descriptions where the role is # implied by the colour's position. palette.setColor(sub_palette, QtGui.QPalette.ColorRole(role), self._color(color)) elif color.tag == 'colorrole': role = getattr(QtGui.QPalette, color.get('role')) brush = self._brush(color[0]) palette.setBrush(sub_palette, role, brush) else: raise UnsupportedPropertyError(color.tag) return palette def _brush(self, prop): brushstyle = prop.get('brushstyle') if brushstyle in ('LinearGradientPattern', 'ConicalGradientPattern', 'RadialGradientPattern'): gradient = self._gradient(prop[0]) brush = self.factory.createQObject("QBrush", "brush", (gradient, ), is_attribute=False) else: color = self._color(prop[0]) brush = self.factory.createQObject("QBrush", "brush", (color, ), is_attribute=False) brushstyle = getattr(QtCore.Qt, brushstyle) brush.setStyle(brushstyle) return brush #@needsWidget def _sizepolicy(self, prop, widget): values = [int(child.text) for child in prop] if len(values) == 2: # Qt v4.3.0 and later. horstretch, verstretch = values hsizetype = getattr(QtGui.QSizePolicy, prop.get('hsizetype')) vsizetype = getattr(QtGui.QSizePolicy, prop.get('vsizetype')) else: hsizetype, vsizetype, horstretch, verstretch = values hsizetype = QtGui.QSizePolicy.Policy(hsizetype) vsizetype = QtGui.QSizePolicy.Policy(vsizetype) sizePolicy = self.factory.createQObject("QSizePolicy", "sizePolicy", (hsizetype, vsizetype), is_attribute=False) sizePolicy.setHorizontalStretch(horstretch) sizePolicy.setVerticalStretch(verstretch) sizePolicy.setHeightForWidth(widget.sizePolicy().hasHeightForWidth()) return sizePolicy _sizepolicy = needsWidget(_sizepolicy) # font needs special handling/conversion of all child elements. _font_attributes = (("Family", str), ("PointSize", int), ("Weight", int), ("Italic", bool_), ("Underline", bool_), ("StrikeOut", bool_), ("Bold", bool_)) def _font(self, prop): newfont = self.factory.createQObject("QFont", "font", (), is_attribute = False) for attr, converter in self._font_attributes: v = prop.findtext("./%s" % (attr.lower(),)) if v is None: continue getattr(newfont, "set%s" % (attr,))(converter(v)) return newfont def _cursorShape(self, prop): return getattr(QtCore.Qt, prop.text) def convert(self, prop, widget=None): try: func = getattr(self, "_" + prop[0].tag) except AttributeError: raise UnsupportedPropertyError(prop[0].tag) else: args = {} if getattr(func, "needsWidget", False): assert widget is not None args["widget"] = widget return func(prop[0], **args) def _getChild(self, elem_tag, elem, name, default=None): for prop in elem.findall(elem_tag): if prop.attrib["name"] == name: return self.convert(prop) else: return default def getProperty(self, elem, name, default=None): return self._getChild("property", elem, name, default) def getAttribute(self, elem, name, default=None): return self._getChild("attribute", elem, name, default) def setProperties(self, widget, elem): try: self.wclass = elem.attrib["class"] except KeyError: pass for prop in elem.findall("property"): prop_name = prop.attrib["name"] DEBUG("setting property %s" % (prop_name,)) try: stdset = bool(int(prop.attrib["stdset"])) except KeyError: stdset = True if not stdset: self._setViaSetProperty(widget, prop) elif hasattr(self, prop_name): getattr(self, prop_name)(widget, prop) else: prop_value = self.convert(prop, widget) if prop_value is not None: getattr(widget, "set%s%s" % (ascii_upper(prop_name[0]), prop_name[1:]))(prop_value) # SPECIAL PROPERTIES # If a property has a well-known value type but needs special, # context-dependent handling, the default behaviour can be overridden here. # Delayed properties will be set after the whole widget tree has been # populated. def _delayed_property(self, widget, prop): prop_value = self.convert(prop) if prop_value is not None: prop_name = prop.attrib["name"] self.delayed_props.append((widget, False, 'set%s%s' % (ascii_upper(prop_name[0]), prop_name[1:]), prop_value)) # These properties will be set with a widget.setProperty call rather than # calling the set function. def _setViaSetProperty(self, widget, prop): prop_value = self.convert(prop) if prop_value is not None: widget.setProperty(prop.attrib["name"], prop_value) # Ignore the property. def _ignore(self, widget, prop): pass # Define properties that use the canned handlers. currentIndex = _delayed_property currentRow = _delayed_property showDropIndicator = _setViaSetProperty intValue = _setViaSetProperty value = _setViaSetProperty objectName = _ignore leftMargin = _ignore topMargin = _ignore rightMargin = _ignore bottomMargin = _ignore horizontalSpacing = _ignore verticalSpacing = _ignore # tabSpacing is actually the spacing property of the widget's layout. def tabSpacing(self, widget, prop): prop_value = self.convert(prop) if prop_value is not None: self.delayed_props.append((widget, True, 'setSpacing', prop_value)) # buddy setting has to be done after the whole widget tree has been # populated. We can't use delay here because we cannot get the actual # buddy yet. def buddy(self, widget, prop): buddy_name = prop[0].text if buddy_name: self.buddies.append((widget, buddy_name)) # geometry is handled specially if set on the toplevel widget. def geometry(self, widget, prop): if widget.objectName() == self.uiname: geom = int_list(prop[0]) widget.resize(geom[2], geom[3]) else: widget.setGeometry(self._rect(prop[0])) def orientation(self, widget, prop): # If the class is a QFrame, it's a line. if widget.metaObject().className() == "QFrame": widget.setFrameShape( {"Qt::Horizontal": QtGui.QFrame.HLine, "Qt::Vertical" : QtGui.QFrame.VLine}[prop[0].text]) # In Qt Designer, lines appear to be sunken, QFormBuilder loads # them as such, uic generates plain lines. We stick to the look in # Qt Designer. widget.setFrameShadow(QtGui.QFrame.Sunken) else: widget.setOrientation(self._enum(prop[0])) # The isWrapping attribute of QListView is named inconsistently, it should # be wrapping. def isWrapping(self, widget, prop): widget.setWrapping(self.convert(prop)) # This is a pseudo-property injected to deal with setContentsMargin() # introduced in Qt v4.3. def pyuicContentsMargins(self, widget, prop): widget.setContentsMargins(*int_list(prop)) # This is a pseudo-property injected to deal with setHorizontalSpacing() # and setVerticalSpacing() introduced in Qt v4.3. def pyuicSpacing(self, widget, prop): horiz, vert = int_list(prop) if horiz == vert: widget.setSpacing(horiz) else: if horiz >= 0: widget.setHorizontalSpacing(horiz) if vert >= 0: widget.setVerticalSpacing(vert) Tools-0.2.15/pysideuic/pyside-uic.1000066400000000000000000000014361220335231500170320ustar00rootroot00000000000000.TH PYSIDE-UIC "1" "December 2010" "pyside-uic" "User Commands" .SH NAME pyside\-uic \- DESCRIPTION... .SH DESCRIPTION .SS "Usage:" .IP pyside\-uic [options] .SS "Options:" .TP \fB\-\-version show program's version number and exit .TP .BI \-h\fB \fR,\fB \-\-help show this help message and exit .TP .BI \-o FILE \fR, \-\-output=\fIFILE write generated code to FILE instead of stdout .TP .BI \-x \fR, \-\-execute generate extra code to test and display the class .TP .BI \-d \fR, \-\-debug show debug output .TP .BI \-i N\fR, \-\-ident=N set indent width to N spaces, tab if N is 0 (default: 4) .SH COPYRIGHT Copyright \(co 2010 Nokia Corporation and/or its subsidiary(\fB\-ies\fR) .SH AUTHOR .PP This manpage was written by Marcelo Lira , on the 29. December 2010. Tools-0.2.15/pysideuic/uiparser.py000066400000000000000000000763501220335231500171100ustar00rootroot00000000000000# This file is part of the PySide project. # # Copyright (C) 2009-2011 Nokia Corporation and/or its subsidiary(-ies). # Copyright (C) 2010 Riverbank Computing Limited. # Copyright (C) 2009 Torsten Marek # # Contact: PySide team # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # version 2 as published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA # 02110-1301 USA import sys import logging import os.path import re try: from xml.etree.cElementTree import parse, SubElement except ImportError: from xml.etree.ElementTree import parse, SubElement from pysideuic.exceptions import NoSuchWidgetError from pysideuic.objcreator import QObjectCreator from pysideuic.properties import Properties logger = logging.getLogger(__name__) DEBUG = logger.debug if sys.version_info < (2,4,0): def reversed(seq): for i in xrange(len(seq)-1, -1, -1): yield seq[i] QtCore = None QtGui = None def gridPosition(elem): """gridPosition(elem) -> tuple Return the 4-tuple of (row, column, rowspan, colspan) for a widget element, or an empty tuple. """ try: return (int(elem.attrib["row"]), int(elem.attrib["column"]), int(elem.attrib.get("rowspan", 1)), int(elem.attrib.get("colspan", 1))) except KeyError: return () class WidgetStack(list): topwidget = None def push(self, item): DEBUG("push %s %s" % (item.metaObject().className(), item.objectName())) self.append(item) if isinstance(item, QtGui.QWidget): self.topwidget = item def popLayout(self): layout = list.pop(self) DEBUG("pop layout %s %s" % (layout.metaObject().className(), layout.objectName())) return layout def popWidget(self): widget = list.pop(self) DEBUG("pop widget %s %s" % (widget.metaObject().className(), widget.objectName())) for item in reversed(self): if isinstance(item, QtGui.QWidget): self.topwidget = item break else: self.topwidget = None DEBUG("new topwidget %s" % (self.topwidget,)) return widget def peek(self): return self[-1] def topIsLayout(self): return isinstance(self[-1], QtGui.QLayout) class UIParser(object): def __init__(self, QtCoreModule, QtGuiModule, creatorPolicy): self.factory = QObjectCreator(creatorPolicy) self.wprops = Properties(self.factory, QtCoreModule, QtGuiModule) global QtCore, QtGui QtCore = QtCoreModule QtGui = QtGuiModule self.reset() def uniqueName(self, name): """UIParser.uniqueName(string) -> string Create a unique name from a string. >>> p = UIParser(QtCore, QtGui) >>> p.uniqueName("foo") 'foo' >>> p.uniqueName("foo") 'foo1' """ try: suffix = self.name_suffixes[name] except KeyError: self.name_suffixes[name] = 0 return name suffix += 1 self.name_suffixes[name] = suffix return "%s%i" % (name, suffix) def reset(self): try: self.wprops.reset() except AttributeError: pass self.toplevelWidget = None self.stack = WidgetStack() self.name_suffixes = {} self.defaults = {"spacing": 6, "margin": 0} self.actions = [] self.currentActionGroup = None self.resources = [] self.button_groups = [] self.layout_widget = False def setupObject(self, clsname, parent, branch, is_attribute = True): name = self.uniqueName(branch.attrib.get("name") or clsname[1:].lower()) if parent is None: args = () else: args = (parent, ) obj = self.factory.createQObject(clsname, name, args, is_attribute) self.wprops.setProperties(obj, branch) obj.setObjectName(name) if is_attribute: setattr(self.toplevelWidget, name, obj) return obj def createWidget(self, elem): self.column_counter = 0 self.row_counter = 0 self.item_nr = 0 self.itemstack = [] self.sorting_enabled = None widget_class = elem.attrib['class'].replace('::', '.') if widget_class == 'Line': widget_class = 'QFrame' # Ignore the parent if it is a container parent = self.stack.topwidget # if is a Menubar on MacOS macMenu = (sys.platform == 'darwin') and (widget_class == 'QMenuBar') if isinstance(parent, (QtGui.QDockWidget, QtGui.QMdiArea, QtGui.QScrollArea, QtGui.QStackedWidget, QtGui.QToolBox, QtGui.QTabWidget, QtGui.QWizard)) or macMenu: parent = None # See if this is a layout widget. if widget_class == 'QWidget': if parent is not None: if not isinstance(parent, QtGui.QMainWindow): self.layout_widget = True self.stack.push(self.setupObject(widget_class, parent, elem)) if isinstance(self.stack.topwidget, QtGui.QTableWidget): self.stack.topwidget.setColumnCount(len(elem.findall("column"))) self.stack.topwidget.setRowCount(len(elem.findall("row"))) self.traverseWidgetTree(elem) widget = self.stack.popWidget() self.layout_widget = False if isinstance(widget, QtGui.QTreeView): self.handleHeaderView(elem, "header", widget.header()) elif isinstance(widget, QtGui.QTableView): self.handleHeaderView(elem, "horizontalHeader", widget.horizontalHeader()) self.handleHeaderView(elem, "verticalHeader", widget.verticalHeader()) elif isinstance(widget, QtGui.QAbstractButton): bg_i18n = self.wprops.getAttribute(elem, "buttonGroup") if bg_i18n is not None: bg_name = bg_i18n.string for bg in self.button_groups: if bg.objectName() == bg_name: break else: bg = self.factory.createQObject("QButtonGroup", bg_name, (self.toplevelWidget, )) bg.setObjectName(bg_name) self.button_groups.append(bg) bg.addButton(widget) if self.sorting_enabled is not None: widget.setSortingEnabled(self.sorting_enabled) self.sorting_enabled = None if self.stack.topIsLayout(): lay = self.stack.peek() gp = elem.attrib["grid-position"] if isinstance(lay, QtGui.QFormLayout): lay.setWidget(gp[0], self._form_layout_role(gp), widget) else: lay.addWidget(widget, *gp) topwidget = self.stack.topwidget if isinstance(topwidget, QtGui.QToolBox): icon = self.wprops.getAttribute(elem, "icon") if icon is not None: topwidget.addItem(widget, icon, self.wprops.getAttribute(elem, "label")) else: topwidget.addItem(widget, self.wprops.getAttribute(elem, "label")) tooltip = self.wprops.getAttribute(elem, "toolTip") if tooltip is not None: topwidget.setItemToolTip(topwidget.indexOf(widget), tooltip) elif isinstance(topwidget, QtGui.QTabWidget): icon = self.wprops.getAttribute(elem, "icon") if icon is not None: topwidget.addTab(widget, icon, self.wprops.getAttribute(elem, "title")) else: topwidget.addTab(widget, self.wprops.getAttribute(elem, "title")) tooltip = self.wprops.getAttribute(elem, "toolTip") if tooltip is not None: topwidget.setTabToolTip(topwidget.indexOf(widget), tooltip) elif isinstance(topwidget, QtGui.QWizard): topwidget.addPage(widget) elif isinstance(topwidget, QtGui.QStackedWidget): topwidget.addWidget(widget) elif isinstance(topwidget, (QtGui.QDockWidget, QtGui.QScrollArea)): topwidget.setWidget(widget) elif isinstance(topwidget, QtGui.QMainWindow): if type(widget) == QtGui.QWidget: topwidget.setCentralWidget(widget) elif isinstance(widget, QtGui.QToolBar): tbArea = self.wprops.getAttribute(elem, "toolBarArea") if tbArea is None: topwidget.addToolBar(widget) else: topwidget.addToolBar(tbArea, widget) tbBreak = self.wprops.getAttribute(elem, "toolBarBreak") if tbBreak: topwidget.insertToolBarBreak(widget) elif isinstance(widget, QtGui.QMenuBar): topwidget.setMenuBar(widget) elif isinstance(widget, QtGui.QStatusBar): topwidget.setStatusBar(widget) elif isinstance(widget, QtGui.QDockWidget): dwArea = self.wprops.getAttribute(elem, "dockWidgetArea") topwidget.addDockWidget(QtCore.Qt.DockWidgetArea(dwArea), widget) def handleHeaderView(self, elem, name, header): value = self.wprops.getAttribute(elem, name + "Visible") if value is not None: header.setVisible(value) value = self.wprops.getAttribute(elem, name + "CascadingSectionResizes") if value is not None: header.setCascadingSectionResizes(value) value = self.wprops.getAttribute(elem, name + "DefaultSectionSize") if value is not None: header.setDefaultSectionSize(value) value = self.wprops.getAttribute(elem, name + "HighlightSections") if value is not None: header.setHighlightSections(value) value = self.wprops.getAttribute(elem, name + "MinimumSectionSize") if value is not None: header.setMinimumSectionSize(value) value = self.wprops.getAttribute(elem, name + "ShowSortIndicator") if value is not None: header.setSortIndicatorShown(value) value = self.wprops.getAttribute(elem, name + "StretchLastSection") if value is not None: header.setStretchLastSection(value) def createSpacer(self, elem): width = elem.findtext("property/size/width") height = elem.findtext("property/size/height") if width is None or height is None: size_args = () else: size_args = (int(width), int(height)) sizeType = self.wprops.getProperty(elem, "sizeType", QtGui.QSizePolicy.Expanding) policy = (QtGui.QSizePolicy.Minimum, sizeType) if self.wprops.getProperty(elem, "orientation") == QtCore.Qt.Horizontal: policy = policy[1], policy[0] spacer = self.factory.createQObject("QSpacerItem", self.uniqueName("spacerItem"), size_args + policy, is_attribute=False) if self.stack.topIsLayout(): lay = self.stack.peek() gp = elem.attrib["grid-position"] if isinstance(lay, QtGui.QFormLayout): lay.setItem(gp[0], self._form_layout_role(gp), spacer) else: lay.addItem(spacer, *gp) def createLayout(self, elem): # Qt v4.3 introduced setContentsMargins() and separate values for each # of the four margins which are specified as separate properties. This # doesn't really fit the way we parse the tree (why aren't the values # passed as attributes of a single property?) so we create a new # property and inject it. However, if we find that they have all been # specified and have the same value then we inject a different property # that is compatible with older versions of Qt. left = self.wprops.getProperty(elem, 'leftMargin', -1) top = self.wprops.getProperty(elem, 'topMargin', -1) right = self.wprops.getProperty(elem, 'rightMargin', -1) bottom = self.wprops.getProperty(elem, 'bottomMargin', -1) # Count the number of properties and if they had the same value. def comp_property(m, so_far=-2, nr=0): if m >= 0: nr += 1 if so_far == -2: so_far = m elif so_far != m: so_far = -1 return so_far, nr margin, nr_margins = comp_property(left) margin, nr_margins = comp_property(top, margin, nr_margins) margin, nr_margins = comp_property(right, margin, nr_margins) margin, nr_margins = comp_property(bottom, margin, nr_margins) if nr_margins > 0: if nr_margins == 4 and margin >= 0: # We can inject the old margin property. me = SubElement(elem, 'property', name='margin') SubElement(me, 'number').text = str(margin) else: # We have to inject the new internal property. cme = SubElement(elem, 'property', name='pyuicContentsMargins') SubElement(cme, 'number').text = str(left) SubElement(cme, 'number').text = str(top) SubElement(cme, 'number').text = str(right) SubElement(cme, 'number').text = str(bottom) elif self.layout_widget: # The layout's of layout widgets have no margin. me = SubElement(elem, 'property', name='margin') SubElement(me, 'number').text = '0' # In case there are any nested layouts. self.layout_widget = False # We do the same for setHorizontalSpacing() and setVerticalSpacing(). horiz = self.wprops.getProperty(elem, 'horizontalSpacing', -1) vert = self.wprops.getProperty(elem, 'verticalSpacing', -1) if horiz >= 0 or vert >= 0: # We inject the new internal property. cme = SubElement(elem, 'property', name='pyuicSpacing') SubElement(cme, 'number').text = str(horiz) SubElement(cme, 'number').text = str(vert) classname = elem.attrib["class"] if self.stack.topIsLayout(): parent = None else: parent = self.stack.topwidget if "name" not in elem.attrib: elem.attrib["name"] = classname[1:].lower() self.stack.push(self.setupObject(classname, parent, elem)) self.traverseWidgetTree(elem) layout = self.stack.popLayout() self.configureLayout(elem, layout) if self.stack.topIsLayout(): top_layout = self.stack.peek() gp = elem.attrib["grid-position"] if isinstance(top_layout, QtGui.QFormLayout): top_layout.setLayout(gp[0], self._form_layout_role(gp), layout) else: top_layout.addLayout(layout, *gp) def configureLayout(self, elem, layout): if isinstance(layout, QtGui.QGridLayout): self.setArray(elem, 'columnminimumwidth', layout.setColumnMinimumWidth) self.setArray(elem, 'rowminimumheight', layout.setRowMinimumHeight) self.setArray(elem, 'columnstretch', layout.setColumnStretch) self.setArray(elem, 'rowstretch', layout.setRowStretch) elif isinstance(layout, QtGui.QBoxLayout): self.setArray(elem, 'stretch', layout.setStretch) def setArray(self, elem, name, setter): array = elem.attrib.get(name) if array: for idx, value in enumerate(array.split(',')): value = int(value) if value > 0: setter(idx, value) def handleItem(self, elem): if self.stack.topIsLayout(): elem[0].attrib["grid-position"] = gridPosition(elem) self.traverseWidgetTree(elem) else: w = self.stack.topwidget if isinstance(w, QtGui.QComboBox): text = self.wprops.getProperty(elem, "text") icon = self.wprops.getProperty(elem, "icon") if icon: w.addItem(icon, '') else: w.addItem('') w.setItemText(self.item_nr, text) elif isinstance(w, QtGui.QListWidget): text = self.wprops.getProperty(elem, "text") icon = self.wprops.getProperty(elem, "icon") flags = self.wprops.getProperty(elem, "flags") check_state = self.wprops.getProperty(elem, "checkState") background = self.wprops.getProperty(elem, "background") foreground = self.wprops.getProperty(elem, "foreground") if icon or flags or check_state: item_name = "item" else: item_name = None item = self.factory.createQObject("QListWidgetItem", item_name, (w, ), False) if self.item_nr == 0: self.sorting_enabled = self.factory.invoke("__sortingEnabled", w.isSortingEnabled) w.setSortingEnabled(False) if text: w.item(self.item_nr).setText(text) if icon: item.setIcon(icon) if flags: item.setFlags(flags) if check_state: item.setCheckState(check_state) if background: item.setBackground(background) if foreground: item.setForeground(foreground) elif isinstance(w, QtGui.QTreeWidget): if self.itemstack: parent, _ = self.itemstack[-1] _, nr_in_root = self.itemstack[0] else: parent = w nr_in_root = self.item_nr item = self.factory.createQObject("QTreeWidgetItem", "item_%d" % len(self.itemstack), (parent, ), False) if self.item_nr == 0 and not self.itemstack: self.sorting_enabled = self.factory.invoke("__sortingEnabled", w.isSortingEnabled) w.setSortingEnabled(False) self.itemstack.append((item, self.item_nr)) self.item_nr = 0 # We have to access the item via the tree when setting the # text. titm = w.topLevelItem(nr_in_root) for child, nr_in_parent in self.itemstack[1:]: titm = titm.child(nr_in_parent) column = -1 for prop in elem.findall("property"): c_prop = self.wprops.convert(prop) c_prop_name = prop.attrib["name"] if c_prop_name == "text": column += 1 if c_prop: titm.setText(column, c_prop) elif c_prop_name == "icon": item.setIcon(column, c_prop) elif c_prop_name == "flags": item.setFlags(c_prop) elif c_prop_name == "checkState": item.setCheckState(column, c_prop) elif c_prop_name == "background": item.setBackground(column, c_prop) elif c_prop_name == "foreground": item.setForeground(column, c_prop) self.traverseWidgetTree(elem) _, self.item_nr = self.itemstack.pop() elif isinstance(w, QtGui.QTableWidget): text = self.wprops.getProperty(elem, "text") icon = self.wprops.getProperty(elem, "icon") flags = self.wprops.getProperty(elem, "flags") check_state = self.wprops.getProperty(elem, "checkState") background = self.wprops.getProperty(elem, "background") foreground = self.wprops.getProperty(elem, "foreground") item = self.factory.createQObject("QTableWidgetItem", "item", (), False) if self.item_nr == 0: self.sorting_enabled = self.factory.invoke("__sortingEnabled", w.isSortingEnabled) w.setSortingEnabled(False) row = int(elem.attrib["row"]) col = int(elem.attrib["column"]) if icon: item.setIcon(icon) if flags: item.setFlags(flags) if check_state: item.setCheckState(check_state) if background: item.setBackground(background) if foreground: item.setForeground(foreground) w.setItem(row, col, item) if text: # Text is translated so we don't have access to the item # attribute when generating code so we must get it from the # widget after it has been set. w.item(row, col).setText(text) self.item_nr += 1 def addAction(self, elem): self.actions.append((self.stack.topwidget, elem.attrib["name"])) def addHeader(self, elem): w = self.stack.topwidget if isinstance(w, QtGui.QTreeWidget): text = self.wprops.getProperty(elem, "text") icon = self.wprops.getProperty(elem, "icon") if text: w.headerItem().setText(self.column_counter, text) if icon: w.headerItem().setIcon(self.column_counter, icon) self.column_counter += 1 elif isinstance(w, QtGui.QTableWidget): if len(elem) == 0: return text = self.wprops.getProperty(elem, "text") icon = self.wprops.getProperty(elem, "icon") whatsThis = self.wprops.getProperty(elem, "whatsThis") item = self.factory.createQObject("QTableWidgetItem", "item", (), False) if elem.tag == "column": w.setHorizontalHeaderItem(self.column_counter, item) if text: w.horizontalHeaderItem(self.column_counter).setText(text) if icon: item.setIcon(icon) if whatsThis: w.horizontalHeaderItem(self.column_counter).setWhatsThis(whatsThis) self.column_counter += 1 elif elem.tag == "row": w.setVerticalHeaderItem(self.row_counter, item) if text: w.verticalHeaderItem(self.row_counter).setText(text) if icon: item.setIcon(icon) if whatsThis: w.verticalHeaderItem(self.row_counter).setWhatsThis(whatsThis) self.row_counter += 1 def createAction(self, elem): self.setupObject("QAction", self.currentActionGroup or self.toplevelWidget, elem) def createActionGroup(self, elem): action_group = self.setupObject("QActionGroup", self.toplevelWidget, elem) self.currentActionGroup = action_group self.traverseWidgetTree(elem) self.currentActionGroup = None widgetTreeItemHandlers = { "widget" : createWidget, "addaction" : addAction, "layout" : createLayout, "spacer" : createSpacer, "item" : handleItem, "action" : createAction, "actiongroup": createActionGroup, "column" : addHeader, "row" : addHeader, } def traverseWidgetTree(self, elem): for child in iter(elem): try: handler = self.widgetTreeItemHandlers[child.tag] except KeyError: continue handler(self, child) def createUserInterface(self, elem): # Get the names of the class and widget. cname = elem.attrib["class"] wname = elem.attrib["name"] # If there was no widget name then derive it from the class name. if not wname: wname = cname if wname.startswith("Q"): wname = wname[1:] wname = wname[0].lower() + wname[1:] self.toplevelWidget = self.createToplevelWidget(cname, wname) self.toplevelWidget.setObjectName(wname) DEBUG("toplevel widget is %s", self.toplevelWidget.metaObject().className()) self.wprops.setProperties(self.toplevelWidget, elem) self.stack.push(self.toplevelWidget) self.traverseWidgetTree(elem) self.stack.popWidget() self.addActions() self.setBuddies() self.setDelayedProps() def addActions(self): for widget, action_name in self.actions: if action_name == "separator": widget.addSeparator() else: DEBUG("add action %s to %s", action_name, widget.objectName()) action_obj = getattr(self.toplevelWidget, action_name) if isinstance(action_obj, QtGui.QMenu): widget.addAction(action_obj.menuAction()) elif not isinstance(action_obj, QtGui.QActionGroup): widget.addAction(action_obj) def setDelayedProps(self): for widget, layout, setter, args in self.wprops.delayed_props: if layout: widget = widget.layout() setter = getattr(widget, setter) setter(args) def setBuddies(self): for widget, buddy in self.wprops.buddies: DEBUG("%s is buddy of %s", buddy, widget.objectName()) try: widget.setBuddy(getattr(self.toplevelWidget, buddy)) except AttributeError: DEBUG("ERROR in ui spec: %s (buddy of %s) does not exist", buddy, widget.objectName()) def classname(self, elem): DEBUG("uiname is %s", elem.text) name = elem.text if name is None: name = "" self.uiname = name self.wprops.uiname = name self.setContext(name) def setContext(self, context): """ Reimplemented by a sub-class if it needs to know the translation context. """ pass def readDefaults(self, elem): self.defaults["margin"] = int(elem.attrib["margin"]) self.defaults["spacing"] = int(elem.attrib["spacing"]) def setTaborder(self, elem): lastwidget = None for widget_elem in elem: widget = getattr(self.toplevelWidget, widget_elem.text) if lastwidget is not None: self.toplevelWidget.setTabOrder(lastwidget, widget) lastwidget = widget def readResources(self, elem): """ Read a "resources" tag and add the module to import to the parser's list of them. """ for include in elem.getiterator("include"): loc = include.attrib.get("location") # Assume our convention for naming the Python files generated by # pyrcc4. if loc and loc.endswith('.qrc'): self.resources.append(os.path.basename(loc[:-4] + '_rc')) def createConnections(self, elem): def name2object(obj): if obj == self.uiname: return self.toplevelWidget else: return getattr(self.toplevelWidget, obj) for conn in iter(elem): QtCore.QObject.connect(name2object(conn.findtext("sender")), QtCore.SIGNAL(conn.findtext("signal")), self.factory.getSlot(name2object(conn.findtext("receiver")), conn.findtext("slot").split("(")[0])) QtCore.QMetaObject.connectSlotsByName(self.toplevelWidget) def customWidgets(self, elem): def header2module(header): """header2module(header) -> string Convert paths to C++ header files to according Python modules >>> header2module("foo/bar/baz.h") 'foo.bar.baz' """ if header.endswith(".h"): header = header[:-2] mpath = [] for part in header.split('/'): # Ignore any empty parts or those that refer to the current # directory. if part not in ('', '.'): if part == '..': # We should allow this for Python3. raise SyntaxError("custom widget header file name may not contain '..'.") mpath.append(part) return '.'.join(mpath) for custom_widget in iter(elem): classname = custom_widget.findtext("class") if classname.startswith("Q3"): raise NoSuchWidgetError(classname) self.factory.addCustomWidget(classname, custom_widget.findtext("extends") or "QWidget", header2module(custom_widget.findtext("header"))) def createToplevelWidget(self, classname, widgetname): raise NotImplementedError # finalize will be called after the whole tree has been parsed and can be # overridden. def finalize(self): pass def parse(self, filename, base_dir=''): self.wprops.set_base_dir(base_dir) # The order in which the different branches are handled is important. # The widget tree handler relies on all custom widgets being known, and # in order to create the connections, all widgets have to be populated. branchHandlers = ( ("layoutdefault", self.readDefaults), ("class", self.classname), ("customwidgets", self.customWidgets), ("widget", self.createUserInterface), ("connections", self.createConnections), ("tabstops", self.setTaborder), ("resources", self.readResources), ) document = parse(filename) version = document.getroot().attrib["version"] DEBUG("UI version is %s" % (version,)) # Right now, only version 4.0 is supported. assert version in ("4.0",) for tagname, actor in branchHandlers: elem = document.find(tagname) if elem is not None: actor(elem) self.finalize() w = self.toplevelWidget self.reset() return w @staticmethod def _form_layout_role(grid_position): if grid_position[3] > 1: role = QtGui.QFormLayout.SpanningRole elif grid_position[1] == 1: role = QtGui.QFormLayout.FieldRole else: role = QtGui.QFormLayout.LabelRole return role Tools-0.2.15/pysideuic/widget-plugins/000077500000000000000000000000001220335231500176335ustar00rootroot00000000000000Tools-0.2.15/pysideuic/widget-plugins/phonon.py000066400000000000000000000026551220335231500215160ustar00rootroot00000000000000# This file is part of the PySide project. # # Copyright (C) 2009-2011 Nokia Corporation and/or its subsidiary(-ies). # Copyright (C) 2010 Riverbank Computing Limited. # # Contact: PySide team # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # version 2 as published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA # 02110-1301 USA # If pluginType is MODULE, the plugin loader will call moduleInformation. The # variable MODULE is inserted into the local namespace by the plugin loader. pluginType = MODULE # moduleInformation() must return a tuple (module, widget_list). If "module" # is "A" and any widget from this module is used, the code generator will write # "import A". If "module" is "A[.B].C", the code generator will write # "from A[.B] import C". Each entry in "widget_list" must be unique. def moduleInformation(): return "PySide.phonon", ("Phonon.SeekSlider", "Phonon.VideoPlayer", "Phonon.VolumeSlider") Tools-0.2.15/pysideuic/widget-plugins/qtdeclarative.py000066400000000000000000000026101220335231500230340ustar00rootroot00000000000000# This file is part of the PySide project. # # Copyright (C) 2009-2011 Nokia Corporation and/or its subsidiary(-ies). # Copyright (C) 2010 Riverbank Computing Limited. # # Contact: PySide team # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # version 2 as published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA # 02110-1301 USA # If pluginType is MODULE, the plugin loader will call moduleInformation. The # variable MODULE is inserted into the local namespace by the plugin loader. pluginType = MODULE # moduleInformation() must return a tuple (module, widget_list). If "module" # is "A" and any widget from this module is used, the code generator will write # "import A". If "module" is "A[.B].C", the code generator will write # "from A[.B] import C". Each entry in "widget_list" must be unique. def moduleInformation(): return "PySide.QtDeclarative", ("QDeclarativeView", ) Tools-0.2.15/pysideuic/widget-plugins/qtwebkit.py000066400000000000000000000026371220335231500220470ustar00rootroot00000000000000# This file is part of the PySide project. # # Copyright (C) 2009-2011 Nokia Corporation and/or its subsidiary(-ies). # Copyright (C) 2009 Riverbank Computing Limited. # Copyright (C) 2009 Torsten Marek # # Contact: PySide team # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # version 2 as published by the Free Software Foundation. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA # 02110-1301 USA # If pluginType is MODULE, the plugin loader will call moduleInformation. The # variable MODULE is inserted into the local namespace by the plugin loader. pluginType = MODULE # moduleInformation() must return a tuple (module, widget_list). If "module" # is "A" and any widget from this module is used, the code generator will write # "import A". If "module" is "A[.B].C", the code generator will write # "from A[.B] import C". Each entry in "widget_list" must be unique. def moduleInformation(): return "PySide.QtWebKit", ("QWebView", ) Tools-0.2.15/tests/000077500000000000000000000000001220335231500140355ustar00rootroot00000000000000Tools-0.2.15/tests/CMakeLists.txt000066400000000000000000000004471220335231500166020ustar00rootroot00000000000000find_package(Shiboken) add_subdirectory(rcc) add_test(QWizard ${SHIBOKEN_PYTHON_INTERPRETER} ${CMAKE_SOURCE_DIR}/pyside-uic "${CMAKE_CURRENT_SOURCE_DIR}/qwizard_test.ui") set_tests_properties(QWizard PROPERTIES ENVIRONMENT "PYTHONPATH=$ENV{PYTHONPATH}:${CMAKE_SOURCE_DIR}") Tools-0.2.15/tests/qwizard_test.ui000066400000000000000000000032421220335231500171150ustar00rootroot00000000000000 Wizard 0 0 400 300 Wizard 0 0 72 Hello Qt::PlainText true Qt::AlignCenter http://test.qml QDeclarativeView QGraphicsView
QtDeclarative/QDeclarativeView
Tools-0.2.15/tests/rcc/000077500000000000000000000000001220335231500146045ustar00rootroot00000000000000Tools-0.2.15/tests/rcc/CMakeLists.txt000066400000000000000000000006561220335231500173530ustar00rootroot00000000000000 macro(ADD_RCC_TEST name pyfile qrcfile) add_test(${name} ${CMAKE_CURRENT_SOURCE_DIR}/run_test.sh ${PYSIDERCC_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/${pyfile} ${CMAKE_CURRENT_SOURCE_DIR}/${qrcfile} ${CMAKE_CURRENT_SOURCE_DIR}) endmacro() add_rcc_test(RccTest rcc_test.py example.qrc) add_rcc_test(RccImageTest rcc_image_test.py image.qrc) Tools-0.2.15/tests/rcc/document-print-preview.png000066400000000000000000000032671220335231500217510ustar00rootroot00000000000000PNG  IHDR szzsBIT|dnIDATXkl~>e !iQԔ%QP*BUyK hJ|"5DVT( 5)m 1[~އw;3~ڱy<~鑎tgfsvݴml߾}w.[C|=7nέ68Ϊ 6op}ΝPJ'qL"8>H4:^acF~]7=a}q"r 07`/U+!1x'?כzb̎“2z{pxnF)_/\q0禱|=}`FZ:2t:Iۇݲ,,˺{^ykT37aٶ?ҳӘ`'$eB*%Ls̛[ybޓ7&s ryt&N`B H)QR $UC\2׮]6LӼ74=V(o| #$똦*`Rη:AUtLAѕ/0q=\!n-znYYAGMUaZ%dE"K* ͢i5XM5KxGBW;~åg3@`h#T棫 c0CQ`+5l:^J*ʕ˄B ^ZYٙsݻá>n:;G"ׯ_8OձEz6Ko*˅.]2!ɠBpSę3gNqvھ;v:LG0'Ks=zɵSV!4z::8(EFbhl words.txt shining.txt manychars.txt Tools-0.2.15/tests/rcc/image.qrc000066400000000000000000000001441220335231500163740ustar00rootroot00000000000000 document-print-preview.png Tools-0.2.15/tests/rcc/manychars.txt000066400000000000000000000264311220335231500173400ustar00rootroot00000000000000aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa Tools-0.2.15/tests/rcc/rcc_image_test.py000066400000000000000000000004551220335231500201320ustar00rootroot00000000000000 import unittest from PySide.QtGui import QApplication, QPixmap import image_rc class TestRccImage(unittest.TestCase): def testImage(self): app = QApplication([]) image = QPixmap(":image") self.assertFalse(image.isNull()) if __name__ == '__main__': unittest.main() Tools-0.2.15/tests/rcc/rcc_test.py000066400000000000000000000016601220335231500167670ustar00rootroot00000000000000import os import unittest from PySide.QtCore import QFile import example_rc class TestRccSimple(unittest.TestCase): def setUp(self): self.testdir = os.path.dirname(__file__) def testSimple(self): handle = QFile(":words.txt") handle.open(QFile.ReadOnly) original = open(os.path.join(self.testdir, "words.txt"), "r") self.assertEqual(handle.readLine(), original.readline()) def testAlias(self): handle = QFile(":jack") handle.open(QFile.ReadOnly) original = open(os.path.join(self.testdir, "shining.txt"), "r") self.assertEqual(handle.readLine(), original.readline()) def testHuge(self): handle = QFile(":manychars.txt") handle.open(QFile.ReadOnly) original = open(os.path.join(self.testdir, "manychars.txt"), "r") self.assertEqual(handle.readLine(), original.readline()) if __name__ == '__main__': unittest.main() Tools-0.2.15/tests/rcc/run_test.sh000077500000000000000000000004451220335231500170110ustar00rootroot00000000000000#!/bin/sh # This is a nasty workaround of a CTest limitation # of setting the environment variables for the test. # $1: pyside-rcc # $2: python test # $3: qrc file export PYTHONPATH=$PYTHONPATH:`pwd` $1 -o `basename $3 .qrc`_rc.py $3 `pkg-config shiboken --variable=python_interpreter` $2 Tools-0.2.15/tests/rcc/shining.txt000066400000000000000000000000541220335231500170030ustar00rootroot00000000000000All work and no play makes Jack a dull boy. Tools-0.2.15/tests/rcc/words.txt000066400000000000000000000000551220335231500165030ustar00rootroot00000000000000The Quick Brown Fox Jumps Over The Lazy Dog.