From a377d3d264e3299f79a7d99ac93cbc1b3f1f1954 Mon Sep 17 00:00:00 2001 From: yvesf Date: Tue, 17 Nov 2009 09:07:14 +0100 Subject: [PATCH] del pgworksheet --- pgworksheet_1.9/ABOUT_THIS_REPOSITORY | 1 - pgworksheet_1.9/AUTHORS | 1 - pgworksheet_1.9/LICENSE.txt | 340 -- pgworksheet_1.9/README | 23 - pgworksheet_1.9/applications/pgworksheet.desktop | 11 - .../locale/fr/LC_MESSAGES/pgworksheet.mo | Bin 6209 -> 0 bytes .../locale/ja/LC_MESSAGES/pgworksheet.mo | Bin 5664 -> 0 bytes pgworksheet_1.9/pgw/DBConnection.py | 147 - pgworksheet_1.9/pgw/Execute.py | 136 - pgworksheet_1.9/pgw/Lexical.py | 357 --- pgworksheet_1.9/pgw/MyPgSQL.py | 3257 -------------------- pgworksheet_1.9/pgw/RunSQL.py | 233 -- pgworksheet_1.9/pgw/Syntax.py | 782 ----- pgworksheet_1.9/pgw/UI.py | 980 ------ pgworksheet_1.9/pgw/Undo.py | 106 - pgworksheet_1.9/pgw/__init__.py | 86 - pgworksheet_1.9/pgworksheet | 606 ---- pgworksheet_1.9/pixmaps/pgworksheet.png | Bin 1291 -> 0 bytes pgworksheet_1.9/pixmaps/pgworksheet/about.png | Bin 320 -> 0 bytes pgworksheet_1.9/pixmaps/pgworksheet/connect.png | Bin 594 -> 0 bytes pgworksheet_1.9/pixmaps/pgworksheet/disconnect.png | Bin 581 -> 0 bytes .../pixmaps/pgworksheet/pgworksheet-32.png | Bin 1291 -> 0 bytes .../pixmaps/pgworksheet/pgworksheet.ico | Bin 16958 -> 0 bytes .../pixmaps/pgworksheet/pgworksheet.png | Bin 14247 -> 0 bytes .../pixmaps/pgworksheet/pgworksheet.xcf | Bin 21321 -> 0 bytes pgworksheet_1.9/setup.py | 37 - pgworksheet_yvesf/Makefile | 2 - pgworksheet_yvesf/TODO | 6 - pgworksheet_yvesf/applications/pgworksheet.desktop | 11 - pgworksheet_yvesf/doc/AUTHORS | 3 - pgworksheet_yvesf/doc/LICENSE.txt | 340 -- pgworksheet_yvesf/doc/README | 36 - .../locale/de/LC_MESSAGES/pgworksheet.mo | Bin 5064 -> 0 bytes .../locale/de/LC_MESSAGES/pgworksheet.po | 230 -- .../locale/fr/LC_MESSAGES/pgworksheet.mo | Bin 5393 -> 0 bytes .../locale/ja/LC_MESSAGES/pgworksheet.mo | Bin 5664 -> 0 bytes pgworksheet_yvesf/locale/pgworksheet.pot | 227 -- pgworksheet_yvesf/pgw/ConnectDialog.py | 271 -- pgworksheet_yvesf/pgw/DBConnection.py | 121 - pgworksheet_yvesf/pgw/Execute.py | 136 - pgworksheet_yvesf/pgw/Lexical.py | 357 --- pgworksheet_yvesf/pgw/Notice.py | 262 -- pgworksheet_yvesf/pgw/Plugin.py | 111 - pgworksheet_yvesf/pgw/QueryView.py | 223 -- pgworksheet_yvesf/pgw/ResultView.py | 291 -- pgworksheet_yvesf/pgw/RunSQL.py | 167 - pgworksheet_yvesf/pgw/Syntax.py | 782 ----- pgworksheet_yvesf/pgw/UI.py | 937 ------ pgworksheet_yvesf/pgw/Undo.py | 106 - pgworksheet_yvesf/pgw/Widgets.py | 389 --- pgworksheet_yvesf/pgw/__init__.py | 105 - pgworksheet_yvesf/pgworksheet.py | 7 - pgworksheet_yvesf/pixmaps/pgworksheet.png | Bin 1291 -> 0 bytes pgworksheet_yvesf/pixmaps/pgworksheet/about.png | Bin 320 -> 0 bytes pgworksheet_yvesf/pixmaps/pgworksheet/connect.png | Bin 594 -> 0 bytes .../pixmaps/pgworksheet/disconnect.png | Bin 581 -> 0 bytes .../pixmaps/pgworksheet/pgworksheet-32.png | Bin 1291 -> 0 bytes .../pixmaps/pgworksheet/pgworksheet.ico | Bin 16958 -> 0 bytes .../pixmaps/pgworksheet/pgworksheet.png | Bin 14247 -> 0 bytes .../pixmaps/pgworksheet/pgworksheet.xcf | Bin 21321 -> 0 bytes pgworksheet_yvesf/plugins/README_PLUGINS | 40 - .../plugins/queryView/QueryViewNullPlugin.py | 19 - .../plugins/resultView/ResultViewGraph.py | 177 -- .../plugins/resultView/ResultViewNull.py | 19 - .../plugins/resultView/ResultViewSaveXML.py | 33 - .../plugins/sidebar/FunctionBrowser.py | 165 - pgworksheet_yvesf/plugins/sidebar/PgStats.py | 241 -- pgworksheet_yvesf/plugins/sidebar/PgStatus.py | 34 - pgworksheet_yvesf/plugins/sidebar/ShowConfig.py | 85 - pgworksheet_yvesf/trash/pgworksheet | 578 ---- pgworksheet_yvesf/trash/setup.py | 37 - 71 files changed, 13651 deletions(-) delete mode 100644 pgworksheet_1.9/ABOUT_THIS_REPOSITORY delete mode 100644 pgworksheet_1.9/AUTHORS delete mode 100644 pgworksheet_1.9/LICENSE.txt delete mode 100644 pgworksheet_1.9/README delete mode 100644 pgworksheet_1.9/applications/pgworksheet.desktop delete mode 100644 pgworksheet_1.9/locale/fr/LC_MESSAGES/pgworksheet.mo delete mode 100644 pgworksheet_1.9/locale/ja/LC_MESSAGES/pgworksheet.mo delete mode 100644 pgworksheet_1.9/pgw/DBConnection.py delete mode 100644 pgworksheet_1.9/pgw/Execute.py delete mode 100644 pgworksheet_1.9/pgw/Lexical.py delete mode 100644 pgworksheet_1.9/pgw/MyPgSQL.py delete mode 100644 pgworksheet_1.9/pgw/RunSQL.py delete mode 100644 pgworksheet_1.9/pgw/Syntax.py delete mode 100644 pgworksheet_1.9/pgw/UI.py delete mode 100644 pgworksheet_1.9/pgw/Undo.py delete mode 100644 pgworksheet_1.9/pgw/__init__.py delete mode 100755 pgworksheet_1.9/pgworksheet delete mode 100644 pgworksheet_1.9/pixmaps/pgworksheet.png delete mode 100644 pgworksheet_1.9/pixmaps/pgworksheet/about.png delete mode 100644 pgworksheet_1.9/pixmaps/pgworksheet/connect.png delete mode 100644 pgworksheet_1.9/pixmaps/pgworksheet/disconnect.png delete mode 100644 pgworksheet_1.9/pixmaps/pgworksheet/pgworksheet-32.png delete mode 100644 pgworksheet_1.9/pixmaps/pgworksheet/pgworksheet.ico delete mode 100644 pgworksheet_1.9/pixmaps/pgworksheet/pgworksheet.png delete mode 100644 pgworksheet_1.9/pixmaps/pgworksheet/pgworksheet.xcf delete mode 100644 pgworksheet_1.9/setup.py delete mode 100644 pgworksheet_yvesf/Makefile delete mode 100644 pgworksheet_yvesf/TODO delete mode 100644 pgworksheet_yvesf/applications/pgworksheet.desktop delete mode 100644 pgworksheet_yvesf/doc/AUTHORS delete mode 100644 pgworksheet_yvesf/doc/LICENSE.txt delete mode 100644 pgworksheet_yvesf/doc/README delete mode 100644 pgworksheet_yvesf/locale/de/LC_MESSAGES/pgworksheet.mo delete mode 100644 pgworksheet_yvesf/locale/de/LC_MESSAGES/pgworksheet.po delete mode 100644 pgworksheet_yvesf/locale/fr/LC_MESSAGES/pgworksheet.mo delete mode 100644 pgworksheet_yvesf/locale/ja/LC_MESSAGES/pgworksheet.mo delete mode 100644 pgworksheet_yvesf/locale/pgworksheet.pot delete mode 100644 pgworksheet_yvesf/pgw/ConnectDialog.py delete mode 100644 pgworksheet_yvesf/pgw/DBConnection.py delete mode 100644 pgworksheet_yvesf/pgw/Execute.py delete mode 100644 pgworksheet_yvesf/pgw/Lexical.py delete mode 100644 pgworksheet_yvesf/pgw/Notice.py delete mode 100644 pgworksheet_yvesf/pgw/Plugin.py delete mode 100644 pgworksheet_yvesf/pgw/QueryView.py delete mode 100644 pgworksheet_yvesf/pgw/ResultView.py delete mode 100755 pgworksheet_yvesf/pgw/RunSQL.py delete mode 100644 pgworksheet_yvesf/pgw/Syntax.py delete mode 100644 pgworksheet_yvesf/pgw/UI.py delete mode 100644 pgworksheet_yvesf/pgw/Undo.py delete mode 100644 pgworksheet_yvesf/pgw/Widgets.py delete mode 100644 pgworksheet_yvesf/pgw/__init__.py delete mode 100755 pgworksheet_yvesf/pgworksheet.py delete mode 100644 pgworksheet_yvesf/pixmaps/pgworksheet.png delete mode 100644 pgworksheet_yvesf/pixmaps/pgworksheet/about.png delete mode 100644 pgworksheet_yvesf/pixmaps/pgworksheet/connect.png delete mode 100644 pgworksheet_yvesf/pixmaps/pgworksheet/disconnect.png delete mode 100644 pgworksheet_yvesf/pixmaps/pgworksheet/pgworksheet-32.png delete mode 100644 pgworksheet_yvesf/pixmaps/pgworksheet/pgworksheet.ico delete mode 100644 pgworksheet_yvesf/pixmaps/pgworksheet/pgworksheet.png delete mode 100644 pgworksheet_yvesf/pixmaps/pgworksheet/pgworksheet.xcf delete mode 100644 pgworksheet_yvesf/plugins/README_PLUGINS delete mode 100644 pgworksheet_yvesf/plugins/queryView/QueryViewNullPlugin.py delete mode 100644 pgworksheet_yvesf/plugins/resultView/ResultViewGraph.py delete mode 100644 pgworksheet_yvesf/plugins/resultView/ResultViewNull.py delete mode 100644 pgworksheet_yvesf/plugins/resultView/ResultViewSaveXML.py delete mode 100644 pgworksheet_yvesf/plugins/sidebar/FunctionBrowser.py delete mode 100644 pgworksheet_yvesf/plugins/sidebar/PgStats.py delete mode 100644 pgworksheet_yvesf/plugins/sidebar/PgStatus.py delete mode 100644 pgworksheet_yvesf/plugins/sidebar/ShowConfig.py delete mode 100755 pgworksheet_yvesf/trash/pgworksheet delete mode 100644 pgworksheet_yvesf/trash/setup.py diff --git a/pgworksheet_1.9/ABOUT_THIS_REPOSITORY b/pgworksheet_1.9/ABOUT_THIS_REPOSITORY deleted file mode 100644 index 26373a8..0000000 --- a/pgworksheet_1.9/ABOUT_THIS_REPOSITORY +++ /dev/null @@ -1 +0,0 @@ -This repository tracks my personal changes on pgw' sourcecode diff --git a/pgworksheet_1.9/AUTHORS b/pgworksheet_1.9/AUTHORS deleted file mode 100644 index 096c148..0000000 --- a/pgworksheet_1.9/AUTHORS +++ /dev/null @@ -1 +0,0 @@ -Henri Michelon hmichelon at e-cml.org diff --git a/pgworksheet_1.9/LICENSE.txt b/pgworksheet_1.9/LICENSE.txt deleted file mode 100644 index 5b6e7c6..0000000 --- a/pgworksheet_1.9/LICENSE.txt +++ /dev/null @@ -1,340 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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. diff --git a/pgworksheet_1.9/README b/pgworksheet_1.9/README deleted file mode 100644 index 6f685f2..0000000 --- a/pgworksheet_1.9/README +++ /dev/null @@ -1,23 +0,0 @@ -== General Informations == - -PgWorksheet is a simple GUI frontend to PostgreSQL -for executing SQL queries without using the psql command line tool. - -More informations on : http://pgworksheet.projects.postgresql.org/ - -== Operating systems == -PgWorksheet is certified to run on the following operating systems: - * FreeBSD - * Linux Ubuntu - * Linux Fedora - * Linux Mandriva - * Microsoft Windows XP - -== Depencies == -PgWorksheet requires the following softwares to run : - * Python 2.4 or better - * Python GTK+ 2.6 or better - * python-pgsql 0.9.7 (or better) or pyPgSQL - -== Installation == -Please refers to http://pgworksheet.projects.postgresql.org/install.html for installation instructions. diff --git a/pgworksheet_1.9/applications/pgworksheet.desktop b/pgworksheet_1.9/applications/pgworksheet.desktop deleted file mode 100644 index a2c16da..0000000 --- a/pgworksheet_1.9/applications/pgworksheet.desktop +++ /dev/null @@ -1,11 +0,0 @@ -[Desktop Entry] -Name=PgWorksheet -GenericName= -Comment=PostgreSQL SQL Tool -Categories=Application;Development;Databases; -Encoding=UTF-8 -Exec=pgworksheet -Icon=pgworksheet.png -StartupNotify=true -Terminal=false -Type=Application diff --git a/pgworksheet_1.9/locale/fr/LC_MESSAGES/pgworksheet.mo b/pgworksheet_1.9/locale/fr/LC_MESSAGES/pgworksheet.mo deleted file mode 100644 index 738dfdf73bd954b9dfbe1e9cfa8f8e11e0551de0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcwPel00001 literal 6209 zcwU`XTWlOx89u$?#Ifs3Y_CI7I4N=6Bwk;Vnucwf#I>C`jc;+BRFsF+?C$aIB;%RQ zTz2Ck5C|kdLP9(gkPxT{9%7&p;)NoFida-sAzlyy(T6+$PZ2Mu5(Nna-+%ryJF^=* z1V*0y&Ybg~|NQs!`%eF(uL?ZNcn{(I;=@AR0RHn)p`Y9D6QU2e4eSK|1b7hm7O)ri zN8ks5?*bnO_IC)e2Y47b3_RAs^RvJq;2Q8TpxwcIJ>Y)er-6gOSAib{ey@Z1{>t#X zYv|tXU^zSXFx?U02yhPg6!1C_qKGf=;eB5->)!&71Aht30{;di6_4x%FW}L=%y$Yn z3S0)_Pt?r(r+_`cZ|r6LUk82!`1W2t=Mfm^NnjW7FmM9+Q{ZLbX<*MjK5ua!+wC%N z09Y{Jb>RDfpEvX0HuG~l9-kXvfB$fR^Xf+fEXS`0nD2W7tpDI3$5C#O?Q(UH^U4EG z0Ka6`-yGyTdS{UHkb>up<&LG zW59=m(ZxJO{{r6U1>5GN;2a|UGkBjBEGy|vF+uz&)_ctU7X_b9aY{N<-cyaBdNXcl zP+qm2NLR||C6PQA1;`*Vm|R8C7zhG1M?*}d~Z{4Z5}-D`_MV2cFV+j zB*={f=k%{xuUB9%S%hIV4b8x!G_+mWM&(tNYlz4ZG}On&WHHE`n7^fp5genH@!U|k z@W6)tymEO_79!Z)7Z*HPu!=Y8P?V0NRmB@iG6=0uZDL;_D{!~xZxQ*1=RYX*f)|8h z(Jm?%##r>Ml0LZ^jU>1wH=vhT@_Yr3;Js;SFId{&Avj5^T6OHAo)*hq997K`*~0Z& zBa0T(p|$LVu^T|q8Xfmp8}FR+z?O`RYy^5*)9y}I4P3xPKZ%=9kQPtN-LC=Fs$Y#ChGP2c$LY5o6flB zmnT3AeU!{edqYbefo1yaloBCXaFeKGeNhBlXKPGvEP3uI6jf}Kd!>>VJcG3HYw+)Q zEPdUw!!Z*RI^baht_qf0k{c>4R^n+>cgDxD+4DnjIkH2&uG@2z`WAp ze7j=RR62_8nP3moW+yv6Qo;8s2wNUIp0IS3$3m!T8?;ZX@Ns^D{LXr z5!0+{$`mz9I9alTs$*@5b$`p$k=ToH!|B4Ak*DEk|7dV}qHu;*^;D@~CXi2hq5|*n zl(_2dVBD+VA@aJ^l4bIyoHhsY3f!%Hy_OU{k)JQw_&ram)}Wl)a|> z0QSns)eA4JtX;aYFh9R8J6BiMv$ML2du|qYh04hjlanX2lhfG~r{vUR?&S3GNz8yS zy9RxOgzlsBGi%wUmF(P%Tv*91T|EBs%JO{YB3zSQ_boSYELbxq7nJMUa>*`Mltb!N zHsc|Rg31;*brCp&jcz%z$|}3Atj(M}?<1Bfol6&&<`dDU#wR;xxmsn{x2h0=;&B2| zX1mYnFbq`q{MGgI*;5G}$%0!W8(+9Nd8%NCozyBQ-&c{(T|;A=lE4bvz9h;DG*D#( zhi|S5F3}*-Ja%1NRLB(64&(*85Z!&CY&Ev8H(nc)H7|11E7=+akTcrYF8U}%zV1j^ zD(W<1DbiySD1Bn{K-%f$>m9hx$fQD`$?MmCH`^gPt8|A1M z)v%}uApwzb6QrZipl*Y}C8A>;nB7-5qsDhb$hU?o$|3QIw=>Eui;axe?oqspJzKNf z;sa6Y@`!MYTOMjr%i2V#lkruJ(AGq59MUZzQ&b^BJKgi3yP$<6f?Fmyic6!r#j7UX zb@dwMj62GLRjp>{-PqpM|Nr}z&TEvQ0VilJ)!)N3nb9a@p3Ek)+v{pfL7oAS_#Fm}pL`9OcgRaA*?`o=6 zMX;}mj=I|FoYZUmc9=L0L1(a~yC zrNf#GtykMJjq@fI?S?4S<(epy>ms#3pGtwS~6p+yZsUmq_d2>NH<|7xCbGgaCS2_#eV?I=F)ip diff --git a/pgworksheet_1.9/locale/ja/LC_MESSAGES/pgworksheet.mo b/pgworksheet_1.9/locale/ja/LC_MESSAGES/pgworksheet.mo deleted file mode 100644 index 2beed8722041864d36676256a1c9b527257854a8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcwPel00001 literal 5664 zcwVhmdr(x@89#|y1tP)%O`BGGTT8n{7ePy^M2!~l6(1<5owPGMm)!$wT=(L=7m?0% z#@+P^rco0_Bfe4}_yA+A3BI81WTw+;rqkrVwv*IY54L-{l2R@w2WY?Nb_D(3h zGtTT1UEU@`D-!0!NEP{t8#$qd@JVg{|R1C{~}pa*ykC_?-Qh^_478D#fQ!0!V8 z3Cse{$s)NMI15;vMe%RTBKy06-va&w_)Xwh;8NgV7TJH2MR|HAo6rS(0XP>}2wbk@ zwQBCqrnuXb{FKta2Fw9|m`!>7Bd`QG3|tG$&!O{P%OStLIpkje=mMHKwEsX3<^Q+kA{610praXrn1G9iLf$M=&fIn389|Q5nUdPY3pJA+3 zAm-gODWAWdNqPHtCh_G9;P-&ffi!c0D|3lI96uV+20jn$%q4$%b7|ji6#fPHRp38z zsZO~#qzw3?!XM3|d>oxcc|NajU>4Q=(^sd{nzuUSGyH*2Bdel) znr&#h=GSe#Ubi@;&25^+gJe-G+D%;Z1q03XhHm;<6)aD(yeeTQF-UQbtqNFbrZt$x zF1dB|;A+!E%n9vKqp)3URTf(-GBy~xU!FY5M&Y=wH6Sjw(J(nI!uBp*Rza8b zwqZ%ro123HpA@rAMuJtNBaw@ckhN? zb?LCp_u6SHGQFc0nX7v&IHvgnR&!8qV|8Ymx;lxArd!(5`sKy$7K@uD*3t#_%f+e` z`RkPc6q14_)QCiE8`POsHWHBpuWA;f1Fe>uXlHUQd99hZ+8@C0YT>naEe|&1SMl4s zNyL*RKJ#wI{Y)*5G&b7SQZ+M+C^ZFzu(mzGTUnB?|6{z#z9Vc0jYbwqy#_3;TZ3$` zL+n}S_iX2;g}YX%)vVdEdF!jSYpbj4wCtMAb)G8Oql}OTosd^*3(LwDdCDq03m0qU zWtEF6=9NJLMbB2mYo+N`c!cUpTG^t?g^TBvErH$!TsKdhsfVnfj%-$Hb-G`-ngZH- zW2fF2(3bLG19q0J5Mf)TmeFGRIEc~6OGDgVj{Tv=7QK;s>bSnEQd_S#>mhFO?2YR- zRwrX9FD=WiqU-FbYiou#f`bddtU%~xNj;0(%eK|6_AE~738&B;J&Es1rM9>}U}uXj zVr*ZB6Yd*6aCPY6J5KmU?9%OcXO|Pk-+=r*pQ3d4So~af=G+N)#2(##e14GBM=l-} z8h{k(s3}Wx!nfjG?~0RpPsO@>63eHZeUYL5_V}58C;UcI814|C;ivmpp6+7#(>yGn zz`+XmcWLOs<=7E8(HH;O<>B|=No$fg9vV(~zZ1SP@k0FMp;&L16X|iHcbv!_C;HHd z9&vlCOPCWqBxaF8Cwf{A?qQ=k=W)0{-hR%BoRC}I7R$n`D^BE=6TR+4qfWHTiFT7U zC)}Uh5IcOxiL}StyXpK1H;g@fGKYrxd&gbwa3V)=V*F$;OZoUC1O1~p!&Z!C0&gh6FJdiG6$Vb zO7us%rx0;+xdYKJJ>?aT4rUkZ(Zqw$jnwtx8QgIGuBq^d{WNK{31cHuTla2~!!uq?R^f8I)6xGs5;c`L@*Ge+Z9rp6@vQS22* zCAE*s)Z8LYvI&@)EY!#^V6uJa!6_$veDeQRoalbJ{RT@kioQh6dJ>`c#ojy_8|aGP zLEpJbO-DNU9x4H@IpOx$zyT+GQI0P-;Z8U&zBNwtth6mE3O{?D$a|7#7vSOW-N?}W zgDjmas9httHZ-vD-#Z9oOXer)O?` ziu$N!YCO_GO8r46(o39A-`Pi+Y~*6k@TL31Z}*4}FvsF;P$Q-f>R 0) : - # psql commands - if (sql[0] == '\\'): - sql = string.replace(sql, '\\\\', '\\') - if (pgw.mswindows()): - cmd = "psql.exe" - sql = string.strip(sql) - else: - cmd = "psql" - if (self.db.user is not None): - cmd += ' -U "' + self.db.user + '"' - if (self.db.host is not None): - cmd += ' -h "' + self.db.host + '"' - if (self.db.port is not None): - cmd += ' -p ' + self.db.port - if (self.db.database is not None): - cmd += ' -d "' + self.db.database + '"' - cmd += ' -c "' + sql + '"' - if (self.db.password is not None): - os.putenv("PGPASSWORD", self.db.password) - #os.putenv("PGCLIENTENCODING", pgw.get_user_encoding()) - output, input = popen2.popen4(cmd) - result = output.read() - output.close() - input.close() - #os.putenv("PGCLIENTENCODING", "") - os.putenv("PGPASSWORD", "") - return { 'text' : result } - else: - # SQL query - return self.db.query(sql) - - - def execute(self, buffer): - """Execute SQL queries or psql commands""" - if not self.db.is_connected() : return - # SQL query - sqls = self.split(buffer) - if (len(sqls) > 1): - # multiple queries - results = [] - for sql in sqls: - sql = string.strip(sql) - if (len(sql) > 0): - results.append(self.execute_one(sql)) - if (len(results) == 1): - return results[0] - return results - else: - # unique query - return self.execute_one(sqls[0]) - - - def split(self, oldbuffer): - """Split multiple queries""" - # a new textbuffer, because we don't want to modify the original - buffer = gtk.TextBuffer() - buffer.set_text(oldbuffer.get_text(oldbuffer.get_start_iter(), - oldbuffer.get_end_iter())) - # filter comments - tokens = self.lexical.analyse(buffer, buffer.get_start_iter(), - buffer.get_end_iter()) - for token in tokens: - if (token.token == 'comment'): - buffer.delete(token.start_iter, token.end_iter) - - # restart without the comments - buffer.set_text(buffer.get_text(buffer.get_start_iter(), - buffer.get_end_iter())) - start = buffer.get_start_iter() - end = buffer.get_end_iter() - tokens = self.lexical.analyse(buffer, start, end) - - # create a list of queries - sql = buffer.get_text(start, end) - parts = [] - stop = start - while (len(tokens) > 0): - token = tokens.pop(0) - if (token.token == 'psql'): - i = token.start_iter - i.backward_char() - parts.append(buffer.get_text(stop, i)) - parts.append(token.value) - stop = token.end_iter - elif (token.value == ';'): - i = token.start_iter - parts.append(buffer.get_text(stop, i)) - stop = token.end_iter - if (stop != end): - parts.append(buffer.get_text(stop, end)) - return parts diff --git a/pgworksheet_1.9/pgw/Lexical.py b/pgworksheet_1.9/pgw/Lexical.py deleted file mode 100644 index 9530d08..0000000 --- a/pgworksheet_1.9/pgw/Lexical.py +++ /dev/null @@ -1,357 +0,0 @@ -#!/usr/bin/env python -# -*- coding: latin-1; -*- -# -# PgWorksheet - PostgreSQL Front End -# http://pgworksheet.projects.postgresql.org/ -# -# Copyright © 2004-2008 Henri Michelon & CML http://www.e-cml.org/ -# -# 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 (read LICENSE.txt). -# -# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# $Id: Lexical.py,v 1.9 2008/03/12 20:26:23 hmichelon Exp $ -# - -# http://www.postgresql.org/docs/8.0/static/sql-syntax.html - -# basic characters sets -SPACES = [ ' ', '\t', '\n' ] -DIGITS = [ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' ] -NUMERIC = DIGITS + [ 'e', '.', '+', '-' ] -OPERATOR_CHARS = [ '+', '-', '*', '/', '<', '>', '=', '~', '!', \ - '@', '#', '%', '^', '&', '|', '`', '?' ] -SPECIAL_CHARS = [ '(', ')', '[', ']', ',', ';', ':', '*', '.' ] -OPERATORS = OPERATOR_CHARS + SPECIAL_CHARS - -# not the first character of an identifier -NOT_IDENT_START = SPECIAL_CHARS + OPERATOR_CHARS + DIGITS + [ '$' ] -# not a character of an identifier -NOT_IDENT_CHAR = SPECIAL_CHARS + OPERATOR_CHARS + SPACES + [ "'" ] -# not a character of a dollar quoted string -NOT_DOLLAR_QUOTED = [ '$' ] + SPACES - - -class Token: - - def __init__(self, token, start_iter, end_iter, value=None): - self.token = token - self.start_iter = start_iter - self.end_iter = end_iter - self.value = value - - -class Eob: - """End of Buffer Exception""" - - -class Lexical: - """Simplified lexical analyser""" - - def analyse(self, buffer, start, end): - """Run the lexical analyser""" - self.buffer = buffer - self.current = start.copy() - self.tokens = []; - try: - self.lexical_analyser(end.copy()) - except Eob: - pass - return self.tokens - - - def next_char(self): - """Returns the next character to analyse""" - if (self.current.is_end()): - raise Eob() - c = self.current.get_char() - self.current.forward_char() - return c - - - def skip_spaces(self, c): - """Skips everything that looks like a space/tab/etc...""" - while (c in SPACES): - c = self.next_char() - return c - - - def string(self): - """Single quoted strings""" - start = self.current.copy() - start.backward_char() - prev = None - c = self.next_char() - try: - while (True): - if ((c == "'") and (prev != '\\')): # a single quote in the string... - c = self.next_char() - if (c != "'"): - break - prev = c - c = self.next_char() - except Eob: - end = self.current.copy() - self.tokens.append(Token('string', start, end)) - raise - end = self.current.copy() - end.backward_char() - self.tokens.append(Token('string', start, end)) - return c - - - def dollar_string(self): - """Dollar-quoted strings""" - # first bound - start = self.current.copy() - start.backward_char() - c = self.next_char() - string_tag = '' - try: - while (c not in NOT_DOLLAR_QUOTED): - string_tag = string_tag + c - c = self.next_char() - except Eob: - end = self.current.copy() - self.tokens.append(Token('identifier', start, end, string_tag.upper())) - raise - end = self.current.copy() - end.backward_char() - if (c != '$'): - self.tokens.append(Token('identifier', start, end, string_tag.upper())) - return c - self.tokens.append(Token('dollarquote', start, end, string_tag.upper())) - - # string content - start = self.current.copy() - try: - c = self.next_char() - except Eob: - end = self.current.copy() - self.tokens.append(Token('identifier', start, end, string_tag.upper())) - raise - try: - while (True): - if (c == '$'): - string_end = self.current.copy() - c = self.next_char() - s = '' - while (c not in NOT_DOLLAR_QUOTED): - s = s + c - c = self.next_char() - if (s == string_tag): - string_end.backward_char() - self.tokens.append(Token('string', start, string_end)) - end = self.current.copy() - end.backward_char() - self.tokens.append(Token('dollarquote', start, end, s.upper())) - return c - else: - c = self.next_char() - except Eob: - end = self.current.copy() - self.tokens.append(Token('string', start, end)) - raise - end = self.current.copy() - end.backward_char() - self.tokens.append(Token('string', start, end)) - return c - - - def bit_string_constant(self, start): - """Binary and Hexadecimal numeric constants using strings""" - c = self.next_char() - if (c == "'"): - c = self.next_char() - start = self.current.copy() - start.backward_char() - start.backward_char() - start.backward_char() - while (c != "'"): - c = self.next_char() - end = self.current.copy() - self.tokens.append(Token('numeric_constant', start, end)) - return self.next_char() - else: - return self.identifier(c, start) - - - def identifier(self, c, ident = ''): - """An identifier, keyword, type name, etc...""" - start = self.current.copy() - for i in range(0, len(ident) + 1): - start.backward_char() - try: - while (c not in NOT_IDENT_CHAR): - ident = ident + c - c = self.next_char() - except Eob: - end = self.current.copy() - self.tokens.append(Token('identifier', start, end, ident.upper())) - raise - end = self.current.copy() - end.backward_char() - self.tokens.append(Token('identifier', start, end, ident.upper())) - return c - - - def numeric(self, c): - """A numeric constant""" - start = self.current.copy() - start.backward_char() - try: - while (c in NUMERIC): - c = self.next_char() - except Eob: - end = self.current.copy() - self.tokens.append(Token('numeric_constant', start, end)) - raise - end = self.current.copy() - end.backward_char() - self.tokens.append(Token('numeric_constant', start, end)) - return c - - - def simple_comment(self): - """One line comment using --""" - start = self.current.copy() - start.backward_char() - start.backward_char() - c = self.next_char() - try: - while (c != '\n'): - c = self.next_char() - except Eob: - end = self.current.copy() - self.tokens.append(Token('comment', start, end)) - raise - end = self.current.copy() - self.tokens.append(Token('comment', start, end)) - - - def comment(self): - """Multi lines comments using /* */""" - start = self.current.copy() - start.backward_char() - start.backward_char() - c = self.next_char() - prev = None - nested = 0 - try: - while (True): - if (c == '*'): - c = self.next_char() - if (prev == '/'): - nested = nested + 1 - continue - if (c == '/'): - if (nested == 0): - c = self.next_char() - break - else: - nested = nested - 1 - else: - prev = c - continue - prev = c - c = self.next_char() - except Eob: - end = self.current.copy() - self.tokens.append(Token('comment', start, end)) - raise - end = self.current.copy() - end.backward_char() - self.tokens.append(Token('comment', start, end)) - return c - - - def psql(self): - """A PgSQL Command""" - start = self.current.copy() - start.backward_char() - c = self.next_char() - cmd = '\\' - try: - while (c != '\n') and (c != ';'): - cmd = cmd + c - c = self.next_char() - except: - end = self.current.copy() - self.tokens.append(Token('psql', start, end, cmd)) - raise - end = self.current.copy() - self.tokens.append(Token('psql', start, end, cmd)) - - - def lexical_analyser(self, fin): - """A simplified lexical analyser""" - c = self.next_char() - while (self.current.compare(fin) <= 0): - c = self.skip_spaces(c) - # Multi lines comments - if (c == '/'): - c = self.next_char() - if (c == '*'): - c = self.comment() - continue - else: - self.current.backward_char() - # One line comments - elif (c == '-'): - c = self.next_char() - if (c == '-'): - self.simple_comment() - else: - self.current.backward_char() - # psql commands - elif (c == '\\'): - self.psql() - # numeric - elif (c in DIGITS): - c = self.numeric(c) - continue - # bit strings - elif (c == 'B') or (c == 'b') or (c == 'H') or (c == 'h'): - c = self.bit_string_constant(c) - continue - # strings - elif (c == "'"): - c = self.string() - continue - # dollar-quoted strings - elif (c == '$'): - c = self.dollar_string() - continue - # numeric - elif (c == '.'): - c = self.next_char() - if (c in DIGITS): - self.current.backward_char() - c = self.numeric(self.current.get_char()) - continue - # quoted identifiers - elif (c == '"'): - c = self.next_char() - while (c != '"'): - c = self.next_char() - # operators - elif (c in OPERATORS): - start = self.current.copy() - start.backward_char() - end = self.current.copy() - self.tokens.append(Token('operator', start, end, c)) - # everything else - elif (c not in NOT_IDENT_START): - c = self.identifier(c) - continue - c = self.next_char() diff --git a/pgworksheet_1.9/pgw/MyPgSQL.py b/pgworksheet_1.9/pgw/MyPgSQL.py deleted file mode 100644 index a9f3cd4..0000000 --- a/pgworksheet_1.9/pgw/MyPgSQL.py +++ /dev/null @@ -1,3257 +0,0 @@ -#ident "@(#) $Id: MyPgSQL.py,v 1.2 2004/11/24 10:31:07 hmichelon Exp $" -# vi:set sw=4 ts=8 showmode ai: -#--(H+)-----------------------------------------------------------------+ -# Name: PgSQL.py | -# | -# Description: This file implements a Python DB-API 2.0 interface to | -# PostgreSQL. | -#=======================================================================| -# Copyright 2000 by Billy G. Allie. | -# All rights reserved. | -# | -# Permission to use, copy, modify, and distribute this software and its | -# documentation for any purpose and without fee is hereby granted, pro- | -# vided that the above copyright notice appear in all copies and that | -# both that copyright notice and this permission notice appear in sup- | -# porting documentation, and that the copyright owner's name not be | -# used in advertising or publicity pertaining to distribution of the | -# software without specific, written prior permission. | -# | -# THE AUTHOR(S) DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, | -# INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN | -# NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY SPECIAL, INDIRECT OR | -# CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS | -# OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE | -# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE | -# USE OR PERFORMANCE OF THIS SOFTWARE. | -#=======================================================================| -# Revision History: | -# | -# Date Ini Description | -# --------- --- ------------------------------------------------------- | -# 05JUL2003 bga - Fixed a problem with PgNumeric where an exception can | -# be thrown if the stated scale and precision of the | -# returned in the first result row does not match later | -# rows. | -# 26JUN2003 bga - Applied patch from Laurent Pinchart to allow _quote | -# to correctly process objects that are sub-classed | -# from String and Long types. | -# 05JUN2003 bga - Change the name of the quoting function back to | -# _quote. Variables named like __*__ should be restrict | -# to system names. | -# 02JUN2003 bga - PgTypes is now hashable. repr() of a PgType will now | -# return the repr() of the underlying OID. | -# - Connection.binary() will now fail if autocommit is | -# enabled. | -# - Connection.binary() will no longer commit the trans- | -# action after creating the large object. The applica- | -# tion developer is now responsible for commiting (or | -# for rolling back) the transaction [Bug #747525]. | -# - Added PG_TIMETZ to the mix [Patch #708013]. | -# - Pg_Money will now accept a string as a parameter. | -# - PostgreSQL int2, int, int4 will now be cast into | -# Python ints. Int8 will be cast into a Python long. | -# Float4, float8, and money types will be cast into | -# a Python float. | -# 07MAR2003 bga - Correct problem with the PgNumeric.__radd__ method. | -# [Bug #694358] | -# - Correct problem with conversion of negitive integers | -# (with a given scale and precision) to PgNumerics. | -# [Bug #694358] | -# - Work around a problem where the precision and scale | -# of a query result can be different from the first re- | -# sult in the result set. | -# [Bug #697221] | -# 12JAN2003 bga - Change the code so that the display length in the | -# cursor.description attribute is always None instead | -# of '-1'. | -# - Fixed another problem with interval <-> DateTimeDelta | -# casting. | -# 23DEC2002 bga - Corrected a problem that caused the close of a portal | -# (ie. PostgreSQL cursor) to fail. | -# 13DEC2002 bga - Corrected a problem with interval <-> DateTimeDelta | -# casting. [Bug #653044] | -# 06DEC2002 bga - Corrected problem found by Adam Buraczewski in the | -# __setupTransaction function. | -# - Allow both 'e' and 'E' to signify an exponet in the | -# PgNumeric constructor. | -# 04DEC2002 bga - Correct some problems that were missed in yesterday's | -# fixes (Thanks, Adam, for the help with the problems) | -# 03DEC2002 bga - Fixed various problems with the constructor and the | -# formatting routine. These correct the problems re- | -# ported by Adam Buraczewski. | -# 01DEC2002 bga - Fixed problems with new __setupTransaction function: | -# 1. Made it a method of Connection, not Cursor. | -# 2. inTransaction was only set if TransactionLevel was | -# set. | -# - Fixed instances where method name was incorrect: | -# Connection__gcCursor -> _Connection__gcCursor | -# Connection__closeCursor -> _Connection__closeCursor | -# - Cleaned up code where there was unneeded references | -# to conn in Connection class. | -# 01DEC2002 gh - Handle the new '__quote__' method for arrays, too. | -# - Still handle '_quote' methods for backwards compati- | -# bility. This will will avoid complaints by users | -# who have code depending on this. Like me. | -# 28NOV2002 bga - Fixed changed PG_TIMESTAMP oid, added PG_TIMESTAMPTZ | -# and PG_REFCURSOR oids. [Bug #845360] | -# - Reference cursors are now type-casted into cursor ob- | -# jects. | -# 27NOV2002 bga - Completed the emulation of a String object for the | -# PgBytea and PgOther classes. This corrects several | -# problems with PgBytea concerning comparisons, using | -# PgBytea types as keys in dictionaries, etc. | -# 10NOV2002 bga - Added the __hash__ function to the PgNumeric class. | -# Cleaned up the code in PgNumeric class and made some | -# small improvments to it. | -# 02NOV2002 bga - Added the PgArray class. This is a wrapper around a | -# Python list and is used for all PostgreSQL arrays. | -# This change was made so that lists and tuples no | -# longer have a special meaning in the Cursor.execute() | -# method. | -# - Changed the quoting methods defined in the various | -# classes defining PostgreSQL support types to __quote__| -# 27OCT2002 gh - Merged the Unicode patch. Closes #484468. | -# - Convert ROWID to PgInt8 instead of PgInt4 (the origi- | -# nal behaviour led to overflow errors.) | -# - Always set the displaysize field of | -# cursor.description to -1. PostgreSQL 7.3 doesn't | -# provide this information any more and it's pretty | -# useless nowadays that we've mostly left line printers | -# beyond us. | -# 26OCT2002 bga - Column access by name (attribute and dictionary) now | -# supports mixed-case column name. Be aware that if | -# you define mixed-case column names in the database, | -# you have to use the mixed-case name to access the co- | -# lumn or it will not be found. For column names that | -# were not defined with mixed-case in the database, the | -# column access by name is case insensitive. | -# 02OCT2002 gh - Only support mxDateTime 2.x and give useful error | -# message if import fails. | -# - Cosmetic changes: use cmp builtin where appropriate. | -# - Fixed typo where PgTypes.__str__ was spelled | -# incorrectly. Compare to None using "is" operator. | -# - Take into account that libpq.PgInt8Type might not be | -# available. | -# - Add support for the INTERVAL type. | -# 08SEP2002 gh Fixed various problems with the PgResultSet: | -# - Column (attribute and dictionary) access is now case- | -# insensitive. | -# - Added __contains__ method. | -# - Added default value parameter to get method. | -# - Made setattr actually work. | -# 11AUG2002 bga Fixed various problems with the PgNumeric type: | -# - Added code to allow a float as an argument to the | -# PgNumeric constructor. | -# - You can now change the precision/scale of a PgNumeric | -# by: a = PgNumeric(pgnumeric, new prec, new scale). | -# This can be used to 'cast' a PgNumeric to the proper | -# precision and scale before storing it in a field. | -# - The arithmatic routines (__add__, __radd__, etc) now | -# ensure that the arguments are properly coerced to the | -# correct types. | -# - Added support for the augmented arithmatic operations | -# (__iadd__, etc). | -# - The math routines would lose precision becuase the | -# precision/scale were set to be the same as the first | -# operand. This is no longer the case all precision is | -# retained for the +, -, and * operations. | -# 03AUG2002 gh - Fixed problem that occurs when a query on an OID | -# field doesn't return any rows. [Bug #589370]. | -# 29JUL2002 gh - Applied patch #569203 and also added __pos__ and | -# __abs__ special methods to PgNumeric. | -# 15MAY2002 gh - Got rid of redundant building and storing of the | -# mapping of column names to column positions in the | -# PgResultSet class. Now, rows of the same query are | -# instances of a dynamically created class, which has | -# this mapping as a class attribute instead of an at- | -# tribute of the instance. This saves a lot of space, | -# and also slightly increases performance of cursor | -# fetches. | -# 21APR2002 gh - Improved the array parsing, so that it now passes all | -# the new mean testcases. Added support for parsing | -# multidimensional arrays. Eventually, the array par- | -# sing code should go as a support function into libpq. | -# - Replaced all typechecks with "is" operators instead | -# of equals. Mark McEahern had a problem with using | -# pyPgSQL in combination with a FixedPoint class where | -# the reason was that the FixedPoint class was not com- | -# parable to None. The consensus on python-list was | -# that None and all types are singletons, so they | -# should be checked using "is", which is also faster, | -# because it only checks for object identity. | -# --------- bga Remove prior comments to reduce the size of the flower | -# box. See revision 1.22 for earlier comments. | -#--(H-)-----------------------------------------------------------------+ -""" - PgSQL - A PyDB-SIG 2.0 compliant module for PostgreSQL. - - Copyright 2000 by Billy G. Allie - See package documentation for further information on copyright. - - Inline documentation is sparse. - See the Python DB-SIG 2.0 specification for usage information. - - basic usage: - - PgSQL.connect(connect_string) -> connection - connect_string = 'host:port:database:user:password:options:tty' - All parts are optional. You may also pass the information in as - keyword arguments with the following keywords: 'host', 'port', - 'database', 'user', 'password', 'options', and 'tty'. The port - may also be passed in as part of the host keyword parameter, - ie. host='localhost:5432'. Other optional parameters are - client_encoding and unicode_results. If unicode_results is true, - all strings from the backend are returned as Unicode strings. - - client_encoding accepts the same parameters as the encode method - of Unicode strings. If you also want to set a policy for encoding - errors, set client_encoding to a tuple, like ("koi8-r", "replace") - - Note that you still must make sure that the PostgreSQL client is - using the same encoding as set with the client_encoding parameter. - This is typically done by issuing a "SET CLIENT_ENCODING TO ..." - SQL statement immediately after creating the connection. - - connection.cursor() -> cursor - Create a new cursor object. A connection can support multiple - cursors at the same time. - - connection.close() - Closes the connection now (instead of when __del__ is called). - The connection will be unusable from this point forward. - NOTE: Any uncommited transactions will be rolled back and any - open cursors for this connection will be closed. - - connection.commit() - Commit any pending transactions for this connection. - - NOTE: This will reset any open cursors for this connection to their - inital state. Any PostgreSQL portals in use by cursors will - be closed and any remaining query results will be discarded. - - connection.rollback() - Rollback any pending transactions for this connection. - - NOTE: This will reset any open cursors for this connection to their - inital state. Any PostgreSQL portals in use by cursors will - be closed and any remaining query results will be discarded. - - connection.binary(string) -> PgLargeObject - Create a new PostgreSQL large object. If string is present, it is - written to the new large object. The returned large object will - not be opened (i.e. it will be closed). - - connection.un_link(OID|PgLargeObject) - Un-links (removes) the PgLargeObject from the database. - - NOTE: This is a PostgreSQL extension to the Connection object. - It is not safe to un-link PgLargeObjects while in a trans- - action (in versions prior to 7.1) since this action can not - be rollbacked completely. Therefore, an attempt to un-link - while in a transaction (in versions prior to 7.1) will raise - an exception. - - connection.version - This instance of the PgVersion class contains information about - the version of the PostgreSQL backend to which the connection - object is connected to. - - NOTE: This is a PgSQL extension to the Connection object. - - cursor.execute(query[, param1[, param2, ..., paramN]) - Execute a query, binding the parameters if they are passed. The - binding syntax is the same as the '%' operator except that only %s - [or %(name)s] should be used and the %s [or %(name)s] should not be - quoted. Any necessary quoting will be performed by the execute - method. - - cursor.execute(query[, sequence]) - Execute a query, binding the contents of the sequence as parameters. - The binding syntax is the same as the '%' operator except that only - %s should be used and the %s should not be quoted. Any necessary - quoting will be performed by the execute method. - - cursor.execute(query[, dictionary]) - Execute a query, binding the contents of the dictionary as para- - meters. The binding syntax is the same as the '%' operator except - that only %s [or %(name)s] should be used and the %s [or %(name)s] - should not be quoted. Any necessary quoting will be performed by - the execute method. - - NOTE: In order to use a PostgreSQL portal (i.e. DECLARE ... CURSOR - FOR ...), the word SELECT must be the first word in the query, - and can only be be proceeded by spaces and tabs. If this is not - the case, a cursor will be simulated by reading the entire result - set into memory and handing out the results as needed. - - NOTE: PostgreSQL cursors are read-only. SELECT ... FOR UPDATE queries - will not use PostgreSQL cursors, but will simulate a cursor by - reading the entire result set into memory and handing out the - results as needed. - - NOTE: Setting the variable, PgSQL.noPostgresCursor, to 1 will cause - PgSQL to NOT use PostgreSQL cursor (DECLARE ... CURSOR FOR ...), - even if all the conditions for doing so are met. PgSQL will - simulate a cursor by reading the entire result set into memory - and handing out the results as needed. - - cursor.executemany(query, sequence_of_params) - Execute a query many times, once for each params in the sequence. - - NOTE: The restriction on the use of PostgreSQL cursors described in - the cursor.execute() note also applies to cursor.executemany(). - The params in the sequence of params can be a list, tuple or - dictionary. - - cursor.fetchone() -> PgResultSet - Fetch the next row of the query result set as a single PgResultSet - containing the column data. Returns None when no more rows are - available. A PgResultSet is a sequence that can be indexed by - a column name in addition to an integer. - - cursor.fetchmany([size]) -> [PgResultSet, ...] - Fetch the next set of rows from the query result, returning a - sequence of PgResultSets. An empty sequence is returned when - no more rows are available. - - The number of rows returned is determined by the size parameter. - If the size parameter is ommited, the value of cursor.arraysize - is used. If size is given, cursor.arraysize is set to that value. - - cursor.fetchall() -> [PgResultSet, ...] - Fetch all (remaining) rows from the query result, returning a - sequence of PgResultSets. An empty sequence is returned when - no more rows are available. - - cursor.description -> [(column info), ... ] - Returns a sequence of 8-item tuples. Each tuple describes one - column of the result: (name, type code, display size, internal - size, precision, scale, null_ok, isArray). - - NOTE: null_ok is not implemented. - isArray is a PostgreSQL specific extension. - - cursor.rowcount - The number of rows the last execute produced (for DQL statements) - or affected (for DML statement). - - cursor.oidValue - The object ID of the inserted record, if the last SQL command - was an INSERT, otherwise it returns 0 (aka. InvalidOid) - - NOTE: oidValue is a PostgreSQL specific extension. - - cursor.close() - Closes the cursor now (instead of when __del__ is called). The - cursor will be unusable from this point forward. - - cursor.rewind() - Moves the cursor back to the beginning of the query result. - This is a PgSQL extension to the PyDB 2.0 API. - - PgResultSet.description() -> [(column info), ... ] - Returns a sequence of 8-item tuples. Each tuple describes one - column of the result: (name, type code, display size, internal - size, precision, scale, null_ok. isArray). - - NOTE: null_ok is not implemented. - isArray is a PostgreSQL specific extension. - - PgResultSet. -> value - Column names are attributes to the PgResultSet. - - Note: Setting the variable, PgSQL.fetchReturnsList = 1 will cause - the fetch*() methods to return a list instead of a PgResultSet. - - PgSQL.version - This string object contains the version number of PgSQL. -""" - -from types import * -from sys import getrefcount, getdefaultencoding -import sys -import copy -import string -import re -import new - -try: - import weakref - noWeakRef = 0 -except: - noWeakRef = 1 - -try: - from mx import DateTime -except ImportError: - raise ImportError, \ - """You need to install mxDateTime - (http://www.egenix.com/files/python/eGenix-mx-Extensions.html)""" -from pyPgSQL.libpq import * - -version = '$Revision: 1.2 $' - -apilevel = '2.0' -threadsafety = 1 -paramstyle = 'pyformat' - -# Setting this variable to 1 will cause the fetch*() methods to return -# a list instead of a PgResultSet - -fetchReturnsList = 0 - -# Setting this variable to 1 will prevent the use of a PostgreSQL Cursor -# (via the "DECLARE ... CURSOR FOR ..." syntax). A cursor will be simulated -# by reading all of the query result into memory and doling out the results -# as needed. - -noPostgresCursor = 0 - -re_DQL = re.compile('^[\s]*SELECT[\s]', re.I) -re_DRT = re.compile('[\s]*DROP[\s]+TABLE[\s]', re.I) -re_DRI = re.compile('[\s]*DROP[\s]+INDEX[\s]', re.I) -re_4UP = re.compile('[\s]FOR[\s]+UPDATE', re.I) - -replace = string.replace - -#-----------------------------------------------------------------------+ -# Make the required Date/Time constructor visable in the PgSQL module. | -#-----------------------------------------------------------------------+ - -Date = DateTime.Date -Time = DateTime.Time -Timestamp = DateTime.Timestamp -DateFromTicks = DateTime.DateFromTicks -TimeFromTicks = DateTime.TimeFromTicks -TimestampFromTicks = DateTime.TimestampFromTicks - -#-----------------------------------------------+ -# The DateTimeDelta type for PgInterval support | -#-----------------------------------------------+ - -DateTimeDelta = DateTime.DateTimeDelta - -#-------------------------------+ -# Also the DateTime types | -#-------------------------------+ - -DateTimeType = DateTime.DateTimeType -DateTimeDeltaType = DateTime.DateTimeDeltaType -DateTimeDelta = DateTime.DateTimeDelta - -#-----------------------------------------------------------------------+ -# Name: DBAPITypeObject | -# | -# Description: The DBAPITypeObject class allows implementing the re- | -# quired DP-API 2.0 type objects even if their are multi- | -# ple database types for the DP-API 2.0 types. | -# | -# Note: This object is taken from the Python DP-API 2.0 imple- | -# mentation hints. | -#-----------------------------------------------------------------------+ - -class DBAPITypeObject: - def __init__(self, name, *values): - self.name = name - self.values = values - - def __repr__(self): - return self.name - - def __cmp__(self, other): - if other in self.values: - return 0 - elif other < self.values: - return 1 - return -1 - -# Define the object types required by the DB-API 2.0 specification. - -BINARY = DBAPITypeObject('BINARY', PG_OID, PG_BLOB, PG_BYTEA) - -DATETIME = DBAPITypeObject('DATETIME', PG_DATE, PG_TIME, PG_TIMETZ, - PG_TIMESTAMP, PG_TIMESTAMPTZ, - PG_ABSTIME, PG_RELTIME, - PG_INTERVAL, PG_TINTERVAL) - -NUMBER = DBAPITypeObject('NUMBER', PG_INT8, PG_INT2, PG_INT4, PG_FLOAT4, - PG_FLOAT8, PG_MONEY, PG_NUMERIC) - -ROWID = DBAPITypeObject('ROWID', PG_OID, PG_ROWID, PG_CID, PG_TID, PG_XID) - -STRING = DBAPITypeObject('STRING', PG_CHAR, PG_BPCHAR, PG_TEXT, PG_VARCHAR, - PG_NAME) - -# BOOLEAN is the PostgreSQL boolean type. - -BOOLEAN = DBAPITypeObject('BOOLEAN', PG_BOOL) - -# OTHER is for PostgreSQL types that don't fit in the standard Objects. - -OTHER = DBAPITypeObject('OTHER', PG_POINT, PG_LSEG, PG_PATH, PG_BOX, - PG_POLYGON, PG_LINE, PG_CIDR, PG_CIRCLE, - PG_INET, PG_MACADDR, PG_ACLITEM, - PG_REFCURSOR) - -#-----------------------------------------------------------------------+ -# Name: PgTypes | -# | -# Description: PgTypes is an object wrapper for the type OID's used by | -# PostgreSQL. It is used to display a meaningful text | -# description of the type while still allowing it to be | -# compared as a numeric value. | -#-----------------------------------------------------------------------+ - -class PgTypes: - def __init__(self, value): - self.value = value - - def __coerce__(self, other): - if type(other) in [IntType, LongType, FloatType]: - return (self.value, int(other)) - return None - - def __cmp__(self, other): - return cmp(self.value, other) - - def __repr__(self): - return repr(self.value) - - def __str__(self): - return PQftypeName(self.value) - - def __int__(self): - return int(self.value) - - def __long__(self): - return long(self.value) - - def __float__(self): - return float(self.value) - - def __complex__(self): - return complex(self.value) - -#-----------------------------------------------------------------------+ -# Name: TypeCache | -# | -# Description: TypeCache is an object that defines methods to: | -# 1. Cast PostgreSQL result strings into the appropiate | -# Python type or object [typecast()]. | -# 2. Retrieve addition information about a type from the | -# PostgreSQL system catalogs [getTypeInfo()]. This | -# type information is maintained in a local cache so | -# that subsequent request for the same information do | -# not require a database query to fulfill it. | -#-----------------------------------------------------------------------+ - -class TypeCache: - """Type cache -- used to cache postgreSQL data type information.""" - - def __init__(self, conn): - if noWeakRef: - self.__conn = conn - else: - self.__conn = weakref.proxy(conn, self.__callback) - self.__type_cache = {} - self.__lo_cache = {} - - def __callback(self, o): - self.__conn = None - - def interval2DateTimeDelta(self, s): - """Parses PostgreSQL INTERVALs. - The expected format is [[[-]YY years] [-]DD days] [-]HH:MM:SS.ss""" - parser = DateTime.Parser.DateTimeDeltaFromString - - ydh = s.split() - ago = 1 - - result = DateTimeDelta(0) - - # Convert any years using 365.2425 days per year, which is PostgreSQL's - # assumption about the number of days in a year. - if len(ydh) > 1: - if ydh[1].lower().startswith('year'): - result += parser('%s days' % ((int(ydh[0]) * 365.2425),)) - ydh = ydh[2:] - - # Converts any days and adds it to the years (as an interval) - if len(ydh) > 1: - if ydh[1].lower().startswith('day'): - result += parser('%s days' % (ydh[0],)) - ydh = ydh[2:] - - # Adds in the hours, minutes, seconds (as an interval) - if len(ydh) > 0: - result += parser(ydh[0]) - - return result - - def parseArray(self, s): - """Parse a PostgreSQL array strings representation. - This parses a PostgreSQL array and return a list of the array - elements as strings. - """ - class LeaveLoopException(Exception): pass - - # Get rid of the escaping in the array string - def convertEscapes(s): - # If we're called with a list in a multi-dimensional - # array, simply return the list. We only convert the - # elements of the multi-dimensional array. - if type(s) is ListType: - return s - - schars = [] - escape = 0 - octdigits = [] - - for char in s: - if char == '\\': - escape += 1 - if escape == 2: - schars.append(char) - escape = 0 - else: - if escape: - if char in string.digits: - octdigits.append(char) - else: - if octdigits != []: - curchar = chr(int(octdigits[0]) * 64) + \ - chr(int(octdigits[1]) * 8) + \ - chr(int(octdigits[2])) - schars.append(curchar) - octdigits = [] - schars.append(char) - else: - schars.append(char) - escape = 0 - return "".join(schars) - - lst = PgArray() - s = s[1:-1] # drop '{' and '}' at start/end - - # If the array is empty, return immediately - if len(s) == 0: - return lst - - pos = 0 - try: - while 1: - if s[pos] == '"': - # A quoted element, find the end-quote, which is the next - # quote char that is not escaped. - end_quote_pos = pos + 1 - escape = 0 - while 1: - if s[end_quote_pos] == '\\': - escape = not escape - elif s[end_quote_pos] == '"': - if not escape: - break - escape = 0 - else: - escape = 0 - end_quote_pos += 1 - lst.append(convertEscapes(s[pos + 1:end_quote_pos])) - - # Skip quote char and next comma - pos = end_quote_pos + 2 - - # If end-of-string. leave loop. - if pos >= len(s): - break - else: - # This array element is not quoted, so it ends either at - # the next comma that isn't escaped, or at the end of the - # string, or, if it contains a subarray, at the position - # of the corresponding curly brace. - if s[pos] != '{': - next_comma_pos = pos + 1 - escape = 0 - while 1: - if next_comma_pos >= len(s): - # This is the last array element. - lst.append(convertEscapes(s[pos:])) - raise LeaveLoopException - - if s[next_comma_pos] == '\\': - escape = not escape - elif s[next_comma_pos] == ',': - if not escape: - break - escape = 0 - else: - escape = 0 - next_comma_pos += 1 - - curelem = s[pos:next_comma_pos] - if curelem.startswith("{"): - lst.append(self.parseArray(curelem[1:-1])) - else: - lst.append(convertEscapes(curelem)) - pos = next_comma_pos + 1 - if s[pos] == ',': - pos += 1 - else: - # The current character is '{', which means we've - # found a sub-array: - # We find the end of the sub-array, then feed this - # string into parseArray again. - escape = 0 - open_braces = 1 - closing_brace_pos = pos + 1 - in_quotes = 0 - while 1: - if s[closing_brace_pos] == '\\': - escape = not escape - elif s[closing_brace_pos] == '{': - if (not escape) and (not in_quotes): - open_braces += 1 - escape = 0 - elif s[closing_brace_pos] == '}': - if (not escape) and (not in_quotes): - open_braces -= 1 - if open_braces == 0: - break - escape = 0 - elif s[closing_brace_pos] == '"': - if not escape: - in_quotes = not in_quotes - escape = 0 - else: - escape = 0 - closing_brace_pos += 1 - - curelem = s[pos:closing_brace_pos + 1] - lst.append(self.parseArray(curelem)) - pos = closing_brace_pos + 1 - if pos >= len(s): - break - if s[pos] == ',': - pos += 1 - - except LeaveLoopException: - pass - - #lst = map(convertEscapes, lst) - return lst - - def typecast(self, colinfo, value): - """ - typecast(rowinfo, value) - Convert certain postgreSQL data types into the appropiate python - object.""" - - if value is None: - return value - - _fn, _ft, _ds, _is, _p, _s, _nu, _ia = colinfo - - _ftv = _ft.value - - if _ia: - # Convert string representation of the array into PgArray object. - _list = self.parseArray(value) - return self.handleArray(colinfo, _list) - - if _ftv == PG_INT2: - if type(value) is PgInt2Type: - return value - else: - return int(value) - elif _ftv == PG_INT4: - if type(value) is IntType: - return value - else: - return int(value) - elif _ftv == PG_INT8 or _ftv == ROWID: - if type(PgInt8) is ClassType: - if isinstance(value, PgInt8): - return value - else: - if type(value) is PgInt8Type: - return value - return long(value) - elif _ftv == PG_NUMERIC: - if isinstance(value, PgNumeric): - return value - else: - try: - return PgNumeric(value, _p, _s) - except OverflowError: - # If we reached this point, then the precision and scale - # of the current field does not match the precision and - # scale of the first record in the result set (there are - # a few reasons why this can happen). Let PgNumeric - # figure out a precision and scale from the value. - return PgNumeric(value) - elif _ftv == PG_MONEY: - if isinstance(value, PgMoney): - return value - else: - return PgMoney(value).value - elif _ftv == DATETIME: - if type(value) in [DateTimeType, DateTimeDeltaType]: - return value - else: - if _ftv == PG_INTERVAL: - return value #self.interval2DateTimeDelta(value) - else: - return value #DateTime.ISO.ParseAny(value) - elif _ftv == BINARY: - if isinstance(value, PgBytea) or type(value) is PgLargeObjectType: - return value - elif type(value) is IntType: - return PgLargeObject(self.conn, value) - else: - return PgBytea(value) - elif _ftv == PG_REFCURSOR: - return self.__conn.cursor(value, isRefCursor=PG_True) - elif _ftv == OTHER: - if isinstance(value, PgOther): - return value - else: - return value - elif self.__conn.unicode_results \ - and _ftv in (PG_CHAR, PG_BPCHAR, PG_TEXT, PG_VARCHAR, PG_NAME): - return unicode(value, *self.__conn.client_encoding) - # Other typecasting is not needed. It will be once support for - # the other built-in types (ie. box, line, inet, cidr, etc) are added. - - return value - - def handleArray(self, colinfo, lst): - # If the list is empty, just return the empty list. - - if len(lst) == 0: - return lst - - _fn, _ft, _ds, _is, _p, _s, _nu, _ia = colinfo - - _ftv = _ft.value - - for _i in range(len(lst)): - if isinstance(lst[_i], PgArray): - lst[_i] = self.handleArray(colinfo, lst[_i]) - elif _ftv == PG_INT4 or _ftv == ROWID: - lst[_i] = int(lst[_i]) - elif _ftv == PG_INT8: - lst[_i] = PgInt8(lst[_i]) - elif _ftv == PG_NUMERIC: - try: - lst[_i] = PgNumeric(lst[_i], _p, _s) - except OverflowError: - # If we reached this point, then the precision and scale - # of the current field does not match the precision and - # scale of the first record in the result set (there are - # a few reasons why this can happen). Let PgNumeric - # figure out a precision and scale from the value. - lst[_i] = PgNumeric(lst[_i]) - elif _ftv == PG_INT2: - lst[_i] = PgInt2(lst[_i]) - elif _ftv == DATETIME: - lst[_i] = DateTime.ISO.ParseAny(lst[_i]) - elif _ftv == PG_MONEY: - if lst[_i][0] == '(': - lst[_i] = PgMoney(-float(replace(lst[_i][2:-1], ',', ''))) - elif lst[_i][0] == '-': - lst[_i] = PgMoney(-float(replace(lst[_i][2:], ',', ''))) - else: - lst[_i] = PgMoney(float(replace(lst[_i][1:], ',', ''))) - elif _ftv == BINARY: - if _ftv == PG_BYTEA: - # There is no need to un-escape lst[_i], it's already been - # done when the PostgreSQL array was converted to a list - # via parseArray(). - lst[_i] = PgBytea(lst[_i]) - else: - lst[_i] = PgLargeObject(self.conn, int(lst[_i])) - - return lst - - def getTypeInfo(self, pgtype): - try: - return self.__type_cache[pgtype.value] - except KeyError: - _nl = len(self.__conn.notices) - _res = self.__conn.conn.query("SELECT typname, -1 , typelem " - "FROM pg_type " - "WHERE oid = %s" % pgtype.value) - - if len(self.__conn.notices) != _nl: - raise Warning, self.__conn.notices.pop() - - _n = _res.getvalue(0, 0) - _p = _res.getvalue(0, 1) - _b = _res.getvalue(0, 2) - if _n[0] == '_': - _n = _n[1:] - _i = 1 - else: - _i = 0 - - self.__type_cache[pgtype.value] = (_n, _p, _i, PgTypes(_b)) - - return self.__type_cache[pgtype.value] - -#-----------------------------------------------------------------------+ -# Name: PgOther | -# | -# Description: A Python wrapper class for the PostgreSQL types that do | -# not (yet) have an implementation in python. The number | -# of types in this category will shrink as more wrappers | -# are implemented. | -# | -# Note: A Python String is used to store the PostgreSQL type in | -# class. | -#-----------------------------------------------------------------------+ - -class PgOther: - def __init__(self, value): - if type(value) is not StringType: - raise TypeError, "argument must be a string." - - self.value = value - - if hasattr(value, '__methods__'): - for i in self.value.__methods__: - exec 'self.%s = self.value.%s' % (i, i) - - # This definition of __coerce__ will cause Python to always call the - # (existing) arithmatic operators for this class. We can the perform the - # appropiate operation on the base type, letting it decide what to do. - def __coerce__(self, other): - return (self, other) - - def __getitem__(self, index): - if type(index) is SliceType: - if index.step is None: - return PgOther(self.value[index.start:index.stop]) - else: - return PgOther(self.value[index.start:index.stop:index.step]) - - return self.value[index]; - - def __setitem__(self, index, item): - raise TypeError, "object doesn't support slice assignment" - - def __delitem__(self, index): - raise TypeError, "object doesn't support slice deletion" - - def __contains__(self, item): - return (item in self.value) - - if sys.version_info < (2, 0): - # They won't be defined if version is at least 2.0 final - def __getslice__(self, i, j): - return PgOther(self.value[max(0, i):max(0, j)]) - - def __setslice__(self, i, j, seq): - raise TypeError, "object doesn't support slice assignment" - - def __delslice__(self, i, j): - raise TypeError, "object doesn't support slice deletion" - - # NOTE: A string is being concatenated to a PgOther, so the result type - # is a PgOther - def __add__(self, other): - return PgOther((self.value + other)) - - # NOTE: A PgOther is being concatenated to a string, so the result type - # is a string. - def __radd__(self, other): - return (other + self.value) - - def __mul__(self, other): - return PgOther((self.value * other)) - - def __rmul__(self, other): - return PgOther((self.value * other)) - - def __repr__(self): - return repr(self.value) - - def __str__(self): - return str(self.value) - - def __hash__(self): - return hash(self.value) - - def __cmp__(self, other): - return cmp(self.value, other) - - def __rcmp__(self, other): - return cmp(other, self.value) - - def __lt__(self, other): - return self.value < other - - def __le__(self, other): - return self.value <= other - - def __eq__(self, other): - return self.value == other - - def __ne__(self, other): - return self.value != other - - def __gt__(self, other): - return self.value > other - - def __ge__(self, other): - return self.value >= other - - # NOTE: A PgOther object will use the PgQuoteString() function in libpq. - def _quote(self, forArray=0): - if self.value: - return PgQuoteString(self.value, forArray) - return 'NULL' - -#-----------------------------------------------------------------------+ -# Name: PgArray | -# | -# Description: A Python wrapper class for PostgreSQL arrays. | -# It is used so that the list type can be used as an arg- | -# ument to Connection.execute() without being treated as | -# a PostgreSQL array. | -#-----------------------------------------------------------------------+ - -class PgArray: - def __init__(self, value=None): - if value is None: - self.value = [] - return - - if type(value) is not ListType and not isinstance(value, PgArray): - raise TypeError, "argument must be a list or a PgArray." - - # We have to insure that nested mutable sequences (list and PgArray) - # get copied. - for i in range(len(value)): - if type(value[i]) is ListType or isinstance(value[i], PgArray): - value[i] = PgArray(value[i][:]) - - self.value = value - - # Define the methods used - def append(self, item): - if type(item) is ListType: - item = PgArray(item) - self.value.append(item) - - def count(self, item): - return self.value.count(item) - - def extend(self, item): - if type(item) is ListType: - item = PgArray(item) - self.value.extend(item) - - def index(self, item): - return self.value.index(item) - - def insert(self, key, item): - if type(item) is ListType: - item = PgArray(item) - self.value.insert(key, item) - - def pop(self, key=-1): - return self.value.pop(key) - - def remove(self, item): - self.value.remove(item) - - def reverse(self): - self.value.reverse() - - def sort(self, compfunc=None): - if compfunc is None: - self.value.sort() - else: - self.value.sort(compfunc) - - def __cmp__(self, other): - if not isinstance(other, PgArray): - return cmp(id(self), id(other)) - - # PgArray objects are considered equal if: - # 1. The lengh of the PgArray objects are equal and - # 2. Each item[k] in the PgArray objects are equal. - - res = cmp(len(self), len(other)) - if res != 0: - return res - - for i in range(len(self.value)): - res = cmp(self.value[i], other.value[i]) - if res != 0: - return res - - return 0 - - def __len__(self): - return len(self.value) - - def __getitem__(self, index): - if type(index) is SliceType: - if index.step is None: - return PgArray(self.value[index.start:index.stop]) - else: - return PgArray(self.value[index.start:index.stop:index.step]) - - return self.value[index]; - - def __setitem__(self, index, item): - if type(item) is ListType: - item = PgArray(item) - - if type(index) is SliceType: - if index.step is None: - self.value[index.start:index.stop] = item - else: - self.value[index.start:index.stop:index.step] = item - else: - self.value[index] = item - - def __delitem__(self, index): - if type(index) is SliceType: - if index.step is None: - del self.value[index.start:index.stop] - else: - del self.value[index.start:index.stop:index.step] - else: - del self.value[index]; - - def __contains__(self, item): - return (item in self.value) - - if sys.version_info < (2, 0): - # They won't be defined if version is at least 2.0 final - def __getslice__(self, i, j): - return PgArray(self.value[max(0, i):max(0, j)]) - - def __setslice__(self, i, j, seq): - if type(seq) is ListType: - seq = PgArray(seq) - self.value[max(0, i):max(0, j)] = seq.value - - def __delslice__(self, i, j): - del self.value[max(0, i):max(0, j)] - - def __add__(self, other): - return PgArray((self.value + other)) - - def __radd__(self, other): - return PgArray(other + self.value) - - def __iadd__(self, other): - value = value + other - return self - - def __mul__(self, other): - return PgArray((self.value * other)) - - def __rmul__(self, other): - return PgArray((self.value * other)) - - def __imul__(self, other): - value = value * other - return self - - def __repr__(self): - return repr(self.value) - - def __str__(self): - return str(self.value) - - # NOTE: A PgArray object will use the _handleArray() function to quote - # itself. - def _quote(self, forArray=0): - if self.value: - return _handleArray(self.value) - return 'NULL' - -#-----------------------------------------------------------------------+ -# Name: PgBytea | -# | -# Description: A Python wrapper class for the PostgreSQL BYTEA type. | -# | -# Note: A Python String is used to store the PostgreSQL type in | -# class. | -#-----------------------------------------------------------------------+ - -class PgBytea: - def __init__(self, value): - if type(value) is not StringType: - raise TypeError, "argument must be a string." - - self.value = value - - if hasattr(value, '__methods__'): - for i in self.value.__methods__: - exec 'self.%s = self.value.%s' % (i, i) - - # This definition of __coerce__ will cause Python to always call the - # (existing) arithmatic operators for this class. We can the perform the - # appropiate operation on the base type, letting it decide what to do. - def __coerce__(self, other): - return (self, other) - - def __getitem__(self, index): - if type(index) is SliceType: - if index.step is None: - return PgBytea(self.value[index.start:index.stop]) - else: - return PgBytea(self.value[index.start:index.stop:index.step]) - - return self.value[index]; - - def __setitem__(self, index, item): - raise TypeError, "object doesn't support slice assignment" - - def __delitem__(self, index): - raise TypeError, "object doesn't support slice deletion" - - def __contains__(self, item): - return (item in self.value) - - if sys.version_info < (2, 0): - # They won't be defined if version is at least 2.0 final - def __getslice__(self, i, j): - return PgBytea(self.value[max(0, i):max(0, j)]) - - def __setslice__(self, i, j, seq): - raise TypeError, "object doesn't support slice assignment" - - def __delslice__(self, i, j): - raise TypeError, "object doesn't support slice deletion" - - def __add__(self, other): - return PgBytea((self.value + other)) - - def __radd__(self, other): - return PgBytea(other + self.value) - - def __mul__(self, other): - return PgBytea((self.value * other)) - - def __rmul__(self, other): - return PgBytea((self.value * other)) - - def __repr__(self): - return repr(self.value) - - def __str__(self): - return str(self.value) - - def __hash__(self): - return hash(self.value) - - def __cmp__(self, other): - return cmp(self.value, other) - - def __rcmp__(self, other): - return cmp(other, self.value) - - def __lt__(self, other): - return self.value < other - - def __le__(self, other): - return self.value <= other - - def __eq__(self, other): - return self.value == other - - def __ne__(self, other): - return self.value != other - - def __gt__(self, other): - return self.value > other - - def __ge__(self, other): - return self.value >= other - - # NOTE: A PgBytea object will use the PgQuoteBytea() function in libpq - def _quote(self, forArray=0): - if self.value: - return PgQuoteBytea(self.value, forArray) - return 'NULL' - -#-----------------------------------------------------------------------+ -# Name: PgNumeric | -# | -# Description: A Python wrapper class for the PostgreSQL numeric type. | -# It implements addition, subtraction, mulitplcation, and | -# division of scaled, fixed precision numbers. | -# | -# Note: The PgNumeric class uses a Python Long type to store | -# the PostgreSQL numeric type. | -#-----------------------------------------------------------------------+ - -class PgNumeric: - def __init__(self, value, prec=None, scale=None): - if type(value) in [IntType, LongType] or value is None: - if prec is None or scale is None: - raise TypeError, \ - "you must supply precision and scale when value is a " \ - "integer, long, or None" - if value is None: - self.__v = value - else: - self.__v = long(value) - # Check to see if the value is too large for the given - # precision/scale - _v = str(abs(value)) - if _v[-1:] == 'L': - _v = _v[:-1] - if len(_v) > prec: - raise OverflowError, "value too large for PgNumeric" - - self.__p = prec - self.__s = scale - elif type(value) in (FloatType, StringType): - # Get the value to convert as a string. - # The expected input is in the form of [+|-][d]*[.[d]*][e[d]+] - - # First get the value as a (trimmed) string - if type(value) is FloatType: - _v = str(value) - else: - _v = value.split() - if len(_v) == 0 or len(_v) > 1: - raise ValueError, \ - "invalid literal for PgNumeric: %s" % value - _v = _v[0] - - # Save the sign character (if any) and remove from the string - _sign = '+' - if _v[0] in ('-', '+'): - _sign = _v[0] - _v = _v[1:] - - # Split the remaining string into int part, frac part and exponet - _d = _v.rfind('.') - _e = _v.rfind('e') - - # Ensure that _e and _v contains a sane value - if _e < 0: - _e = _v.rfind('E') - if _e < 0: - _e = len(_v) - - if _d < 0: - _d = _e - - _ip = _v[:_d] - _fp = _v[_d+1:_e] - _xp = _v[_e+1:] - - # Check the validity of the input - if len(_ip) == 0 and len(_fp) == 0: - raise ValueError, \ - "invalid literal for PgNumeric: %s" % value - - if len(_xp) > 0: - try: - _exp = int(_xp) - except: - raise ValueError, \ - "invalid literal for PgNumeric: %s" % value - else: - _exp = 0 - - if _exp > 999: - raise OverflowError, "value too large for PgNumeric" - - if _exp < -999: - raise OverflowError, "value too small for PgNumeric" - - # Create the string that will become the base (long) object - _v = _ip + _fp - - _sc = len(_fp) - if _exp > 0: - if _exp > _sc: - _v = _v + ("0" * (_exp - _sc)) - _sc = 0 - else: - _sc = _sc - _exp - else: - _sc = _sc - _exp - - try: - self.__v = long(_sign + _v) - except: - raise ValueError, \ - "invalid literal for PgNumeric: %s" % value - - self.__p = len(_v) - if self.__p < _sc: - self.__p = _sc - self.__s = _sc - - # Now adjust for the inputted scale (if any) - if scale is None: - pass - else: - _adj = scale - self.__s - if _adj > 0: - self.__v = self.__v * (10L ** (scale - self.__s)) - elif _adj < 0: - self.__v = self._round(self.__v, -_adj) - - self.__p = self.__p + _adj - self.__s = scale - - # Apply the inputted precision (if any) - if prec is None: - pass - else: - if prec > 1000: - raise ValueError, "precision too large for PgNumeric" - elif self.__p > prec: - raise OverflowError, "value too large for PgNumeric" - else: - self.__p = prec - elif isinstance(value, PgNumeric): - # This is used to "cast" a PgNumeric to the specified precision - # and scale. It can also make a copy of a PgNumeric. - self.__v = value.__v - if scale: - self.__s = scale - _ds = scale - value.__s - else: - self.__s = value.__s - _ds = 0 - if prec: - self.__p = prec - else: - self.__p = value.__p - # Now we adjust the value to reflect the new scaling factor. - if _ds > 0: - if _ds == 1: - self.__v = self.__v * 10 - else: - self.__v = self.__v * (10L ** _ds) - elif _ds < 0: - self.__v = self._round(self.__v, -_ds) - if self.__v > (10L ** self.__p): - raise OverflowError, "result exceeds precision of %d" % self.__p - else: - raise TypeError, "value can not be converted to a PgNumeric." - - if self.__s > self.__p: - raise ValueError, \ - "scale of %d exceeds precision of %d" % (self.__s, self.__p) - - # The value (10L ** self.__s) is used a lot. Save it as a constant - # to save a (small) bit of time. - - self.__sf = 10L ** self.__s - - def __fmtNumeric(self, value=None): - if value is None: - _v = self.__v - else: - _v = value - - # Check for a negative value and adjust if necessary - if _v < 0: - _sign = '-' - _v = -_v - else: - _sign = '' - _v = str(_v) - - # Check to see if the string representation of the python long has - # a trailing 'L', if so, remove it. Python 1.5 has the trailing 'L', - # Python 1.6 does not. - if _v[-1:] == 'L': - _v = _v[:-1] - - # Check to see if the numeric is less than one and fix string if so. - if len(_v) <= self.__s: - _v = ("0" * (self.__s - len(_v) + 1)) + _v - - if self.__s: - _s = "%s%s.%s" % (_sign, _v[:-(self.__s)], _v[-(self.__s):]) - else: - _s = "%s%s" % (_sign, _v) - return _s - - def __repr__(self): - return "" % \ - (self.__p, self.__s, self.__fmtNumeric()) - - def __str__(self): - return self.__fmtNumeric() - - def getScale(self): - return self.__s - - def getPrecision(self): - return self.__p - - def __coerce__(self, other): - if isinstance(other, PgNumeric): - return self, other - elif type(other) in [IntType, LongType]: - _s = str(other) - if _s[-1:] == 'L': - _s = _s[:-1] # Work around v1.5/1.6 differences - return (self, PgNumeric(_s)) - elif type(other) == FloatType: - return (self, PgNumeric(other)) - return None - - def _round(self, value, drop): - if drop == 1: - return ((value + 5L) / 10L) - elif drop > 1: - return (((value / (10L ** (drop - 1))) + 5L) / 10L) - - return value - - def __add__(self, other): - _c = self.__coerce__(other) - if _c is None: - return None - self, other = _c - if self.__s < other.__s: - _s = self.__v * (other.__sf / self.__sf) - _o = other.__v - elif self.__s > other.__s: - _s = self.__v - _o = other.__v * (self.__sf / other.__sf) - else: - _s = self.__v - _o = other.__v - - mp = max(self.__p - self.__s, other.__p - other.__s) - ms = max(self.__s, other.__s) - v = _s + _o - # Check to see if the addition caused an increase in the precision - # due to a carry. If so, compensate for it. - if (v / (10L ** (mp + ms))) > 0: - mp = mp + 1 - - return PgNumeric((_s + _o), (mp + ms), ms) - - def __radd__(self, other): - return self.__add__(other) - - def __iadd__(self, other): - _r = self.__add__(other) - if _r is None: - return None - self.__v = _r.__v - self.__p = _r.__p - self.__s = _r.__s - self.__sf = _r.__sf - return self - - def __sub__(self, other): - _c = self.__coerce__(other) - if _c is None: - return None - self, other = _c - if self.__s < other.__s: - _s = self.__v * (other.__sf / self.__sf) - _o = other.__v - elif self.__s > other.__s: - _s = self.__v - _o = other.__v * (self.__sf / other.__sf) - else: - _s = self.__v - _o = other.__v - - mp = max(self.__p - self.__s, other.__p - other.__s) - ms = max(self.__s, other.__s) - return PgNumeric((_s - _o), (mp + ms), ms) - - def __rsub__(self, other): - return other.__sub__(self) - - def __isub__(self, other): - _r = self.__sub__(other) - if _r is None: - return None - self.__v = _r.__v - self.__p = _r.__p - self.__s = _r.__s - self.__sf = _r.__sf - return self - - def __mul__(self, other): - _c = self.__coerce__(other) - if _c is None: - return None - self, other = _c - _p = self.__v * other.__v - return PgNumeric(_p, self.__p + other.__p, self.__s + other.__s) - - def __rmul__(self, other): - return self.__mul__(self, other) - - def __imul__(self, other): - _r = self.__mul__(other) - if _r is None: - return None - self.__v = _r.__v - self.__p = _r.__p - self.__s = _r.__s - self.__sf = _r.__sf - return self - - def __div__(self, other): - _c = self.__coerce__(other) - if _c is None: - return None - self, other = _c - _n = self.__v * other.__sf * self.__sf - _d = other.__v - _q = self._round((_n / _d), self.__s) - return PgNumeric(_q, self.__p, self.__s) - - def __rdiv__(self, other): - return other.__div__(self) - - def __idiv__(self, other): - _r = self.__div__(other) - if _r is None: - return None - self.__v = _r.__v - self.__p = _r.__p - self.__s = _r.__s - self.__sf = _r.__sf - return self - - def __cmp__(self, other): - if other is None: - return 1 - _c = self.__coerce__(other) - if _c is None: - return None - self, other = _c - if self.__s < other.__s: - _s = self.__v * (other.__sf / self.__sf) - _o = other.__v - elif self.__s > other.__s: - _s = self.__v - _o = other.__v * (self.__sf / other.__sf) - else: - _s = self.__v - _o = other.__v - return cmp(_s, _o) - - def __neg__(self): - return PgNumeric(-self.__v, self.__p, self.__s) - - def __nonzero__(self): - return self.__v not in (None, 0) - - def __pos__(self): - return PgNumeric(self.__v, self.__p, self.__s) - - def __abs__(self): - if self.__v >= 0: - return PgNumeric(self.__v, self.__p, self.__s) - else: - return PgNumeric(-self.__v, self.__p, self.__s) - - def _quote(self, forArray=0): - if self.__v: - if forArray: - return '"%s"' % self.__fmtNumeric() - else: - return "'%s'" % self.__fmtNumeric() - return 'NULL' - - def __int__(self): - return int(self.__v / self.__sf) - - def __long__(self): - return self.__v / self.__sf - - def __float__(self): - v = self.__v - s = self.__sf - return (float(v / s) + (float(v % s) / float(s))) - - def __complex__(self): - return complex(self.__float__()) - - def __hash__(self): - if self.__s == 0: - return hash(self.__v) - v = self.__v / self.__sf - if (v * self.__sf) == self.__v: - return hash(v) - return hash(float(self)) - -#-----------------------------------------------------------------------+ -# Name: PgMoney | -# | -# Description: A Python wrapper class for the PostgreSQL Money type. | -# It's primary purpose it to check for overflow during | -# calulations and to provide formatted output. | -# | -# Note: The PgMoney class uses a Python Floating point number | -# represent a PostgreSQL money type. | -#-----------------------------------------------------------------------+ - -class PgMoney: - def __init__(self, value): - if value is None: - self.value = value - return - - if type(value) is StringType: - if value[0] == '(': - self.value = PgMoney(-float(replace(value[2:-1], ',', ''))) - elif value[0] == '-': - self.value = PgMoney(-float(replace(value[2:], ',', ''))) - else: - self.value = PgMoney(float(replace(value[1:], ',', ''))) - else: - self.value = float(value) - - if self.value < -21474836.48 or self.value > 21474836.47: - raise OverflowError, 'money initialization' - - - def __checkresult(self, value, op): - if value < -21474836.48 or value > 21474836.47: - raise OverflowError, 'money %s' % op - return PgMoney(value) - - def __coerce__(self, other): - if other is None: - return None - res = coerce(self.value, other) - if res is None: - return None - _s, _o = res - return (self, _o) - - def __hash__(self): - return hash(self.value) - - def __cmp__(self, other): - return cmp(self.value, other) - - def __add__(self, other): - return self.__checkresult(self.value + other, "addition") - - def __sub__(self, other): - return self.__checkresult(self.value - other, "subtraction") - - def __mul__(self, other): - return self.__checkresult(self.value * other, "mulitplication") - - def __div__(self, other): - return self.__checkresult(self.value / other, "division") - - def __divmod__(self, other): - _a, _b = divmod(self.value, other) - return (self.__checkresult(_a, "divmod"), _b) - - def __pow__(self, other, modulus=None): - return self.__checkresult(pow(self.value, other, modulus), "pow") - - def __radd__(self, other): - return self.__checkresult(other + self.value, "addition") - - def __rsub__(self, other): - return self.__checkresult(other - self.value, "subtraction") - - def __rmul__(self, other): - return self.__checkresult(other * self.value, "multiplication") - - def __rdiv__(self, other): - return self.__checkresult(other / self.value, "division") - - def __rdivmod__(self, other): - _a, _b = divmod(other, self.value) - return (self.__checkresult(_a, "divmod"), _b) - - def __rpow__(self, other, modulus=None): - return self.__checkresult(pow(other, self.value, modulus), "pow") - - def __neg__(self): - return self.__checkresult(self.value * -1, "negation") - - def __pos__(self): - return self.value - - def __abs__(self): - return self.__checkresult(abs(self.value), "abs") - - def __complex__(self): - return complex(self.value) - - def __int__(self): - return int(self.value) - - def __long__(self): - return long(self.value) - - def __float__(self): - return self.value # PgMoney is already a float :-) - - def __repr__(self): - return '%.2f' % self.value - - def __str__(self): - _s = '%.2f' % abs(self.value) - _i = string.rfind(_s, '.') - _c = (_i - 1) / 3 - for _j in range(_c): - _i = _i - 3 - _s = '%s,%s' % (_s[:_i], _s[_i:]) - if self.value < 0.0: - return '($%s)' % _s - else: - return '$%s' % _s - - def _quote(self, forArray=0): - if self.value: - if forArray: - return '"%s"' % str(self.value) - else: - return "'%s'" % str(self.value) - return 'NULL' - -#-----------------------------------------------------------------------+ -# Name: PgInt8 | -# | -# Description: A Python wrapper class for the PostgreSQL int8 type. | -# It's primary purpose it to check for overflow during | -# calulations. | -# | -# Note: The PgInt8 class uses a Python Long Integer to hold | -# the PostgreSQL int8 type. | -# | -# Note: This class will only be defined if the C implementation | -# of the PgInt8 object was not imported with/from libpq. | -#-----------------------------------------------------------------------+ - -if dir().count('PgInt8') == 0: # Only define this class is PgInt8 wasn't - # brought in via libpq. - class PgInt8: - def __init__(self, value): - if value is None: - self.value = value - return - - self.value = long(value) - if self.value < -9223372036854775808L or \ - self.value > 9223372936854775807L: - raise OverflowError, 'int8 initialization' - - def __checkresult(self, value, op): - if value < -9223372036854775808L or value > 9223372936854775807L: - raise OverflowError, 'int8 %s' % op - return PgInt8(value) - - def __coerce__(self, other): - if other is None: - return None - res = coerce(self.value, other) - if res is None: - return None - _s, _o = res - return (self, _o) - - def __hash__(self): - return hash(self.value) - - def __cmp__(self, other): - return cmp(self.value, other) - - def __nonzero__(self): - return self.value != 0 - - def __add__(self, other): - return self.__checkresult(self.value + other, "addition") - - def __sub__(self, other): - return self.__checkresult(self.value - other, "subtraction") - - def __mul__(self, other): - return self.__checkresult(self.value * other, "mulitplication") - - def __div__(self, other): - return self.__checkresult(self.value / other, "division") - - def __divmod__(self, other): - _a, _b = divmod(self.value, other) - return (self.__checkresult(_a, "divmod"), _b) - - def __pow__(self, other, modulus=None): - return self.__checkresult(pow(self.value, other, modulus), "pow") - - def __lshift__(self, other): - return self.__checkresult(self.value << other, 'lshift') - - def __rshift__(self, other): - return self.__checkresult(self.value >> other, 'rshift') - - def __and__(self, other): - return self.__checkresult(self.value & other, 'and') - - def __xor__(self, other): - return self.__checkresult(self.value ^ other, 'xor') - - def __or__(self, other): - return self.__checkresult(self.value | other, 'or') - - def __radd__(self, other): - return self.__checkresult(other + self.value, "addition") - - def __rsub__(self, other): - return self.__checkresult(other - self.value, "subtraction") - - def __rmul__(self, other): - return self.__checkresult(other * self.value, "mulitplication") - - def __rdiv__(self, other): - return self.__checkresult(other / self.value, "division") - - def __rdivmod__(self, other): - _a, _b = divmod(other, self.value) - return (self.__checkresult(_a, "divmod"), - self.__checkresult(_b, "divmod")) - - def __rpow__(self, other, modulus=None): - return self.__checkresult(pow(other, self.value, modulus), "pow") - - def __rlshift__(self, other): - return self.__checkresult(other << self.value, 'lshift') - - def __rrshift__(self, other): - return self.__checkresult(other >> self.value, 'rshift') - - def __rand__(self, other): - return self.__checkresult(other & self.value, 'and') - - def __rxor__(self, other): - return self.__checkresult(other ^ self.value, 'xor') - - def __ror__(self, other): - return self.__checkresult(other | self.value, 'or') - - def __neg__(self): - return self.__checkresult(neg(self.value), 'neg') - - def __pos__(self): - return self.__checkresult(pos(self.value), 'pos') - - def __abs__(self): - return self.__checkresult(abs(self.value), 'abs') - - def __complex__(self): - return complex(self) - - def __int__(self): - return int(self.value) - - def __long__(self): - return self.value # PgInt8 is already a Long. - - def __float__(self): - return float(self.value) - - def __complex__(self): - return complex(self.value) - - def __hex__(self): - return hex(self.value) - - def __oct__(self): - return oct(self.value) - - def __repr__(self): - return repr(self.value) - - def __str__(self): - return str(self.value) - - def _quote(self, forArray=0): - if self.value is not None: - s = str(self.value) - if s[-1:] == "L": - s = s[:-1] - return "%s" % s - return 'NULL' - - PgInt8Type = PgInt8 - - -#-----------------------------------------------------------------------+ -# Name: PgResultSet | -# | -# Description: This class defines the DB-API query result set for a | -# single row. It emulates a sequence with the added | -# feature of being able to reference an attribute by | -# column name in addition to a zero-based numeric index. | -# | -# This class isn't used directly, instead it's used as a | -# base class for the actual result set class created with | -# make_PgResultSetClass. | -# | -#-----------------------------------------------------------------------+ - -class PgResultSet: - - # It may not be obvious what self.__class__ does: - # Apart from the __init__ method, all methods are called on instances of a - # class dynamically created make_PgResultSetClass, which means that when - # you call a method, self.__class__ is *not* PgResultSet, but a subclass of - # it created with make_PgResultSetClass (using the new module). The - # subclass will have a class attribute called _xlatkey, which is a mapping - # of column names to column positions. - - def __init__(self, value): - self.__dict__['baseObj'] = value - - def __getattr__(self, key): - # When retrieving column data by name as an attribute, we must be - # aware that a column name can be defiend with mixed-case within the - # database. Because of this we must first check for an exact match - # with the given key. If that fails, then we match with the key that - # has been changed to lower case. Note: we are relying on the fact - # that PostgreSQL sends column names that are not defined with mixed- - # case to the client as lower-case names. - keyl = key.lower() - if self._xlatkey.has_key(key): - return self.baseObj[self._xlatkey[key]] - if self._xlatkey.has_key(keyl): - return self.baseObj[self._xlatkey[keyl]] - raise AttributeError, key - - # We define a __setattr__ routine that will only allow the attributes that - # are the column names to be updated. All other attributes are read-only. - def __setattr__(self, key, value): - if key in ('baseObj', '_xlatkey', '_desc_'): - raise AttributeError, "%s is read-only." % key - - # Try an exact match first, then the case-insensitive match. - # See comment in __getattr__ for details. - keyl = key.lower() - if self._xlatkey.has_key(key): - self.__dict__['baseObj'][self._xlatkey[key]] = value - elif self._xlatkey.has_key(keyl): - self.__dict__['baseObj'][self._xlatkey[keyl]] = value - else: - raise AttributeError, key - - def __len__(self): - return len(self.baseObj) - - def __getitem__(self, key): - if isinstance(key, StringType): - # Try an exact match first, then the case-insensitive match. - # See comment in __getattr__ for details. - try: - key = self._xlatkey[key] - except: - key = self._xlatkey[key.lower()] - return self.baseObj[key] - - def __setitem__(self, key, value): - if isinstance(key, StringType): - # Try an exact match first, then the case-insensitive match. - # See comment in __getattr__ for details. - try: - key = self._xlatkey[key] - except: - key = self._xlatkey[key.lower()] - self.baseObj[key] = value - - def __contains__(self, key): - return self.has_key(key) - - def __getslice__(self, i, j): - klass = make_PgResultSetClass(self._desc_[i:j]) - obj = klass(self.baseObj[i:j]) - return obj - - def __repr__(self): - return repr(self.baseObj) - - def __str__(self): - return str(self.baseObj) - - def __cmp__(self, other): - return cmp(self.baseObj, other) - - def description(self): - return self._desc_ - - def keys(self): - _k = [] - for _i in self._desc_: - _k.append(_i[0]) - return _k - - def values(self): - return self.baseObj[:] - - def items(self): - _items = [] - for i in range(len(self.baseObj)): - _items.append((self._desc_[i][0], self.baseObj[i])) - return _items - - def has_key(self, key): - # Try an exact match first, then the case-insensitive match. - # See comment in __getattr__ for details. - if not self._xlatkey.has_key(key): - key = key.lower() - return self._xlatkey.has_key(key) - - def get(self, key, defaultval=None): - try: - if isinstance(key, StringType): - # Try an exact match first, then the case-insensitive match. - # See comment in __getattr__ for details. - try: - key = self._xlatkey[key] - except: - key = self._xlatkey[key.lower()] - return self[key] - except: - return defaultval - -def make_PgResultSetClass(description, mapname=None): - """Dynamically create a new subclass of PgResultSet.""" - klass = new.classobj("PgResultSetConcreteClass", (PgResultSet,), {}) - klass.__dict__['_desc_'] = description - - klass.__dict__['_xlatkey'] = {} - if mapname is None: - for _i in range(len(description)): - klass.__dict__['_xlatkey'][description[_i][0]] = _i - else: - for k, v in mapname.items(): - klass.__dict__['_xlatkey'][k] = v - return klass - - -#-----------------------------------------------------------------------+ -# Define the PgSQL function calls: | -# | -# connect() -- connect to a PostgreSQL database. | -# _handleArray() -- Transform a PgArray class into a string rep- | -# resenting a PostgreSQL array. | -# _quote() -- Transform a Python object representing a | -# PostgreSQL type into a appropiately quoted | -# string that can be sent to the database in a | -# UPDATE/INSERT statement. _quote() calls the | -# _handleArray() function to quote arrays. | -# _quoteall() -- transforms all elements of a list or diction- | -# ary using _quote. | -# dateTimeDelta2Interval() -- converts a DateTimeDelta type into | -# a string PostgreSQL accepts as a interval. | -#-----------------------------------------------------------------------+ - -def connect(dsn=None, user=None, password=None, host=None, database=None, - port=None, options=None, tty=None, client_encoding=None, - unicode_results=None): - """ -connection = PgSQL.connect(dsn[, user, password, host, database, port, - options, tty] [, client_encoding] - [, unicode_results]) - Opens a connection to a PostgreSQL database.""" - - _d = {} - - # Try getting values from the DSN first. - if dsn is not None: - try: - params = string.split(dsn, ":") - if params[0] != '': _d["host"] = params[0] - if params[1] != '': _d["port"] = params[1] - if params[2] != '': _d["dbname"] = params[2] - if params[3] != '': _d["user"] = params[3] - if params[4] != '': _d["password"] = params[4] - if params[5] != '': _d["options"] = params[5] - if params[6] != '': _d["tty"] = params[6] - except: - pass - - # Override from the keyword arguments, if needed. - if (user is not None): _d["user"] = user - if (password is not None): _d["password"] = password - if (host is not None): - _d["host"] = host - try: - params = string.split(host, ":") - _d["host"] = params[0] - _d["port"] = params[1] - except: - pass - if (database is not None): _d["dbname"] = database - if (port is not None): _d["port"] = port - if (options is not None): _d["options"] = options - if (tty is not None): _d["tty"] = tty - - # Build up the connection info string passed to PQconnectdb - # via the constructor to Connection. - - connInfo = "" - for i in _d.keys(): - connInfo = "%s%s=%s " % (connInfo, i, _d[i]) - - return Connection(connInfo, client_encoding, unicode_results) - -def _handleArray(value): - """ -_handleArray(list) -> string - This function handle the transformation of a Python list into a string that - can be used to update a PostgreSQL array attribute.""" - - #Check for, and handle an empty list. - if len(value) == 0: - return '{}' - - _j = "'{" - for _i in value: - if _i is None: - _j += "," - elif isinstance(_i, PgArray): - _j = _j + _handleArray(_i)[1:-1] + ',' - elif hasattr(_i, '_quote'): - _j = '%s%s,' % (_j, _i._quote(1)) - elif type(_i) is DateTimeType: - _j = '%s"%s",' % (_j, _i) - elif type(_i) is DateTime.DateTimeDeltaType: - _j = '%s"%s",' % (_j, dateTimeDelta2Interval(_i)) - elif type(_i) is PgInt2Type or isinstance(_i, PgInt8Type): - _j = '%s%s,' % (_j, str(_i)) - else: - _j = '%s%s,' % (_j, PgQuoteString(str(_i), 1)) - - return _j[:-1] + "}'" - -def _quote(value): - """ -_quote(value) -> string - This function transforms the Python value into a string suitable to send - to the PostgreSQL database in a insert or update statement. This function - is automatically applied to all parameter sent vis an execute() call. - Because of this an update/insert statement string in an execute() call - should only use '%s' [or '%(name)s'] for variable subsitution without any - quoting.""" - - if value is None: - return 'NULL' - elif hasattr(value, '_quote'): - return value._quote() - elif type(value) is DateTimeType: - return "'%s'" % value - elif type(value) is DateTimeDeltaType: - return "'%s'" % dateTimeDelta2Interval(value) - elif isinstance(value, StringType): - return PgQuoteString(value) - elif isinstance(value, LongType): - return str(value) - else: - return repr(value) - -def _quoteall(vdict): - """ -_quoteall(vdict)->dict - Quotes all elements in a list or dictionary to make them suitable for - insertion.""" - - if type(vdict) is DictType or isinstance(vdict, PgResultSet): - t = {} - for k, v in vdict.items(): - t[k]=_quote(v) - elif type(vdict) in (StringType, UnicodeType): - # Note: a string is a SequenceType, but is treated as a single - # entity, not a sequence of characters. - t = (_quote(vdict), ) - elif type(vdict) in [ListType, TupleType]: - t = tuple(map(_quote, vdict)) - else: - raise TypeError, \ - "argument to _quoteall must be a sequence or dictionary!" - - return t - -def dateTimeDelta2Interval(interval): - """ -DateTimeDelta2Interval - Converts a DateTimeDelta to an interval string\n - The input format is [+-]DD:HH:MM:SS.ss\n - The output format is DD days HH:MM:SS.ss [ago]\n - """ - - if type(interval) is DateTimeDeltaType: - s = str(interval) - ago = '' - if s[0] == '-': - ago = ' ago' - s = s[1:] - else: - ago = '' - s = s.split(':') - if len(s) < 4: - return '%s:%s:%s %s' % (s[0], s[1], s[2], ago) - - return '%s days %s:%s:%s %s' % (s[0], s[1], s[2], s[3], ago) - else: - raise TypeException, "DateTimeDelta2Interval requires a DataTimeDelta." - -#-----------------------------------------------------------------------+ -# Name: Connection | -# | -# Description: Connection defines the Python DB-API 2.0 connection | -# object. See the DB-API 2.0 specifiaction for details. | -#-----------------------------------------------------------------------+ - -class Connection: - """Python DB-API 2.0 Connection Object.""" - - def __init__(self, connInfo, client_encoding=None, unicode_results=None): - try: - self.__dict__["conn"] = PQconnectdb(connInfo) - except Exception, m: - # The connection to the datadata failed. - # Clean up the Connection object that was created. - # Note: _isOpen must be defined for __del__ to work. - self.__dict__["_isOpen"] = None - del(self) - raise DatabaseError, m - - self.__dict__["autocommit"] = 0 - self.__dict__["TransactionLevel"] = "" - self.__dict__["notices"] = self.conn.notices - self.__dict__["inTransaction"] = 0 - self.__dict__["version"] = self.conn.version - self.__dict__["_isOpen"] = 1 - self.__dict__["_cache"] = TypeCache(self) - if noWeakRef: - self.__dict__["cursors"] = [] - else: - self.__dict__["cursors"] = weakref.WeakValueDictionary() - - self.unicode_results = unicode_results - if type(client_encoding) in (TupleType, ListType): - self.client_encoding = client_encoding - else: - self.client_encoding = (client_encoding or getdefaultencoding(),) - - def __del__(self): - if self._isOpen: - self.close() # Ensure that the connection is closed. - - def __setattr__(self, name, value): - if name == "autocommit": - if value is None: - raise InterfaceError, \ - "Can't delete the autocommit attribute." - # Don't allow autocommit to change if there are any opened cursor - # associated with this connection. - if self.__anyLeft(): - if noWeakRef: - # If the are cursors left, but weak references are not - # available, garbage collect any cursors that are only - # referenced in self.cursors. - - self.__gcCursors() - - if len(self.cursors) > 0: - raise AttributeError, \ - "Can't change autocommit when a cursor is active." - else: - raise AttributeError, \ - "Can't change autocommit when a cursor is active." - - # It's possible that the connection can still have an open - # transaction, even though there are no active cursors. - - if self.inTransaction: - self.rollback() - - if value: - self.__dict__[name] = 1 - else: - self.__dict__[name] = 0 - elif name == "TransactionLevel": - if value is None: - raise InterfaceError, \ - "Can't delete the TransactinLevel attribute." - # Don't allow TransactionLevel to change if there are any opened - # cursors associated with this connection. - if self.__anyLeft(): - if noWeakRef: - # If the are cursors left, but weak references are not - # available, garbage collect any cursors that are only - # referenced in self.cursors. - - self.__gcCursors() - - if len(self.cursors) > 0: - raise AttributeError, \ - "Can't change TransactionLevel when a cursor is active." - else: - raise AttributeError, \ - "Can't change TransactionLevel when a cursor is active." - - # It's possible that the connection can still have an open - # transaction, even though there are no active cursors. - - if self.inTransaction: - self.rollback() - - if type(value) is not StringType: - raise ValueError, "TransactionLevel must be a string." - - if value.upper() in [ "", "READ COMMITTED", "SERIALIZABLE" ]: - self.__dict__[name] = value.upper() - else: - raise ValueError, \ - 'TransactionLevel must be: "", "READ COMMITTED", or "SERIALIZABLE"' - elif name in ('unicode_results', 'client_encoding'): - self.__dict__[name] = value - elif self.__dict__.has_key(name): - raise AttributeError, "%s is read-only." % name - else: - raise AttributeError, name - - def __closeCursors(self, flag=0): - """ - __closeCursors() - closes all cursors associated with this connection""" - if self.__anyLeft(): - if noWeakRef: - curs = self.cursors[:] - else: - curs = map(lambda x: x(), self.cursors.data.values()) - - for i in curs: - if flag: - i.close() - else: - i._Cursor__reset() - - return self.inTransaction - - def __anyLeft(self): - if noWeakRef: - return len(self.cursors) > 0 - - return len(self.cursors.data.keys()) > 0 - - def __gcCursors(self): - # This routine, which will be called only if weak references are not - # available, will check the reference counts of the cursors in the - # connection.cursors list and close any that are only referenced - # from that list. This will clean up deleted cursors. - - for i in self.cursors[:]: - # Check the reference count. It will be 4 if it only exists in - # self.cursors. The magic number for is derived from the fact - # that there will be 1 reference count for each of the follwoing: - # self.cursors, self.cursors[:], i, and as the argument to - # getrefcount(), - - if getrefcount(i) < 5: - i.close() - - def __setupTransaction(self): - """ - __setupTransaction() - Internal routine that will set up a transaction for this connection.\n""" - self.conn.query("BEGIN WORK") - if self.TransactionLevel != "": - _nl = len(self.notices) - self.conn.query('SET TRANSACTION ISOLATION LEVEL %s' % - self.TransactionLevel) - if len(self.notices) != _nl: - raise Warning, self.notices.pop() - self.__dict__["inTransaction"] = 1 - - - def close(self): - """ - close() - Close the connection now (rather than whenever __del__ is called). - Any active cursors for this connection will be closed and the connection - will be unusable from this point forward.\n""" - - if not self._isOpen: - raise InterfaceError, "Connection is already closed." - - if self.__closeCursors(1): - try: - _nl = len(self.conn.notices) - self.conn.query("ROLLBACK WORK") - if len(self.notices) != _nl: - raise Warning, self.notices.pop() - except: - pass - - self.__dict__["_cache"] = None - self.__dict__["_isOpen"] = 0 - self.__dict__["autocommit"] = None - self.__dict__["conn"] = None - self.__dict__["cursors"] = None - self.__dict__["inTransaction"] = 0 - self.__dict__["TransactionLevel"] = None - self.__dict__["version"] = None - self.__dict__["notices"] = None - - def commit(self): - """ - commit() - Commit any pending transactions to the database.\n""" - - if not self._isOpen: - raise InterfaceError, "Commit failed - Connection is not open." - - if self.autocommit: - raise InterfaceError, "Commit failed - autocommit is on." - - if self.__closeCursors(): - self.__dict__["inTransaction"] = 0 - _nl = len(self.conn.notices) - res = self.conn.query("COMMIT WORK") - if len(self.notices) != _nl: - raise Warning, self.notices.pop() - if res.resultStatus != COMMAND_OK: - raise InternalError, "Commit failed - reason unknown." - - def rollback(self): - """ - rollback() - Rollback to the start of any pending transactions.\n""" - - if not self._isOpen: - raise InterfaceError, "Rollback failed - Connection is not open." - - if self.autocommit: - raise InterfaceError, "Rollback failed - autocommit is on." - - if self.__closeCursors(): - self.__dict__["inTransaction"] = 0 - _nl = len(self.conn.notices) - res = self.conn.query("ROLLBACK WORK") - if len(self.notices) != _nl: - raise Warning, self.notices.pop() - if res.resultStatus != COMMAND_OK: - raise InternalError, \ - "Rollback failed - %s" % res.resultErrorMessage - - def cursor(self, name=None, isRefCursor=PG_False): - """ - cursor([name]) - Returns a new 'Cursor Object' (optionally named 'name').""" - - if not self._isOpen: - raise InterfaceError, \ - "Create cursor failed - Connection is not open." - - return Cursor(self, name, isRefCursor) - - def binary(self, string=None): - """ - binary([string]) - Returns a new 'Large Object'. If sting is present, it is used to - initialize the large object.""" - - if not self._isOpen: - raise InterfaceError, \ - "Creation of large object failed - Connection is not open." - - if self.autocommit: - raise InterfaceError, \ - "Creation of large object failed - autocommit is on." - - _nl = len(self.notices) - _ct = 0 - # Ensure that we are in a transaction for working with large objects - if not self.inTransaction: - self.__setupTransaction() - _ct = 1 - - _lo = self.conn.lo_creat(INV_READ | INV_WRITE) - - if len(self.notices) != _nl: - raise Warning, self.notices.pop() - - if string: - _lo.open("w") - _lo.write(string) - _lo.close() - - if len(self.notices) != _nl: - if self.inTransaction: - self.conn.query("ROLLBACK WORK") - raise Warning, self.conn.notices.pop() - - return _lo - - def unlink(self, lobj): - """ - unlink(OID|PgLargeObject) - Remove a large object from the database inversion file syste.""" - - if not self._isOpen: - raise InterfaceError, \ - "Unlink of large object failed - Connection is not open." - - if not self.version.post70 and self.inTransaction: - raise NotSupportedError, \ - "unlink of a PostgreSQL Large Object in a transaction" - - if type(lobj) is IntType: - oid = lobj - elif type(lobj) is PgLargeObjectType: - oid = lobj.oid - - _nl = len(self.conn.notices) - res = self.conn.lo_unlink(oid) - if len(self.notices) != _nl: - raise Warning, self.notices.pop() - - return res - -#-----------------------------------------------------------------------+ -# Name: Cursor | -# | -# Description: Cursor defines the Python DB-API 2.0 cursor object. | -# See the DB-API 2.0 specification for details. | -#-----------------------------------------------------------------------+ - -class Cursor: - """Python DB-API 2.0 Cursor Object.""" - - def __init__(self, conn, name, isRefCursor=PG_False): - if not isinstance(conn, Connection): - raise TypeError, "Cursor requires a connection." - - # Generate a unique name for the cursor is one is not given. - if name is None: - if isRefCursor: - raise TypeError, "Reference cursor requires a name." - name = "PgSQL_%08X" % id(self) - elif type(name) is not StringType: - raise TypeError, "Cursor name must be a string." - - # Define the public variables for this cursor. - self.__dict__["arraysize"] = 1 - - # Define the private variables for this cursor. - if noWeakRef: - self.__dict__["conn"] = conn - else: - self.__dict__["conn"] = weakref.proxy(conn) - self.__dict__["name"] = name - - # This needs to be defined here sot that the initial call to __reset() - # will work. - self.__dict__["closed"] = None - self.__reset() - - # _varhdrsz is the length (in bytes) of the header for variable - # sized postgreSQL data types. - - self.__dict__["_varhdrsz"] = 4 - - # Add ourselves to the list of cursors for our owning connection. - if noWeakRef: - self.conn.cursors.append(self) - if len(self.conn.cursors) > 1: - # We have additional cursors, garbage collect them. - self.conn._Connection__gcCursors() - else: - self.conn.cursors[id(self)] = self - - if not self.conn.autocommit: - # Only the first created cursor begins the transaction. - if not self.conn.inTransaction: - self.conn._Connection__setupTransaction() - self.__dict__["PgResultSetClass"] = None - - if isRefCursor: - # Ok -- we've created a cursor, we will pre-fetch the first row in - # order to make the description array. Note: the first call to - # fetchXXX will return the pre-fetched record. - self.__dict__["closed"] = 0 - self.res = self.conn.conn.query('FETCH 1 FROM "%s"' % self.name) - self._rows_ = self.res.ntuples - self._idx_ = 0 - self.__makedesc__() - - def __del__(self): - # Ensure that the cursor is closed when it is deleted. This takes - # care of some actions that needs to be completed when a cursor is - # deleted, such as disassociating the cursor from the connection - # and closing an open transaction if this is the last cursor for - # the connection. - if not self.closed: - self.close() - - def __reset(self): - try: - if (self.closed == 0) and self.conn.inTransaction: - try: - self.conn.conn.query('CLOSE "%s"' % self.name) - except: - pass - except: - pass - - self.__dict__["res"] = None - # closed is a trinary variable: - # == None => Cursor has not been opened. - # == 0 => Cursor is open. - # == 1 => Curosr is closed. - self.__dict__["closed"] = None - self.__dict__["description"] = None - self.__dict__["oidValue"] = None - self.__dict__["_mapname"] = None - self.__dict__["_rows_"] = 0 - self.__dict__["_idx_"] = 1 - self.__dict__["rowcount"] = -1 - - def __setattr__(self, name, value): - if self.closed: - raise InterfaceError, "Operation failed - the cursor is closed." - - if name in ["rowcount", "oidValue", "description"]: - raise AttributeError, "%s is read-only." % name - elif self.__dict__.has_key(name): - self.__dict__[name] = value - else: - raise AttributeError, name - - def __unicodeConvert(self, obj): - if type(obj) is StringType: - return obj - elif type(obj) is UnicodeType: - return obj.encode(*self.conn.client_encoding) - elif type(obj) in (ListType, TupleType): - converted_obj = [] - for item in obj: - if type(item) is UnicodeType: - converted_obj.append(item.encode(*self.conn.client_encoding)) - else: - converted_obj.append(item) - return converted_obj - elif type(obj) is DictType: - converted_obj = {} - for k, v in obj.items(): - if type(v) is UnicodeType: - converted_obj[k] = v.encode(*self.conn.client_encoding) - else: - converted_obj[k] = v - return converted_obj - elif isinstance(obj, PgResultSet): - obj = copy.copy(obj) - for k, v in obj.items(): - if type(v) is UnicodeType: - obj[k] = v.encode(*self.conn.client_encoding) - return obj - else: - return obj - - def __fetchOneRow(self): - if self._idx_ >= self._rows_: - self.__dict__['rowcount'] = 0 - return None - - _j = [] - _r = self.res - _c = self.conn._cache - for _i in range(self.res.nfields): - _j.append(_c.typecast(self.description[_i], - _r.getvalue(self._idx_, _i))) - - self._idx_ = self._idx_ + 1 - - self.__dict__['rowcount'] = 1 - - if fetchReturnsList: - # Return a list (This is the minimum required by DB-API 2.0 - # compliance). - return _j - else: - return self.PgResultSetClass(_j) - - def __fetchManyRows(self, count, iList=[]): - _many = iList - if count < 0: - while 1: - _j = self.__fetchOneRow() - if _j is not None: - _many.append(_j) - else: - break - elif count > 0: - for _i in range(count): - _j = self.__fetchOneRow() - if _j is not None: - _many.append(_j) - else: - break - - self.__dict__['rowcount'] = len(_many) - - return _many - - def __makedesc__(self): - # Since __makedesc__ will only be called after a successful query or - # fetch, self.res will contain the information needed to build the - # description attribute even if no rows were returned. So, we always - # build up the description. - self.__dict__['description'] = [] - self._mapname = {} - _res = self.res - _cache = self.conn._cache - for _i in range(_res.nfields): - _j = [] - - _j.append(_res.fname(_i)) - - _typ = PgTypes(_res.ftype(_i)) - _mod = _res.fmod(_i) - _tn, _pl, _ia, _bt = _cache.getTypeInfo(_typ) - if _ia: - _s, _pl, _s, _s = _cache.getTypeInfo(_bt) - if _bt == PG_OID: - _bt = PgTypes(PG_BLOB) - _typ = _bt - elif _typ.value == PG_OID: - try: - _p = _res.getvalue(0, _i) - except (ValueError, TypeError), m: - # We can only guess here ... - _typ = PgTypes(PG_BLOB) - else: - if type(_p) in [PgLargeObjectType, NoneType]: - _typ = PgTypes(PG_BLOB) - else: - _typ = PgTypes(PG_ROWID) - - _j.append(_typ) - - # Calculate Display size, Internal size, Precision and Scale. - # Note: Precision and Scale only have meaning for PG_NUMERIC - # columns. - if _typ.value == PG_NUMERIC: - if _mod == -1: - # We have a numeric with no scale/precision. - # Get them from by converting the string to a PgNumeric - # and pulling them form the PgNumeric object. If that - # fails default to a precision of 30 with a scale of 6. - try: - nv = PgNumeric(_res.getvalue(0, _i)) - _p = nv.getPrecision() - _s = nv.getScale() - except (ValueError, TypeError), m: - _p = 30 - _s = 6 - else: - # We hava a valid scale/precision value. Use them. - _s = _mod - self._varhdrsz - _p = (_s >> 16) & 0xffff - _s = _s & 0xffff - _j.append(None) # Display size (always None since PG7.3) - _j.append(_p) # Internal (storage) size - _j.append(_p) # Precision - _j.append(_s) # Scale - else: - if _pl == -1: - _pl = _res.fsize(_i) - if _pl == -1: - _pl = _mod - self._varhdrsz - _j.append(None) # Display size (always None since PG7.3) - _s = _res.fsize(_i) - if _s == -1: - _s = _mod - _j.append(_s) # Internal (storage) size - if _typ.value == PG_MONEY: - _j.append(9) # Presicion and Scale (from - _j.append(2) # the PostgreSQL doco.) - else: - _j.append(None) # Preision - _j.append(None) # Scale - - _j.append(None) # nullOK is not implemented (yet) - _j.append(_ia) # Array indicator (PostgreSQL specific) - - self.__dict__["description"].append(_j) - - # Add the fieldname:fieldindex to the _mapname dictionary - self._mapname[_j[0]] = _i - - # Create a subclass of PgResultSet. Note that we pass a copy of the - # description to this class. - self.PgResultSetClass = make_PgResultSetClass(self.description[:], self._mapname) - - def callproc(self, proc, *args): - if self.closed: - raise InterfaceError, "callproc failed - the cursor is closed." - - if self.conn is None: - raise Error, "connection is closed." - - if self.closed == 0: - raise InterfaceError, "callproc() failed - cursor is active." - - if self.conn.autocommit: - pass - else: - if not self.conn.inTransaction: - self.conn._Connection__setupTransaction() - - proc = self.__unicodeConvert(proc) - args = self.__unicodeConvert(args) - - _qstr = "select %s(" % proc - for _i in range(len(args)): - _qstr = '%s%s, ' % (_qstr, _quote(args[_i])) - if len(args) == 0: - _qstr = '%s)' % _qstr - else: - _qstr = '%s)' % _qstr[:-2] - - _nl = len(self.conn.notices) - - try: - self.res = self.conn.conn.query(_qstr) - self._rows_ = self.res.ntuples - self._idx_ = 0 - if type(self.res) is not PgResultType: - self.__dict__['rowcount'] = -1 - else: - self.__dict__['oidValue'] = self.res.oidValue - if self.res.resultType == RESULT_DQL: - pass - elif self.res.resultType == RESULT_DML: - self.__dict__['rowcount'] = self.res.cmdTuples - else: - self.__dict__['rowcount'] = -1 - except OperationalError, msg: - # Uh-oh. A fatal error occurred. This means the current trans- - # action has been aborted. Try to recover to a sane state. - if self.conn.inTransaction: - self.conn.conn.query('END WORK') - self.conn.__dict__["inTransaction"] = 0 - self.conn._Connection__closeCursors() - raise OperationalError, msg - except InternalError, msg: - # An internal error occured. Try to get to a sane state. - self.conn.__dict__["inTransaction"] = 0 - self.conn._Connection__closeCursors_() - self.conn.close() - raise InternalError, msg - - if len(self.conn.notices) != _nl: - _drop = self.conn.notices[-1] - if _drop.find('transaction is aborted') > 0: - raise Warning, self.conn.notices.pop() - - self._rows_ = self.res.ntuples - self._idx_ = 0 - self.__dict__['rowcount'] = -1 # New query - no fetch occured yet. - self.__makedesc__() - - return None - - def close(self): - if self.closed: - raise InterfaceError, "The cursor is already closed." - - # Dis-associate ourselves from our cursor. - self.__reset() - try: - _cc = self.conn.cursors - if noWeakRef: - _cc.remove(self) - if (len(_cc) > 0): - # We have additional cursors, garbage collect them. - _cc._Connection__gcCursors() - else: - del _cc.data[id(self)] - except: - pass - self.conn = None - self.closed = 1 - - def execute(self, query, *parms): - if self.closed: - raise InterfaceError, "execute failed - the cursor is closed." - - if self.conn is None: - raise Error, "connection is closed." - - if self.closed == 0: - if re_DQL.search(query): - # A SELECT has already been executed with this cursor object, - # which means a PostgreSQL portal (may) have been opened. - # Trying to open another portal will cause an error to occur, - # so we asusme that the developer is done with the previous - # SELECT and reset the cursor object to it's inital state. - self.__reset() - - _qstr = query - if self.conn.autocommit: - pass - else: - _badQuery = (self.conn.version < 70100) and \ - (re_DRT.search(query) or re_DRI.search(query)) - if not self.conn.inTransaction: - if _badQuery: - pass # PostgreSQL version < 7.1 and not in transaction, - # so DROP TABLE/INDEX is ok. - else: - self.conn._Connection__setupTransaction() - - if re_DQL.search(query) and \ - not (noPostgresCursor or re_4UP.search(query)): - _qstr = 'DECLARE "%s" CURSOR FOR %s' % (self.name, query) - self.closed = 0 - elif _badQuery and self.conn.inTransaction: - raise NotSupportedError, \ - "DROP [TABLE|INDEX] within a transaction" - if not self.conn.inTransaction: - if _badQuery: - pass # not in transaction so DROP TABLE/INDEX is ok. - else: - self.conn._Connection__setupTransaction() - - _nl = len(self.conn.notices) - - try: - _qstr = self.__unicodeConvert(_qstr) - if len(parms) == 0: - # If there are no paramters, just execute the query. - self.res = self.conn.conn.query(_qstr) - else: - if len(parms) == 1 and \ - (type(parms[0]) in [DictType, ListType, TupleType] or \ - isinstance(parms[0], PgResultSet)): - parms = (self.__unicodeConvert(parms[0]),) - parms = _quoteall(parms[0]) - else: - parms = self.__unicodeConvert(parms) - parms = tuple(map(_quote, parms)); - self.res = self.conn.conn.query(_qstr % parms) - self._rows_ = self.res.ntuples - self._idx_ = 0 - self.__dict__['rowcount'] = -1 # New query - no fetch occured yet. - if type(self.res) is not PgResultType: - self.__dict__['rowcount'] = -1 - else: - self.__dict__['oidValue'] = self.res.oidValue - if self.res.resultType == RESULT_DQL: - pass - elif self.res.resultType == RESULT_DML: - self.__dict__['rowcount'] = self.res.cmdTuples - else: - self.__dict__['rowcount'] = -1 - except OperationalError, msg: - # Uh-oh. A fatal error occurred. This means the current trans- - # action has been aborted. Try to recover to a sane state. - if self.conn.inTransaction: - _n = len(self.conn.notices) - self.conn.conn.query('ROLLBACK WORK') - if len(self.conn.notices) != _n: - raise Warning, self.conn.notices.pop() - self.conn.__dict__["inTransaction"] = 0 - self.conn._Connection__closeCursors() - raise OperationalError, msg - except InternalError, msg: - # An internal error occured. Try to get to a sane state. - self.conn.__dict__["inTransaction"] = 0 - self.conn._Connection__closeCursors_() - self.conn.close() - raise InternalError, msg - - if len(self.conn.notices) != _nl: - _drop = self.conn.notices[-1] - if _drop.find('transaction is aborted') > 0: - raise Warning, self.conn.notices.pop() - - if self.res.resultType == RESULT_DQL: - self.__makedesc__() - elif _qstr[:8] == 'DECLARE ': - # Ok -- we've created a cursor, we will pre-fetch the first row in - # order to make the description array. Note: the first call to - # fetchXXX will return the pre-fetched record. - self.res = self.conn.conn.query('FETCH 1 FROM "%s"' % self.name) - self._rows_ = self.res.ntuples - self._idx_ = 0 - self.__makedesc__() - - if len(self.conn.notices) != _nl: - _drop = self.conn.notices[-1] - if _drop.find('transaction is aborted') > 0: - raise Warning, self.conn.notices.pop() - - def executemany(self, query, parm_sequence): - if self.closed: - raise InterfaceError, "executemany failed - the cursor is closed." - - if self.conn is None: - raise Error, "connection is closed." - - for _i in parm_sequence: - self.execute(query, _i) - - def fetchone(self): - if self.closed: - raise InterfaceError, "fetchone failed - the cursor is closed." - - if self.conn is None: - raise Error, "connection is closed." - - if self.res is None: - raise Error, \ - "fetchone() failed - cursor does not contain a result." - elif self.res.resultType != RESULT_DQL: - if self.closed is None: - raise Error, \ - "fetchone() Failed - cursor does not contain any rows." - - if self._idx_ < self._rows_: - pass # Still data in result buffer, use it. - elif self.closed == 0: - _nl = len(self.conn.notices) - self.res = self.conn.conn.query('FETCH 1 FROM "%s"' % self.name) - self._rows_ = self.res.ntuples - self._idx_ = 0 - - if len(self.conn.notices) != _nl: - _drop = self.conn.notices[-1] - if _drop.find('transaction is aborted') > 0: - raise Warning, self.conn.notices.pop() - - return self.__fetchOneRow() - - def fetchmany(self, sz=None): - if self.closed: - raise InterfaceError, "fetchmany failed - the cursor is closed." - - if self.conn is None: - raise Error, "connection is closed." - - if self.res is None: - raise Error, \ - "fetchmany() failed - cursor does not contain a result." - elif self.res.resultType != RESULT_DQL: - if self.close is None: - raise Error, \ - "fetchmany() Failed - cursor does not contain any rows." - - if sz is None: - sz = self.arraysize - else: - self.__dict__["arraysize"] = abs(sz) - - if sz < 0: - return self.fetchall() - - _list = [] - - # While there are still results in the PgResult object, append them - # to the list of results. - while self._idx_ < self._rows_ and sz > 0: - _list.append(self.__fetchOneRow()) - sz = sz - 1 - - # If still need more results to fullfill the request, fetch them from - # the PostgreSQL portal. - if self.closed == 0 and sz > 0: - _nl = len(self.conn.notices) - self.res = self.conn.conn.query('FETCH %d FROM "%s"' % - (sz, self.name)) - self._rows_ = self.res.ntuples - self._idx_ = 0 - - if len(self.conn.notices) != _nl: - _drop = self.conn.notices[-1] - if _drop.find('transaction is aborted') > 0: - raise Warning, self.conn.notices.pop() - - return self.__fetchManyRows(sz, _list) - - def fetchall(self): - if self.closed: - raise InterfaceError, "fetchall failed - the cursor is closed." - - if self.conn is None: - raise Error, "connection is closed." - - if self.res is None: - raise Error, \ - "fetchall() failed - cursor does not contain a result." - elif self.res.resultType != RESULT_DQL: - if self.closed is None: - raise Error, \ - "fetchall() Failed - cursor does not contain any rows." - - _list = [] - - # While there are still results in the PgResult object, append them - # to the list of results. - while self._idx_ < self._rows_: - _list.append(self.__fetchOneRow()) - - # Fetch the remaining results from the PostgreSQL portal. - if self.closed == 0: - _nl = len(self.conn.notices) - self.res = self.conn.conn.query('FETCH ALL FROM "%s"' % self.name) - self._rows_ = self.res.ntuples - self._idx_ = 0 - - if len(self.conn.notices) != _nl: - _drop = self.conn.notices[-1] - if _drop.find('transaction is aborted') > 0: - raise Warning, self.conn.notices.pop() - - return self.__fetchManyRows(self._rows_, _list) - - def rewind(self): - if self.closed: - raise InterfaceError, "rewind failed - the cursor is closed." - - if self.conn is None: - raise Error, "connection is closed." - - if self.res is None: - raise Error, "rewind() failed - cursor does not contain a result." - elif self.res.resultType != RESULT_DQL: - if self.closed is None: - raise Error, \ - "rewind() Failed - cursor does not contain any rows." - - if self.closed == 0: - _nl = len(self.conn.notices) - self.res = self.conn.conn.query('MOVE BACKWARD ALL IN "%s"' % - self.name) - self._rows_ = 0 - if len(self.conn.notices) != _nl: - _drop = self.conn.notices[-1] - if _drop.find('transaction is aborted') > 0: - raise Warning, self.conn.notices.pop() - - self.__dict__["rowcount"] = -1 - self._idx_ = 0 - - def setinputsizes(self, sizes): - if self.closed: - raise InterfaceError, "setinputsize failed - the cursor is closed." - - def setoutputsize(self, size, column=None): - if self.closed: - raise InterfaceError, "setoutputsize failed - the cursor is closed." diff --git a/pgworksheet_1.9/pgw/RunSQL.py b/pgworksheet_1.9/pgw/RunSQL.py deleted file mode 100644 index 77ecc30..0000000 --- a/pgworksheet_1.9/pgw/RunSQL.py +++ /dev/null @@ -1,233 +0,0 @@ -# -*- coding: latin-1; -*- -# -# PgWorksheet - PostgreSQL Front End -# http://pgworksheet.projects.postgresql.org/ -# -# Copyright © 2004-2008 Henri Michelon & CML http://www.e-cml.org/ -# -# 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 (read LICENSE.txt). -# -# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# $Id -# -import string -import pygtk -import gtk - -import pgw - - -class RunSQL: - """Execute the SQL buffer and fill the GtkNotebook with the results.""" - - def __init__(self, execute, txtSQL, tabResult, result): - self.execute = execute - self.txtSQL = txtSQL - self.lblResult = result - self.tabResult = tabResult - self.error_font = {} - - - def result(self, msg): - """update status bar text""" - self.lblResult.set_markup('' + msg + '') - - - def str_limit(self, s, max = 20): - s = string.replace(s, '\\\\', '\\') - if (len(s) > (max + 3)): - return s[:max] + "..." - return s - - - def error(self, msg, title = None): - """update the error messages""" - if (title is None): - title = '' + _('Errors') + '' - scroll = gtk.ScrolledWindow() - txt = gtk.TextView() - txt.get_buffer().set_text(unicode(msg, pgw.get_user_encoding())) - pgw.set_proportional(txt.get_buffer()) - txt.set_editable(False) - scroll.add(txt) - scroll.show_all() - label = gtk.Label() - label.set_markup(title) - self.tabResult.append_page(scroll, label) - - - def add_treeview(self, title): - """Add a new tree view""" - scroll = gtk.ScrolledWindow() - tvw = gtk.TreeView() - scroll.add(tvw) - scroll.show() - label = gtk.Label(title) - self.tabResult.append_page(scroll, label) - return (tvw, label) - - - def fill_treeview(self, sql, result): - """build the tree view columns and rows""" - sql = sql.strip() - treeview, label = self.add_treeview(self.str_limit(sql)) - type_str = "" - cell = gtk.CellRendererText() - ncol = 0 - for col in result.description: - column = gtk.TreeViewColumn(string.replace(col[0], "_", "__")) - column.pack_start(cell, True) - column.add_attribute(cell, 'text', ncol) - column.set_sort_column_id(ncol) - treeview.append_column(column) - ncol = ncol + 1 - if (type_str == ""): - type_str = "str" - else: - type_str = type_str + ",str" - pass - - # dynamically create the liststore - code = "liststore = gtk.ListStore(" + type_str + ")" - exec compile(code, "", 'exec') - - # fill the tree view - row = result.fetchone() - rows = 0 - while ( row is not None ) : - c = 0 - while c < len(row): - if (row[c] is None) and type(row) == list: - row[c] = '(null)' - c = c + 1 - liststore.append(row) - row = result.fetchone() - rows = rows + 1 - result.close() - treeview.set_model(liststore) - treeview.set_reorderable(True) - treeview.columns_autosize() - treeview.show() - label.set_markup(label.get_text() + ' : ' + - str(rows) + "") - return rows - - - def run(self): - """Run the query and update the results""" - # clear the treeviews and the error text buffers - for child in self.tabResult.get_children(): - self.tabResult.remove(child) - self.result(_("Please wait, executing the query and fetching the results...")) - # update the display - while (gtk.events_pending() == True): - gtk.main_iteration_do(False) - - # execute the query - sqlbuffer= self.txtSQL.get_buffer() - notices = [] - try: - result = self.execute.execute(sqlbuffer) - rows = 0 - if (isinstance(result, list)): - # multiple queries and multiple results... - parts = self.execute.split(sqlbuffer) - sqls = [] - have_errors = 0 - for sql in parts : - sql = string.strip(sql) - if (len(sql) > 0) : - sqls.append(sql) - for res in result: - sql = sqls.pop(0) - try: - if (res['cursor'].description is not None): - rows += self.fill_treeview(sql, res['cursor']) - else: - rows += res['cursor'].rowcount - notices = res['notices'] - except KeyError: - try: - self.error(res['text'], "psql : " + self.str_limit(sql)) - except KeyError: - notices = res['notices'] - self.error(res['error'], - '' + _('Errors :') + ' ' + - self.str_limit(sql)) - have_errors += 1 - self.tabResult.set_current_page(0) - if (rows > 1): - res_str = _("%d results or affected rows") % rows - elif (rows == 1): - res_str = _("1 result or affected row") - else: - res_str = _("No result or no affected row") - if (have_errors > 1) : - res_str += ', ' + \ - _('%d queries failed') % have_errors + '' - elif (have_errors > 0) : - res_str += ', ' + \ - _('1 query failed') + '' - self.result(res_str) - else: # one query - sql = sqlbuffer.get_text(sqlbuffer.get_start_iter(), - sqlbuffer.get_end_iter()) - try: - if (result is None): - self.result(_("No result")) - elif (result['cursor'].description is None): - # not a SELECT - rows = result['cursor'].rowcount - notices = result['notices'] - if (rows > 1): - self.result(_("%d rows affected") % rows) - elif (rows == 1): - self.result(_("1 row affected")) - else: - self.result(_("No row affected")) - else: - # only one SELECT - rows = self.fill_treeview(sql, result['cursor']) - notices = result['notices'] - if (rows > 1): - self.result(_("%d results") % rows) - elif (rows == 1): - self.result(_("1 result")) - else: - self.result(_("No result")) - except KeyError: - try: - self.error(result['text'], "psql : " + self.str_limit(sql)) - self.result("") - except KeyError: - self.error(result['error']) - self.result('' + _('query failed') + '') - notices = result['notices'] - buffer = self.txtSQL.get_buffer() - buffer.move_mark_by_name('selection_bound', buffer.get_start_iter()); - buffer.move_mark_by_name('insert', buffer.get_end_iter()); - - except KeyError, errstr: - self.result('' + _('query failed') + '') - self.error(str(errstr)) - - if (len(notices) > 0): - msg = "" - while len(notices): - msg += notices.pop() - self.error(msg, ''+ _("log") + '') - - # restore the focus - self.txtSQL.grab_focus() - diff --git a/pgworksheet_1.9/pgw/Syntax.py b/pgworksheet_1.9/pgw/Syntax.py deleted file mode 100644 index 21ae87a..0000000 --- a/pgworksheet_1.9/pgw/Syntax.py +++ /dev/null @@ -1,782 +0,0 @@ -#!/usr/bin/env python -# -*- coding: latin-1; -*- -# -# PgWorksheet - PostgreSQL Front End -# http://pgworksheet.projects.postgresql.org/ -# -# Copyright © 2004-2008 Henri Michelon & CML http://www.e-cml.org/ -# -# 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 (read LICENSE.txt). -# -# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# $Id: Syntax.py,v 1.30 2008/03/12 20:26:23 hmichelon Exp $ -# -import gtk.gdk -import pango -import pgw -import pgw.Lexical - -# built-in data types and extensions -TYPES = [ 'BIGINT', 'INT8', 'BIGSERIAL', 'SERIAL8', 'BIT', 'VARYING', - 'VARBIT', 'BOOL', 'BOOLEAN', 'BOX', 'BYTEA', 'CHARACTER', 'VARCHAR', - 'CHAR', 'CIDR', 'CIRCLE', 'DATE', 'DOUBLE', 'PRECISION', - 'INET', 'INTEGER', 'FLOAT8', 'INT', 'INT4', 'INTERVAL', - 'LINE', 'LSEG', 'MACADDR', 'MONEY', 'NUMERIC', 'DECIMAL', - 'PATH', 'POINT', 'POLYGON', 'REAL', 'FLOAT4', 'SMALLINT', - 'INT2', 'SERIAL', 'SERIAL4', 'TEXT','TIME', 'TIMESTAMP', - 'TIMETZ', 'TIMESTAMPTZ', 'WITHOUT', 'TIME', 'ZONE' - ] - -# special constants -SPECIALS = [ 'FALSE', 'NULL', 'TRUE', 'UNKNOWN', 'ALL', 'ANY', 'SOME' ] - - -# named operators, constructs, conditionals and subqueries -OPERATORS2 = [ 'OVERLAPS', 'AND', 'OR', 'NOT', 'BETWEEN', 'IS', 'ISNULL', - 'NOTNULL', 'CAST', 'LIKE', 'ILIKE', 'SIMILAR', - 'EXISTS', 'IN', - 'CASE', 'WHEN', 'THEN', 'ELSE', 'END', - 'UNION', 'ARRAY', - ] - -# SQL and PostgreSQL statements -STATEMENTS = [ 'ABORT', 'ALTER', 'ANALYSE', 'BEGIN', 'CHECKPOINT', 'CLOSE', - 'CLUSTER', 'COMMENT', 'COMMIT', 'COPY', 'CREATE', 'DEALLOCATE', - 'DECLARE', 'DELETE', 'DROP', 'END', 'EXECUTE', 'EXPLAIN', - 'FETCH', 'GRANT', 'INSERT', 'LISTEN', 'LOAD', 'LOCK', 'MOVE', - 'NOTIFY', 'PREPARE', 'REINDEX', 'RELEASE', 'RESET', 'REVOKE', - 'ROLLBACK', 'SAVEPOINT', 'SELECT', 'SET', 'SHOW', 'START', - 'TRUNCATE', 'UNLISTEN', 'UPDATE', 'VACUUM' ] - -# built-in functions -BUILTINS = [ - # MATH - 'ABS', 'CBTR', 'CEIL', 'CEILING', 'DEGREES', 'EXP', 'FLOOR', 'LN', - 'LOG', 'MOD', 'PI', 'POWER', 'RADIANS', 'RANDOM', 'ROUND', - 'SETSEED', 'SIGN', 'SQRT', 'TRUNC', 'WIDTH_BUCKET', 'ACOS', - 'ASIN', 'ATAN', 'ATAN2', 'COS', 'COT', 'SIN', 'TAN', - # STRING - 'BIT_LENGTH', 'CHAR_LENGTH', 'CONVERT', 'LOWER', 'OCTET_LENGTH', - 'OVERLAY', 'POSITION', 'SUBSTRING', 'TRIM', 'UPPER', 'ASCII', - 'BTRIM', 'CHR', 'DECODE', 'ENCODE', 'INITCAP', 'LENGTH', - 'LPAD', 'LTRIM', 'MD5', 'PG_CLIENT_ENCODING', 'QUOTE_IDENT', - 'QUOTE_LITERAL', 'REPEAT', 'RPAD', 'RTRIM', 'SPLIT_PART', - 'STRPOS', 'TO_ASCII', 'TO_HEX', 'TRANSLATE', - # BSTRING - 'GET_BYTE', 'SET_BYTE', 'GET_BIT', 'SET_BIT', - # DATE - 'TO_CHAR', 'TO_DATE', 'TO_TIMESTAMP', 'TO_NUMBER', - 'AGE', 'DATE_PART', 'DATE_TRUNC', 'EXTRACT', 'ISFINITE', - 'NOW', 'TIMEOFDAY', - # GEOMETRIC - 'AREA', 'BOX_INTERSECT', 'CENTER', 'DIAMETER', 'HEIGHT', - 'ISCLOSED', 'ISOPEN', 'LENGTH', 'NPOINTS', 'PCLOSE', - 'POPEN', 'RADIUS', 'WIDTH', 'BOX', 'CIRCLE', 'LSEG', - 'PATH', 'POINT', 'POLYGON', - # NETWORK - 'BROADCAST', 'HOST', 'MASKLEN', 'SET_MASKLEN', - 'NETMASK', 'HOSTMASK', 'NETWORK', 'TEXT', 'ABBREV', - 'FAMILY', 'TRUNC', - # SEQUENCES - 'NEXTVAL', 'CURRVAL', - # CONDITIONAL - 'COALESCE', 'NULLIF', - # ARRAY - 'ARRAY_CAT', 'ARRAY_APPEND', 'ARRAY_PREPEND', 'ARRAY_DIMS', - 'ARRAY_LOWER', 'ARRAY_UPPER', 'ARRAY_TO_STRING', - 'STRING_TO_ARRAY' - # AGGREGATE - 'AVG', 'BIT_AND', 'BIT_OR', 'BOOL_AND', 'BOOL_OR', - 'COUNT', 'EVERY', 'MAX', 'MIN', 'STDDEV', 'SUM', - 'VARIANCE' - # SETS - 'GENERATE_SERIES', - # SYSTEM - 'CURRENT_DATABASE', 'CURRENT_SCHEMA', - 'INET_CLIENT_ADDR', 'INET_CLIENT_PORT', - 'INET_SERVER_ADDR', 'INET_SERVER_PORT', 'VERSION', - 'HAS_TABLE_PRIVILEGE', 'HAS_DATABASE_PRIVILEGE', - 'HAS_FUNCTION_PRIVILEGE', 'HAS_LANGUAGE_PRIVILEGE', - 'HAS_SCHEMA_PRIVILEGE', 'HAS_TABLESPACE_PRIVILEGE' - 'PG_TABLE_IS_VISIBLE', 'PG_TYPE_IS_VISIBLE', - 'PG_FUNCTION_IS_VISIBLE', 'PG_OPERATOR_IS_VISIBLE', - 'PG_OPCLASS_IS_VISIBLE', 'PG_CONVERSION_IS_VISIBLE', - 'FORMAT_TYPE', 'PG_GET_VIEWDEF', 'PG_GET_RULEGET', - 'PG_GET_INDEXDEF', 'PG_GET_TRIGGERDEF', - 'PG_GET_CONSTRAINTDEF', 'PG_GET_EXPR', 'PG_GET_USERBYID', - 'PG_GET_SERIAL_SEQUENCE', 'PG_TABLESPACE_DATABASES', - 'OBJ_DESCRIPITION', - # SYSTEM ADMIN - 'CURRENT_SETTINGS', 'SET_CONFIG', 'PG_CANCEL_BACKEND', - 'PG_START_BACKUP', 'PG_STOP_BACKUP', - - ] - -# built-in functions that can be used without () -# or conditional expressions -BUILTINS2 = [ # DATE - 'CURRENT_DATE', 'CURRENT_TIME', 'CURRENT_TIMESTAMP', - 'LOCALTIME', 'LOCALTIMESTAMP', - # SYSTEM - 'CURRENT_USER', 'SESSION_USER', 'USER', - ] - - -""" -# PL/PgSQL keywords -PLPGSQL = [ # structure - 'DECLARE', 'BEGIN', 'END', - # declarations - 'RECORD', 'DEFAULT', 'CONSTANT', 'ALIAS', 'FOR', 'TYPE', 'ROWTYPE', - 'RENAME', 'TO', - # Statements - 'FOUND', 'PERFORM', 'GET', 'DIAGNOSTICS', - # Control Structures - 'RETURN', 'NEXT', 'IF', 'THEN', 'ELSE', 'END', 'ELSIF', 'LOOP', - 'EXIT', 'WHILE', 'REVERSE', 'IN', 'EXCEPTION', 'WHEN', - # Cursors - 'CURSOR', 'OPEN', 'EXECUTE', 'FETCH', 'INTO', 'CLOSE', - # Errors - 'RAISE', 'DEBUG', 'LOG', 'INFO', 'NOTICE', 'WARNING', 'EXCEPTION', - # Trigger Procedures - 'NEW', 'OLD', 'TG_NAME', 'TG_WHEN', 'TG_LEVEL', 'TG_OP', - 'TG_RELID', 'TG_RELNAME', 'TG_NARGS', 'TG_ARGV', - ] -""" - -# keywords for each statement -KEYWORDS = { 'ABORT' : [ 'WORK', 'TRANSACTION' ], - 'ALTER' : { 'AGGREGATE' : [ [ 'RENAME', 'TO' ], - [ 'OWNER', 'TO' ] - ], - 'CONVERSION' : [ [ 'RENAME', 'TO' ], - [ 'OWNER', 'TO' ] - ], - 'DATABASE' : [ 'SET', 'TO', 'DEFAULT', - 'RESET', [ 'RENAME', 'TO' ], - [ 'OWNER', 'TO' ] - ], - 'DOMAIN' : [ [ 'SET', 'DEFAULT' ], - [ 'DROP', 'DEFAULT' ], - 'ADD', - [ 'DROP', 'CONSTRAINT' ], - 'RESTRICT', 'CASCADE', - [ 'OWNER', 'TO' ] - ], - 'FUNCTION' : [ [ 'RENAME', 'TO' ], - [ 'OWNER', 'TO' ] - ], - 'GROUP' : [ [ 'ADD', 'USER' ], - [ 'DROP', 'USER' ], - [ 'RENAME', 'TO' ] - ], - 'INDEX' : [ [ 'RENAME', 'TO' ], - [ 'OWNER', 'TO' ], - [ 'SET', 'TABLESPACE' ] - ], - 'LANGUAGE' : [ [ 'RENAME', 'TO' ] ], - 'OPERATOR' : [ 'NONE', [ 'OWNER', 'TO' ], - 'CLASS', 'USING' - ], - 'SCHEMA' : [ [ 'RENAME', 'TO' ], - [ 'OWNER', 'TO' ] - ], - 'SEQUENCE' : [ [ 'INCREMENT', 'BY' ], - 'MINVALUE', 'MAXVALUE', - [ 'RESTART', 'WITH' ], 'CACHE', - 'NO', 'CYCLE' - ], - 'TABLE' : [ 'ONLY', [ 'RENAME', 'COLUMN' ], - [ 'RENAME', 'TO' ], 'TO', - [ 'ADD', 'COLUMN' ], - [ 'DROP', 'COLUMN' ], 'RESTRICT', - 'CASCADE', 'TYPE', 'USING', - [ 'ALTER', 'COLUMN' ], - [ 'SET', 'DEFAULT' ], - [ 'DROP', 'DEFAULT' ], - 'SET', 'DROP', - [ 'SET', 'STATISTICS' ], - [ 'SET', 'STORAGE' ], 'PLAIN', - 'EXTERNAL', 'EXTERNAL', 'MAIN', - [ 'DROP', 'CONSTRAINT' ], - [ 'CLUSTER', 'ON' ], - [ 'SET', 'WITHOUT', 'CLUSTER' ], - [ 'SET', 'WITHOUT', 'OIDS' ], - [ 'OWNER', 'TO' ], - [ 'SET', 'TABLESPACE' ], - 'CHECK', - [ 'FOREIGN', 'KEY' ], 'CASCADE', - [ 'PRIMARY', 'KEY' ], - [ 'ON', 'DELETE' ], - [ 'ON', 'UPDATE' ], 'REFERENCES', - ], - 'TABLESPACE' : [ [ 'RENAME', 'TO' ], - [ 'OWNER', 'TO' ] - ], - 'TRIGGER' : [ 'ON', [ 'RENAME', 'TO' ] ], - 'TYPE' : [ [ 'OWNER', 'TO' ] ], - 'USER' : [ 'WITH', 'CREATEDB', 'NOCREATEDB', - 'CREATEUSER', 'NOCREATEUSER', - 'ENCRYPTED', 'UNENCRYPTED', - 'PASSWORD', [ 'VALID', 'UNTIL' ], - [ 'RENAME', 'TO' ], 'SET', - 'TO', 'DEFAULT', 'RESET' - ], - }, - 'ANALYZE' : [ 'VERBOSE' ], - 'BEGIN' : [ 'WORK', 'TRANSACTION', [ 'ISOLATION', 'LEVEL' ], - 'SERIALIZABLE', [ 'REPEATABLE', 'READ' ], - [ 'READ', 'COMMITTED' ], [ 'READ', 'UNCOMMITTED' ], - [ 'READ', 'WRITE' ], [ 'READ', 'ONLY' ] - ], - 'CHECKPOINT' : [], - 'CLOSE' : [], - 'CLUSTER' : [ 'ON' ], - 'COMMENT' : { 'ON' : [ 'TABLE', 'COLUMN', 'AGGREGATE', 'CAST', - 'AS', 'CONSTRAINT', 'ON', 'CONVERSION', - 'DATABASE', 'DOMAIN', 'FUNCTION', 'INDEX', - [ 'LARGE', 'OBJECT' ], 'OPERATOR', - [ 'OPERATOR', 'CLASS' ], 'USING', - 'PROCEDURAL', 'LANGUAGE', 'RULE', - 'SCHEMA', 'SEQUENCE', 'TRIGGER', - 'TYPE', 'VIEW', 'IS' - ] - }, - 'COMMIT' : [ 'WORK', 'TRANSACTION' ], - 'COPY' : [ 'FROM', 'STDIN', 'WITH', 'BINARY', 'OIDS', - 'DELIMITER', 'CSV', 'AS', 'ESCAPE' - 'FORCE', 'TO', 'STDOUT', 'QUOTE' - ], - 'CREATE' : { 'AGGREGATE' : [ 'BASETYPE', 'SFUNC', 'STYPE', - 'FINALFUNC', 'INITCOND' ], - 'CAST' : [ [ 'WITH', 'FUNCTION' ], - [ 'AS', 'ASSIGNMENT' ], - [ 'AS', 'IMPLICIT' ], - [ 'WITHOUT', 'FUNCTION'] - ], - 'CONSTRAINT' : [ 'TRIGGER', 'AFTER', 'ON', - [ 'FOR', 'EACH', 'ROW', 'EXECUTE' - 'PROCEDURE' ] - ], - 'CONVERSION' : [ 'FOR', 'TO', 'FROM' ], - 'DEFAULT' : [ 'CONVERSION', 'FOR', - 'TO', 'FROM' ], - 'DATABASE' : [ 'WITH', 'OWNER', 'TEMPLATE', - 'ENCODING', 'TABLESPACE', - 'DEFAULT' ], - 'DOMAIN' : [ 'AS', 'DEFAULT', 'CONSTRAINT', - 'CHECK' - ], - 'OR' : [ 'REPLACE', 'FUNCTION', - 'RETURNS', 'LANGUAGE', 'AS', - 'IMMUTABLE', 'STABLE', - 'VOLATILE', [ 'CALLED', 'ON', - 'NULL', 'INPUT' ], [ 'RETURNS', - 'NULL', 'ON', 'NULL', 'INPUT' ], - 'STRICT', 'EXTERNAL', - [ 'SECURITY', 'INVOKER' ], - [ 'SECURITY', 'DEFINER' ], 'WITH', - # XXX: for RULE - 'RULE', - 'AS', 'ON', 'TO', 'WHERE', - 'DO', 'ALSO', 'INSTEAD', - 'NOTHING', - 'VIEW' - ], - 'FUNCTION' : [ 'RETURNS', 'LANGUAGE', 'AS', - 'IMMUTABLE', 'STABLE', - 'VOLATILE', [ 'CALLED', 'ON', - 'NULL', 'INPUT' ], [ 'RETURNS', - 'NULL', 'ON', 'NULL', 'INPUT' ], - 'STRICT', 'EXTERNAL', - [ 'SECURITY', 'INVOKER' ], - [ 'SECURITY', 'DEFINER' ], 'WITH' - ], - 'GROUP' : [ 'WITH', 'SYSID', 'USER' ], - 'UNIQUE' : [ 'ON', 'USING', 'TABLESPACE', - 'WHERE', 'INDEX' ], - 'INDEX' : [ 'ON', 'USING', 'TABLESPACE', - 'WHERE', 'RTREE', 'HASH' ], - 'LANGUAGE' : [ 'HANDLER', 'VALIDATOR' ], - 'PROCEDURAL' : [ 'HANDLER', 'VALIDATOR', - 'LANGUAGE' ], - 'TRUSTED' : [ 'HANDLER', 'VALIDATOR', - 'LANGUAGE' ], - 'OPERATOR' : [ 'PROCEDURE', 'LEFTARG', - 'RIGHTARG', 'COMMUTATOR', - 'NEGATOR', 'RESTRICT', - 'JOIN', 'HASHES', 'MERGES', - 'SORT1', 'SORT2', 'LTCMP', - 'GTCMP', - 'CLASS', 'DEFAULT', - [ 'FOR', 'TYPE' ], 'USING', - 'AS', 'OPERATOR', 'RECHECK', - 'FUNCTION', 'STORAGE' ], - 'RULE' : [ 'AS', 'ON', 'TO', 'WHERE', - 'DO', 'ALSO', 'INSTEAD', - 'NOTHING' ], - 'SCHEMA' : [ 'AUTHORIZATION' ], - 'SEQUENCE' : [ 'INCREMENT', 'BY', 'MINVALUE', - 'NO', 'MAXVALUE', [ 'START', - 'WITH' ], 'CACHE', 'CYCLE' ], - 'TEMPORARY' : [ 'SEQUENCE', - 'INCREMENT', 'BY', 'MINVALUE', - 'NO', 'MAXVALUE', [ 'START', - 'WITH' ], 'CACHE', 'CYCLE', - # CREATE TABLE - 'TABLE', - 'DEFAULT', 'INCLUDING', - 'EXCLUDING', 'DEFAULTS', - 'INHERITS', 'WITH', - 'WITHOUT', 'OIDS', - [ 'ON', 'COMMIT' ], - [ 'PRESERVE', 'ROWS' ], - [ 'DELETE', 'ROWS' ], 'DROP', - 'TABLESPACE', 'CONSTRAINT', - 'UNIQUE', - [ 'USING', 'INDEX', 'TABLESPACE'], - [ 'PRIMARY', 'KEY' ], 'CHECK', - 'REFERENCES', [ 'MATCH', 'FULL' ], - [ 'MATCH', 'PARTIAL' ], - [ 'MATCH', 'SIMPLE' ], - [ 'ON', 'DELETE' ], - [ 'ON', 'UPDATE' ], 'DEFERRABLE', - [ 'INITIALLY', 'DEFERRED' ], - [ 'INITIALLY', 'IMMEDIATE' ], - [ 'FOREIGN', 'KEY' ], - 'CHECK', - ], - 'TEMP' : [ 'SEQUENCE', - 'INCREMENT', 'BY', 'MINVALUE', - 'NO', 'MAXVALUE', [ 'START', - 'WITH' ], 'CACHE', 'CYCLE', - # CREATE TABLE - 'TABLE', - 'DEFAULT', 'INCLUDING', - 'EXCLUDING', 'DEFAULTS', - 'INHERITS', 'WITH', 'OIDS', - 'WITHOUT', - [ 'ON', 'COMMIT' ], - [ 'PRESERVE', 'ROWS' ], - [ 'DELETE', 'ROWS' ], 'DROP', - 'TABLESPACE', 'CONSTRAINT', - 'UNIQUE', - [ 'USING', 'INDEX', 'TABLESPACE'], - [ 'PRIMARY', 'KEY' ], 'CHECK', - 'REFERENCES', [ 'MATCH', 'FULL' ], - [ 'MATCH', 'PARTIAL' ], - [ 'MATCH', 'SIMPLE' ], - [ 'ON', 'DELETE' ], - [ 'ON', 'UPDATE' ], 'DEFERRABLE', - [ 'INITIALLY', 'DEFERRED' ], - [ 'INITIALLY', 'IMMEDIATE' ], - [ 'FOREIGN', 'KEY' ], - 'CHECK', - ], - 'LOCAL' : [ 'TABLE', - 'DEFAULT', 'INCLUDING', - 'EXCLUDING', 'DEFAULTS', - 'INHERITS', 'WITH', - 'WITHOUT', 'OIDS', - [ 'ON', 'COMMIT' ], - [ 'PRESERVE', 'ROWS' ], - [ 'DELETE', 'ROWS' ], 'DROP', - 'TABLESPACE', 'CONSTRAINT', - 'UNIQUE', - [ 'USING', 'INDEX', 'TABLESPACE'], - [ 'PRIMARY', 'KEY' ], 'CHECK', - 'REFERENCES', [ 'MATCH', 'FULL' ], - [ 'MATCH', 'PARTIAL' ], - [ 'MATCH', 'SIMPLE' ], - [ 'ON', 'DELETE' ], - [ 'ON', 'UPDATE' ], 'DEFERRABLE', - [ 'INITIALLY', 'DEFERRED' ], - [ 'INITIALLY', 'IMMEDIATE' ], - [ 'FOREIGN', 'KEY' ], - 'CHECK', - ], - 'GLOBAL' : [ 'TABLE', - 'DEFAULT', 'INCLUDING', - 'EXCLUDING', 'DEFAULTS', - 'INHERITS', 'WITH', 'OIDS', - 'WITHOUT', - [ 'ON', 'COMMIT' ], - [ 'PRESERVE', 'ROWS' ], - [ 'DELETE', 'ROWS' ], 'DROP', - 'TABLESPACE', 'CONSTRAINT', - 'UNIQUE', - [ 'USING', 'INDEX', 'TABLESPACE'], - [ 'PRIMARY', 'KEY' ], 'CHECK', - 'REFERENCES', [ 'MATCH', 'FULL' ], - [ 'MATCH', 'PARTIAL' ], - [ 'MATCH', 'SIMPLE' ], - [ 'ON', 'DELETE' ], - [ 'ON', 'UPDATE' ], 'DEFERRABLE', - [ 'INITIALLY', 'DEFERRED' ], - [ 'INITIALLY', 'IMMEDIATE' ], - [ 'FOREIGN', 'KEY' ], - 'CHECK', - ], - 'TABLE' : [ 'DEFAULT', 'INCLUDING', - 'EXCLUDING', 'DEFAULTS', - 'INHERITS', 'WITH', 'OIDS', - 'WITHOUT', - [ 'ON', 'COMMIT' ], - [ 'PRESERVE', 'ROWS' ], - [ 'DELETE', 'ROWS' ], 'DROP', - 'TABLESPACE', 'CONSTRAINT', - 'UNIQUE', - [ 'USING', 'INDEX', 'TABLESPACE'], - [ 'PRIMARY', 'KEY' ], 'CHECK', - 'REFERENCES', [ 'MATCH', 'FULL' ], - [ 'MATCH', 'PARTIAL' ], - [ 'MATCH', 'SIMPLE' ], - [ 'ON', 'DELETE' ], - [ 'ON', 'UPDATE' ], 'DEFERRABLE', - 'INITIALLY', 'DEFERRED', - 'IMMEDIATE', 'RESTRICT', - [ 'FOREIGN', 'KEY' ], 'CASCADE' - 'CHECK', - ], - 'TABLESPACE' : [ 'OWNER', 'LOCATION' ], - 'TRIGGER' : [ 'BEFORE', 'AFTER', 'OR', 'ON', - 'FOR', 'EACH', 'ROW', 'STATEMENT', - [ 'EXECUTE', 'PROCEDURE' ] - ], - 'TYPE' : [ 'AS', 'INPUT', 'OUTPUT', - 'RECEIVE', 'SEND', 'ANALYZE', - 'INTERNALLENGTH', 'VARIABLE', - 'PASSEDBYVALUE', 'ALIGNMENT', - 'STORAGE', 'DEFAULT', - 'ELEMENT', 'DELIMITER' ], - 'USER' : [ 'WITH', 'SYSID', 'CREATEDB', - 'NOCREATEDB', 'CREATEUSER', - 'NOCREATEUSER', [ 'IN', 'GROUP' ], - 'ENCRYPTED', 'UNENCRYPTED', - 'PASSWORD', [ 'VALID', 'UNTIL' ] - ], - 'VIEW' : [ 'AS' , - # select - 'SELECT', 'DISTINCT', 'ON', - 'AS', 'FROM', 'WHERE', - [ 'GROUP', 'BY' ], 'HAVING', - 'UNION', 'INTERSECT', 'EXCEPT', - [ 'ORDER', 'BY' ], 'ASC', - 'DESC', 'USING', 'LIMIT', - 'OFFSET', [ 'FOR', 'UPDATE', - 'OF' ], 'ONLY', 'NATURAL', - 'USING', 'INNER', 'LEFT', 'OUTER', - 'RIGHT', 'FULL', 'JOIN', 'CROSS', - 'INTO' ], - }, - 'DEALLOCATE': [ 'PREPARE' ], - 'DECLARE' : [ 'BINARY', 'INSENSITIVE', 'NO', 'SCROLL', - 'CURSOR', 'WITH', 'WITHOUT', 'HOLD', 'FOR', - [ 'READ', 'ONLY' ], 'UPDATE', 'OF' ], - 'DELETE' : { 'FROM' : [ 'ONLY', 'WHERE' ] }, - 'DROP' : { 'AGGREGATE' : [ 'CASCADE', 'RESTRICT' ], - 'CAST' : [ 'AS', 'CASCADE', 'RESTRICT' ], - 'CONVERSION' : [ 'CASCADE', 'RESTRICT' ], - 'DATABASE' : [], - 'DOMAIN' : [ 'CASCADE', 'RESTRICT' ], - 'FUNCTION' : [ 'CASCADE', 'RESTRICT' ], - 'GROUP' : [], - 'INDEX' : [ 'CASCADE', 'RESTRICT' ], - 'LANGUAGE' : [ 'CASCADE', 'RESTRICT' ], - 'PROCEDURAL' : ['LANGUAGE', 'CASCADE', 'RESTRICT'], - 'OPERATOR' : [ 'NONE', 'CASCADE', 'RESTRICT', - 'CLASS', 'USING' ], - 'RULE' : [ 'ON', 'CASCADE', 'RESTRICT' ], - 'SCHEMA' : [ 'CASCADE', 'RESTRICT' ], - 'SEQUENCE' : [ 'CASCADE', 'RESTRICT' ], - 'TABLE' : [ 'CASCADE', 'RESTRICT' ], - 'TABLESPACE' : [], - 'TRIGGER' : [ 'ON', 'CASCADE', 'RESTRICT' ], - 'TYPE' : [ 'CASCADE', 'RESTRICT' ], - 'USER' : [], - 'VIEW' : [ 'CASCADE', 'RESTRICT' ], - }, - 'END' : [ 'WORK', 'TRANSACTION' ], - 'EXECUTE' : [], - 'EXPLAIN' : [ 'ANALYZE', 'VERBOSE' ], - 'FETCH' : [ 'FROM', 'IN', 'NEXT', 'PRIOR', 'FIRST', 'LAST', - 'ABSOLUTE', 'RELATIVE', 'FORWARD', - 'BACKWARD' ], - 'GRANT' : [ 'SELECT', 'INSERT', 'UPDATE', 'DELETE', 'RULE', - 'REFERENCES', 'TRIGGER', 'PRIVILEGES', - 'ON', 'TABLE', 'TO', 'GROUP', 'PUBLIC', - [ 'WITH', 'GRANT', 'OPTION' ], - 'CREATE', 'TEMPORARY', 'TEMP', 'PRIVILEGES', - 'DATABASE', 'EXECUTE', 'FUNCTION', 'USAGE', - 'LANGUAGE', 'SCHEMA', 'TABLESPACE' ], - 'INSERT' : { 'INTO' : [ 'DEFAULT', 'VALUES', - 'SELECT', 'DISTINCT', 'ON', 'AS', - 'FROM', 'WHERE', [ 'GROUP', 'BY' ], - 'HAVING', 'UNION', 'INTERSECT', 'EXCEPT', - [ 'ORDER', 'BY' ], - 'ASC', 'DESC', 'USING', 'LIMIT', - 'OFFSET', [ 'FOR', 'UPDATE', 'OF' ], - 'ONLY', 'NATURAL', 'USING', 'INNER', - 'LEFT', 'OUTER', 'RIGHT', 'FULL', - 'JOIN', 'CROSS', 'INTO', - ] - }, - 'LISTEN' : [], - 'LOAD' : [], - 'LOCK' : [ 'TABLE', 'IN', 'MODE', 'NOWAIT', - [ 'ACCESS', 'SHARE' ], [ 'ROW', 'SHARE' ], - [ 'ROW', 'EXCLUSIVE' ], - [ 'SHARE', 'UPDATE', 'EXCLUSIVE' ], - 'SHARE', [ 'SHARE', 'ROW', 'EXCLUSIVE' ], - 'EXCLUSIVE', [ 'ACCESS', 'EXCLUSIVE' ] ], - 'MOVE' : [ 'FROM', 'IN' ], - 'NOTIFY' : [], - 'PREPARE' : [ 'AS' ], - 'REINDEX' : [ 'DATABASE', 'TABLE', 'TABLE', 'FORCE' ], - 'RELEASE' : [ 'SAVEPOINT' ], - 'RESET' : [ ], - 'REVOKE' : [ [ 'GRANT', 'OPTION', 'FOR' ], 'SELECT', 'INSERT', - 'UPDATE', 'DELETE', 'RULE', 'REFERENCES', - 'TRIGGER', 'PRIVILEGES', 'ON', 'TABLE', - 'FROM', 'GROUP', 'PUBLIC', 'CASCADE', 'RESTRICT', - 'CREATE', 'TEMPORARY', 'TEMP', 'EXECUTE', - 'USAGE', 'SCHEMA', 'LANGUAGE', 'TABLESPACE' ], - 'ROLLBACK' : [ 'WORK', 'TRANSACTION', 'TO', 'SAVEPOINT' ], - 'SAVEPOINT': [], - - 'SELECT' : [ 'SELECT', 'INTO', 'DISTINCT', 'ON', 'AS', 'FROM', - 'WHERE', [ 'GROUP', 'BY' ], 'HAVING', 'UNION', - 'INTERSECT', 'EXCEPT', [ 'ORDER', 'BY' ], - 'ASC', 'DESC', 'USING', 'LIMIT', 'OFFSET', - [ 'FOR', 'UPDATE', 'OF' ], 'ONLY', 'NATURAL', - 'USING', 'INNER', 'LEFT', 'OUTER', 'RIGHT', 'FULL', - 'JOIN', 'CROSS', 'INTO' ], - 'SET' : [ 'SESSION', 'LOCAL', 'TO', 'DEFAULT', 'LOCAL', - [ 'TIME', 'ZONE' ], 'CONSTRAINTS', - 'DEFERRED', 'IMMEDIATE', 'AUTHORIZATION', - 'TRANSACTION', 'CHARACTERISTICS', - [ 'ISOLATION', 'LEVEL' ], 'SERIALIZABLE', - [ 'REPEATABLE', 'READ' ], [ 'READ', 'COMMITTED' ], - [ 'READ', 'UNCOMMITTED' ], [ 'READ', 'WRITE' ], - [ 'READ', 'ONLY' ] - ], - 'SHOW' : [ ], - 'START' : { 'TRANSACTION' : [ [ 'ISOLATION', 'LEVEL' ], - 'SERIALIZABLE', - [ 'REPEATABLE', 'READ' ], - [ 'READ', 'COMMITTED' ], - [ 'READ', 'UNCOMMITTED' ], - [ 'READ', 'WRITE' ], - [ 'READ', 'ONLY' ] - ], - }, - 'TRUNCATE' : [ 'TABLE' ], - 'UNLISTEN' : [], - 'UPDATE' : [ 'ONLY', 'SET', 'DEFAULT', 'FROM', 'WHERE' ], - 'VACUUM' : [ 'FULL', 'FREEZE', 'VERBOSE', 'ANALYSE' ] - } - - -class Syntax: - """Syntax highlight""" - - def __init__(self, buffer): - self.lexical = pgw.Lexical.Lexical() - self.buffer = buffer - self.last = None - # default colors - self.tag = {} - self.tag['font'] = self.buffer.create_tag("font") - if (pgw.mswindows()): - self.tag['font'].set_property('font', 'Courier New 10') - else: - self.tag['font'].set_property('family', 'monospace') - self.tag['function'] = self.buffer.create_tag("function") - self.tag['function'].set_property('foreground', '#009999') - self.tag['dollarquote'] = self.buffer.create_tag("dollarquote") - self.tag['dollarquote'].set_property('foreground', '#000000') - self.tag['identifier'] = self.buffer.create_tag("identifier") - self.tag['identifier'].set_property('foreground', '#000000') - self.tag['keyword'] = self.buffer.create_tag("keyword") - self.tag['keyword'].set_property('foreground', '#0000FF') - self.tag['type'] = self.buffer.create_tag("type") - self.tag['type'].set_property('foreground', '#009900') - self.tag['string'] = self.buffer.create_tag("string") - self.tag['string'].set_property('foreground', '#F700BF') - self.tag['numeric_constant'] = self.buffer.create_tag("numeric_constant") - self.tag['numeric_constant'].set_property('foreground', '#c53838') - self.tag['special'] = self.buffer.create_tag("special") - self.tag['special'].set_property('foreground', '#c53838') - self.tag['comment'] = self.buffer.create_tag("comment") - self.tag['comment'].set_property('foreground', '#999999') - self.tag['comment2'] = self.buffer.create_tag("comment2") - self.tag['comment2'].set_property('style', pango.STYLE_ITALIC) - self.tag['operator'] = self.buffer.create_tag("operator") - self.tag['operator'].set_property('foreground', '#555555') - self.tag['psql'] = self.buffer.create_tag("psql") - self.tag['psql'].set_property('background', '#d0d4df') - - - def start_of_prev_statement(self, iter): - """Find the first character of a statement""" - if (self.last is not None): - self.found = None - for token in self.last: - if (token.start_iter.compare(iter) >= 0): - if (self.found is None): - break - return self.found.start_iter - if (token.value == ';'): - self.found = token - if (self.found): - return self.found.start_iter - return iter.get_buffer().get_start_iter() - - - def start_of_next_statement(self, iter): - """Find the last character of a statement""" - if (self.last is not None): - self.found = None - for token in reversed(self.last): - if (token.end_iter.compare(iter) <= 0): - if (self.found is None): - break - return self.found.end_iter - if (token.value == ';'): - self.found = token - if (self.found): - return self.found.end_iter - return iter.get_buffer().get_end_iter() - - - def text_inserted(self, buffer, iter, text, length): - """Called by Gtk when text is inserted in the buffer: - prepare 'start' and 'end' for text_changed()""" - self.start = self.start_of_prev_statement(iter.copy()).get_offset() - self.end = self.start_of_next_statement(iter.copy()).get_offset() + length - - - def text_deleted(self, buffer, start, end): - """Called by Gtk when text is deleted from the buffer: - prepare 'start' and 'end' for text_changed()""" - self.start = self.start_of_prev_statement(start.copy()).get_offset() - self.end = self.start_of_next_statement(end.copy()).get_offset() - - - def text_changed(self, buffer): - """Called by Gtk when (after) text is deleted or inserted - in the buffer. Uses 'start' and 'end' prepared in text_inserted - and text_deleted then run the analyse""" - start = self.buffer.get_iter_at_offset(self.start) - end = self.buffer.get_iter_at_offset(self.end) - self.analyse(start, end) - - - def refresh(self): - """Used when you want to manually refresh the syntax highlight - of the whole buffer""" - start = self.buffer.get_start_iter() - end = self.buffer.get_end_iter() - self.analyse(start, end) - - - def analyse(self, start, end): - """Run the lexical and syntaxical analysers then - apply the syntax highlight to the buffer""" - self.tokens = self.lexical.analyse(self.buffer, start, end) - self.syntaxical_analyser() - self.buffer.remove_all_tags(start, end) - self.buffer.apply_tag(self.tag['font'], start, end) - self.last = self.tokens - for token in self.tokens: - self.buffer.apply_tag(self.tag[token.token], \ - token.start_iter, \ - token.end_iter) - if (token.token == 'comment'): - self.buffer.apply_tag(self.tag['comment2'], \ - token.start_iter, \ - token.end_iter) - - - def syntaxical_analyser(self): - """Find keywords""" - tokens = self.tokens - self.tokens = [] - try: - while (len(tokens) > 0): - token = tokens.pop(0) - # only statements, other tokens - # are analysed below or already founds in - # the lexical analyser - if (token.value in STATEMENTS): - token.token = 'keyword' - self.tokens.append(token) - statement = token.value - token = tokens.pop(0) - # get the list containing the - # keywords for this statement - try: - keywords = KEYWORDS[statement] - except KeyError: - continue - if (type(keywords) is dict): - try: - keywords = keywords[token.value] - token.token = 'keyword' - self.tokens.append(token) - token = tokens.pop(0) - except KeyError: - pass - self.tokens.append(token) - # identify each token inside the statement - while (token.value != ';'): - # only identifiers, other tokens are - # analysed in the lexical analyser - if (token.token == 'identifier'): - # special constants - if (token.value in SPECIALS): - token.token = 'special' - # buit-in data types - elif (token.value in TYPES): - # TODO : manage composed types names - token.token = 'type' - # names operators - elif (token.value in OPERATORS2): - token.token = 'operator' - # built-in functions - elif (token.value in BUILTINS): - next = tokens.pop(0) - if (next.value == '('): - token.token = 'function' - self.tokens.append(next) - else: - tokens.insert(0, next) - # built-in function that can be used without () - if (token.value in BUILTINS2): - token.token = 'function' - # everything else : keywords or indentifiers - else: - for keyword in keywords: - if (type(keyword) is list): - # TODO : write the right code here - # to manage composed keywords - if (token.value in keyword): - token.token = 'keyword' - elif (token.value == keyword): - token.token = 'keyword' - self.tokens.append(token) - token = tokens.pop(0) - self.tokens.append(token) - except IndexError: - pass diff --git a/pgworksheet_1.9/pgw/UI.py b/pgworksheet_1.9/pgw/UI.py deleted file mode 100644 index 6b7b596..0000000 --- a/pgworksheet_1.9/pgw/UI.py +++ /dev/null @@ -1,980 +0,0 @@ -# -*- coding: latin-1; -*- -# -# PgWorksheet - PostgreSQL Front End -# http://pgworksheet.projects.postgresql.org/ -# -# Copyright © 2004-2008 Henri Michelon & CML http://www.e-cml.org/ -# -# 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 (read LICENSE.txt). -# -# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# $Id: UI.py,v 1.26 2008/03/12 20:26:23 hmichelon Exp $ -# -import os -import ConfigParser -import pygtk -import gtk - -import pgw -import pgw.Syntax -import pgw.Undo - -PGW_CONNECT = 'pgw-connect' -PGW_CONNECTNOW = 'pgw-connectnow' -PGW_DISCONNECT = 'pwg-disconnect' -PGW_SELECTALL = 'pwg-selectall' -PGW_ENCODING = 'pwg-encoding' -PGW_ABOUT = 'pwg-about' - - -class UI: - """UI Construction and management""" - - def __init__(self, app, app_name, app_version, pixmap_path): - self.pixmap_path = pixmap_path - self.app_version = app_version - self.register_stock_items() - self.file_dialog_path = None # last used path - self.file_dialog_filename = None # last used filename - self.define_ui(app) - - self.wndmain = gtk.Window(gtk.WINDOW_TOPLEVEL) - self.wndmain.set_title(_('PgWorksheet - PostgreSQL SQL Tool')) - self.wndmain.set_icon_from_file(os.path.join(pixmap_path, - "pgworksheet-32.png")) - self.wndmain.add_accel_group(self.accelgroup) - self.wndmain.set_default_size(640, 480) - self.wndmain.connect('window-state-event', self.on_wndmain_state) - self.wndmain.connect('configure-event', self.on_wndmain_configure) - self.wndmain.connect('destroy', app.on_wndmain_destroy) - self.wndmain.connect('delete_event', app.on_wndmain_delete) - - hbox = gtk.VBox(False) - hbox.pack_start(self.uimanager.get_widget('/MenuBar'), False) - hbox.pack_start(self.uimanager.get_widget('/ToolBar'), False) - hbox.pack_start(self.vmain, True, True) - hbox.pack_start(self.statusbar, False, False) - self.wndmain.add(hbox) - - self.load_user_parameters() - self.wndmain.show_all() - - - def load_user_parameters(self): - cp = ConfigParser.ConfigParser() - try: - cp.readfp(open(pgw.get_config_path(), 'r')) - maximized = 0 - try: - maximized = int(cp.get("window", "maximized")) - except: - pass - if (maximized): - self.wndmain.maximize() - else: - width, height = self.wndmain.get_size() - try: - width = int(cp.get("window", "width")) - except: - pass - try: - height = int(cp.get("window", "height")) - except: - pass - self.wndmain.resize(width, height) - x, y = self.wndmain.get_position() - try: - x = int(cp.get("window", "x")) - except: - pass - try: - y = int(cp.get("window", "y")) - except: - pass - self.wndmain.move(x, y) - try: - self.vmain.set_position(int(cp.get("window", "divider"))) - except: - pass - except IOError: - pass - return cp - - - def message_dialog(self, msg, type, buttons = gtk.BUTTONS_OK): - dialog = gtk.MessageDialog(self.wndmain, - gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, - type, buttons, msg) - result = dialog.run() - dialog.destroy() - return result - - - def message_box(self, msg): - self.message_dialog(msg, gtk.MESSAGE_INFO) - - - def error_box(self, msg): - self.message_dialog(msg, gtk.MESSAGE_ERROR) - - - def yesno_box(self, msg): - return self.message_dialog(msg, gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO) - - - def file_dialog(self, msg, - action = gtk.FILE_CHOOSER_ACTION_OPEN, - button = gtk.STOCK_OPEN): - fb = gtk.FileChooserDialog(msg, self.wndmain, - action, - (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, - button, gtk.RESPONSE_OK)) - if (self.file_dialog_path is not None): - fb.set_current_folder_uri(self.file_dialog_path) - if (self.file_dialog_filename is not None): - fb.set_filename(self.file_dialog_filename) - fb.show_all() - result = fb.run() - if (result == gtk.RESPONSE_OK): - filename = fb.get_filename() - else: - filename = None - self.file_dialog_path = fb.get_current_folder_uri() - self.file_dialog_filename = fb.get_filename() - fb.destroy() - return filename - - - def register_stock_items(self): - gtk.stock_add([ - (PGW_CONNECT, _('_Connect Server...'), gtk.gdk.CONTROL_MASK, - gtk.gdk.keyval_from_name('N'), None), - (PGW_DISCONNECT, _('_Disconnect'), 0, -1, None), - (PGW_SELECTALL, _('Select _All'), gtk.gdk.CONTROL_MASK, - gtk.gdk.keyval_from_name('A'), None), - (PGW_ENCODING, _('Character _Encoding'), 0, -1, None), - (PGW_ABOUT, _('_About...'), 0, -1, None), - (PGW_CONNECTNOW, _('_Connect'), 0, -1, None), - ]) - self.factory = gtk.IconFactory() - self.factory.add_default() - self.factory.add(PGW_CONNECTNOW, gtk.IconSet(gtk.gdk.pixbuf_new_from_file( - os.path.join(self.pixmap_path, "connect.png")))) - self.factory.add(PGW_CONNECT, gtk.IconSet(gtk.gdk.pixbuf_new_from_file( - os.path.join(self.pixmap_path, "connect.png")))) - self.factory.add(PGW_DISCONNECT, gtk.IconSet(gtk.gdk.pixbuf_new_from_file( - os.path.join(self.pixmap_path, "disconnect.png")))) - self.factory.add(PGW_ABOUT, gtk.IconSet(gtk.gdk.pixbuf_new_from_file( - os.path.join(self.pixmap_path, "about.png")))) - - - def define_ui(self, app): - self.ui = ''' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ''' - - self.undo = pgw.Undo.Undo() - self.uimanager = gtk.UIManager() - self.accelgroup = self.uimanager.get_accel_group() - self.actiongroup = gtk.ActionGroup('UIManagerMenuBar') - self.actiongroup.add_actions([ - ('File', None, _('_File')), - ('Connect', PGW_CONNECT, None, None, - _('Connect to a database'), app.on_menu_connect), - ('Disconnect', PGW_DISCONNECT, None, '', - _('Disconnect from the database'), app.on_menu_disconnect), - ('Open SQL', gtk.STOCK_OPEN, _('_Open SQL queries...'), None, - _('Load SQL queries from a file'), app.on_menu_opensql), - ('Save SQL', gtk.STOCK_SAVE, _('_Save SQL queries...'), None, - _('Save SQL queries to a file'), app.on_menu_savesql), - ('Save Results', gtk.STOCK_SAVE, _('Save _Results...'), 'R', - _('Save the results to a file'), app.on_menu_saveresults), - ('Save All Results', gtk.STOCK_SAVE, _('Save _All Results...'), - 'R', - _('Save all the results to a file'), app.on_menu_saveallresults), - ('Quit', gtk.STOCK_QUIT, None, None, - _('Quit the Program'), app.on_wndmain_destroy), - ('Edit', None, _('_Edit')), - ('Undo', gtk.STOCK_UNDO, None, 'Z', - _('Undo the last action'), lambda w: self.undo.undo()), - ('Redo', gtk.STOCK_REDO, None, 'Z', - _('Redo the last action'), lambda w: self.undo.redo()), - ('Cut', gtk.STOCK_CUT, None, None, - _('Cut selection to the clipboard'), app.on_menu_cut), - ('Copy', gtk.STOCK_COPY, None, None, - _('Copy selection to the clipboard'), app.on_menu_copy), - ('Paste', gtk.STOCK_PASTE, None, None, - _('Paste the content of the clipboard'), app.on_menu_paste), - ('Select All', PGW_SELECTALL, None, None, - _('Select all the text'), app.on_menu_selectall), - ('View', None, _('_View')), - ('Encoding', PGW_ENCODING, None, None, _('Select the character \ - encoding for display'), app.on_menu_selectall), - ('Tools', None, _('_Tools')), - ('Run SQL', gtk.STOCK_EXECUTE, None, "Return", - _('Execute the content of the SQL buffer'), app.on_menu_runsql), - ('History', None, _('_History')), - ('Prev Statement', gtk.STOCK_GO_BACK, _('_Previous statements'), - "Page_Down", - _('Go backward in the executed statements history'), - app.on_menu_prevsql), - ('Next Statement', gtk.STOCK_GO_FORWARD, _('_Next statements'), - "Page_Up", - _('Go forward in the executed statements history'), - app.on_menu_nextsql), - ('Help', None, _('_Help')), - ('About', PGW_ABOUT, None, '', - _('More information about this application'), app.on_menu_about), - ('Run SQL 2', gtk.STOCK_EXECUTE, None, "F9", None, app.on_menu_runsql), - ('Run SQL 3', gtk.STOCK_EXECUTE, None, "F5", None, app.on_menu_runsql), - ]) - self.uimanager.insert_action_group(self.actiongroup, 0) - self.uimanager.add_ui_from_string(self.ui) - self.uimanager.get_widget('/MenuBar/Help').\ - set_right_justified(True) - self.enable_disconnect(False) - self.enable_runsql(False) - self.enable_prevsql(False) - self.enable_nextsql(False) - self.enable_saveresult(False) - self.create_vpaned(app) - self.create_statusbar() - self.uimanager.get_widget('/ToolBar').set_style(gtk.TOOLBAR_ICONS) - - - def create_vpaned(self, app): - self.vmain = gtk.VPaned() - self.vmain.connect("event", self.on_vpaned_accept) - scroll = gtk.ScrolledWindow() - scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - scroll.set_property("height-request", 150) - scroll.set_shadow_type(gtk.SHADOW_NONE) - self.sqlbuffer = gtk.TextBuffer() - self.sqlbuffer.connect('delete-range', self.undo.text_deleted) - self.sqlbuffer.connect('insert-text', self.undo.text_inserted) - self.syntax = pgw.Syntax.Syntax(self.sqlbuffer) - self.buffer_handlers = [] - self.buffer_handlers.append(self.sqlbuffer.connect('delete-range', - self.syntax.text_deleted)) - self.buffer_handlers.append(self.sqlbuffer.connect('insert-text', - self.syntax.text_inserted)) - self.buffer_handlers.append(self.sqlbuffer.connect('changed', - self.syntax.text_changed)) - self.buffer_handlers.append(self.sqlbuffer.connect('changed', - app.on_text_change)) - self.sqlview = gtk.TextView(self.sqlbuffer) - self.sqlview.connect('focus-in-event', app.on_sqlview_focus_in) - self.sqlview.connect('focus-out-event', app.on_sqlview_focus_out) - self.sqlview.connect('key-press-event', app.on_sqlview_keypress) - scroll.add(self.sqlview) - self.vmain.add1(scroll) - self.resulttab = gtk.Notebook() - self.resulttab.set_tab_pos(gtk.POS_BOTTOM) - self.resulttab.set_scrollable(True) - resultview = gtk.Viewport() - resultview.set_shadow_type(gtk.SHADOW_IN) - resultview.add(self.resulttab) - self.vmain.add2(resultview) - - - def create_statusbar(self): - self.statusbar = gtk.Statusbar() - self.statusbar.set_border_width(0) - - f = self.statusbar.get_children()[0] - f.set_shadow_type(gtk.SHADOW_IN) - self.status_result = f.get_children() - self.status_result = self.status_result[0] - self.statusbar.set_child_packing(f, True, True, 0, gtk.PACK_START) - - self.status_connect = gtk.Label(); - self.status_connect.set_justify(gtk.JUSTIFY_LEFT) - f = gtk.Frame() - f.set_shadow_type(gtk.SHADOW_IN) - f.add(self.status_connect) - self.statusbar.pack_start(f, False, False) - - self.status_version = gtk.Label(); - f = gtk.Frame() - f.set_shadow_type(gtk.SHADOW_IN) - f.add(self.status_version) - self.statusbar.pack_start(f, False, False) - - f = gtk.Label(' ') - self.statusbar.pack_start(f, False, False) - - - def status(self, connect, version): - """Update the status bar text""" - self.status_connect.set_markup(" " + connect + " ") - self.status_version.set_markup(" " + version + " ") - - - def setfocus_sqlbuffer(self): - self.sqlview.grab_focus() - - - def enable_disconnect(self, state = True): - self.uimanager.get_widget('/MenuBar/File/Disconnect').\ - set_sensitive(state) - - - def enable_saveresult(self, state = True): - self.uimanager.get_widget('/MenuBar/File/Save All Results').\ - set_sensitive(state) - self.uimanager.get_widget('/MenuBar/File/Save Results').\ - set_sensitive(state) - - - def enable_runsql(self, state = True): - self.uimanager.get_widget('/MenuBar/Tools/Run SQL').\ - set_sensitive(state) - self.uimanager.get_widget('/ToolBar/Run SQL').\ - set_sensitive(state) - - - def enable_cut(self, state = True): - self.uimanager.get_widget('/MenuBar/Edit/Cut').\ - set_sensitive(state) - self.uimanager.get_widget('/ToolBar/Cut').\ - set_sensitive(state) - - - def enable_copy(self, state = True): - self.uimanager.get_widget('/MenuBar/Edit/Copy').\ - set_sensitive(state) - self.uimanager.get_widget('/ToolBar/Copy').\ - set_sensitive(state) - - - def enable_selectall(self, state = True): - self.uimanager.get_widget('/MenuBar/Edit/Select All').\ - set_sensitive(state) - - - def enable_paste(self, state = True): - self.uimanager.get_widget('/MenuBar/Edit/Paste').\ - set_sensitive(state) - self.uimanager.get_widget('/ToolBar/Paste').\ - set_sensitive(state) - - - def enable_prevsql(self, state = True): - self.uimanager.get_widget('/MenuBar/History/Prev Statement').\ - set_sensitive(state) - self.uimanager.get_widget('/ToolBar/Prev Statement').\ - set_sensitive(state) - - - def enable_nextsql(self, state = True): - self.uimanager.get_widget('/MenuBar/History/Next Statement').\ - set_sensitive(state) - self.uimanager.get_widget('/ToolBar/Next Statement').\ - set_sensitive(state) - - - def get_text(self, buffer): - """Return the text of a widget""" - c1 = buffer.get_start_iter() - c2 = buffer.get_end_iter() - return buffer.get_slice(c1, c2, True) - - - def get_sqlbuffer_text(self): - return self.get_text(self.sqlbuffer) - - - def set_sqlbuffer_text(self, text): - self.sqlbuffer.set_text(text) - - - def on_connect_event(self, widget, event): - if ((not self.entry_password.is_focus()) and - self.viewconn.is_focus()): - self.entry_password.grab_focus() - - - def connect_dialog(self, app, host, port, user, database, overwrite_entry): - dlg = gtk.Dialog(_('Database connection'), - self.wndmain, - gtk.DIALOG_MODAL or gtk.DIALOG_DESTROY_WITH_PARENT, - ((gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, - PGW_CONNECTNOW, gtk.RESPONSE_OK))) - dlg.set_resizable(False) - - mbox = gtk.HBox() - box = gtk.Frame() - self.storeconn = gtk.ListStore(str, str) - self.viewconn = gtk.TreeView(self.storeconn) - cell = gtk.CellRendererText() - column = gtk.TreeViewColumn(_('5 Previous connections')) - column.pack_start(cell, True) - column.add_attribute(cell, 'text', 0) - column.set_sort_column_id(0) - self.viewconn.append_column(column) - self.viewconn.connect('cursor-changed', app.on_dlgconnect_change) - box.add(self.viewconn) - mbox.pack_start(box, True, True) - - hbox = gtk.HBox(False) - hbox.set_border_width(10) - hbox.set_spacing(10) - - box = gtk.VBox(True) - box.set_spacing(10) - lbl = gtk.Label(_('Host')) - lbl.set_alignment(0, 0.1) - box.pack_start(lbl, True, True) - lbl = gtk.Label(_('Port')) - lbl.set_alignment(0, 0.1) - box.pack_start(lbl, True, True) - lbl = gtk.Label(_('User')) - lbl.set_alignment(0, 0.1) - box.pack_start(lbl, True, True) - lbl = gtk.Label(_('Password')) - lbl.set_alignment(0, 0.1) - box.pack_start(lbl, True, True) - lbl = gtk.Label(_('Database')) - lbl.set_alignment(0, 0.1) - box.pack_start(lbl, True, True) - hbox.pack_start(box, False, False) - - box = gtk.VBox(False) - box.set_spacing(10) - self.entry_host = gtk.Entry() - self.entry_host.connect('activate', lambda w: dlg.response(gtk.RESPONSE_OK)) - box.pack_start(self.entry_host, True, True) - self.entry_port = gtk.Entry() - self.entry_port.connect('activate', lambda w: dlg.response(gtk.RESPONSE_OK)) - box.pack_start(self.entry_port, True, True) - self.entry_user = gtk.Entry() - self.entry_user.connect('activate', lambda w: dlg.response(gtk.RESPONSE_OK)) - box.pack_start(self.entry_user, True, True) - self.entry_password = gtk.Entry() - self.entry_password.set_visibility(False) - self.entry_password.connect('activate', lambda w: dlg.response(gtk.RESPONSE_OK)) - box.pack_start(self.entry_password, True, True) - self.entry_database = gtk.Entry() - self.entry_database.connect('activate', lambda w: dlg.response(gtk.RESPONSE_OK)) - box.pack_start(self.entry_database, True, True) - hbox.pack_start(box, True, True) - - mbox.pack_start(hbox, True, True) - - dlg.vbox.pack_start(mbox, True, True, 0) - app.on_dlgconnect_map(None) - if (overwrite_entry or (not self.storeconn.iter_n_children(None))): - self.entry_host.set_text(host) - self.entry_port.set_text(str(port)) - self.entry_user.set_text(user) - self.entry_database.set_text(database) - dlg.set_default_response(gtk.RESPONSE_OK) - dlg.connect('event-after', self.on_connect_event) - dlg.vbox.show_all() - self.entry_password.grab_focus() - result = None - if (dlg.run() == gtk.RESPONSE_OK): - result = (self.entry_host.get_text(), - self.entry_port.get_text(), - self.entry_user.get_text(), - self.entry_password.get_text(), - self.entry_database.get_text()) - dlg.destroy() - return result - - - def write_config(self, cp): - try: - cp.write(open(pgw.get_config_path(), 'w')) - except IOError: - pass - - - def on_vpaned_accept(self, widget, event): - cp = ConfigParser.ConfigParser() - try: - cp.readfp(open(pgw.get_config_path(), 'r')) - except IOError: - pass - if (not cp.has_section("window")): - cp.add_section("window") - cp.set("window", "divider", str(widget.get_position())) - self.write_config(cp) - - - def on_wndmain_state(self, widget, event): - cp = ConfigParser.ConfigParser() - try: - cp.readfp(open(pgw.get_config_path(), 'r')) - except IOError: - pass - if (not cp.has_section("window")): - cp.add_section("window") - if (event.new_window_state == gtk.gdk.WINDOW_STATE_MAXIMIZED): - cp.set("window", "maximized", "1") - else: - cp.set("window", "maximized", "0") - self.write_config(cp) - - - def on_wndmain_configure(self, widget, event): - cp = ConfigParser.ConfigParser() - try: - cp.readfp(open(pgw.get_config_path(), 'r')) - except IOError: - pass - if (not cp.has_section("window")): - cp.add_section("window") - x, y = widget.get_position() - cp.set("window", "x", x) - cp.set("window", "y", y) - width, height = widget.get_size() - cp.set("window", "width", width) - cp.set("window", "height", height) - self.write_config(cp) - - - def about_dialog(self): - dlg = gtk.Dialog(_('About PgWorksheet'), - self.wndmain, - gtk.DIALOG_MODAL or gtk.DIALOG_DESTROY_WITH_PARENT, - ((gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE))) - nbk = gtk.Notebook() - - box = gtk.VBox(False) - - lbl = gtk.Label() - lbl.set_markup(''' -PgWorksheet - PostgreSQL Front End -Version ''' + self.app_version + ''' -http://pgworksheet.projects.postgresql.org/ - -Copyright © 2004-2006, Henri Michelon and CML -http://www.e-cml.org/ - ''') - lbl.set_justify(gtk.JUSTIFY_CENTER) - lbl.set_padding(10, 10) - box.pack_start(lbl, True) - lbl = gtk.Label() - lbl.set_markup(''' -Internationalization: -French : Henri Michelon <hmichelon@e-cml.org> -Japanese : Tadashi Jokagi <elf2000@users.sourceforge.net> - ''') - lbl.set_padding(10, 0) - box.pack_start(lbl, True) - pix = gtk.Image() - pix.set_from_file(os.path.join(self.pixmap_path, "pgworksheet.png")) - pix.set_padding(10, 10) - box.pack_start(pix, False) - nbk.append_page(box, gtk.Label(_('About'))) - - txt = gtk.TextBuffer() - txt.set_text(''' - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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. - ''') - scroll = gtk.ScrolledWindow() - scroll.add(gtk.TextView(txt)) - nbk.append_page(scroll, gtk.Label(_('License'))) - - dlg.vbox.pack_start(nbk, True, True, 0) - nbk.show_all() - dlg.run() - dlg.destroy() diff --git a/pgworksheet_1.9/pgw/Undo.py b/pgworksheet_1.9/pgw/Undo.py deleted file mode 100644 index 6f29ed9..0000000 --- a/pgworksheet_1.9/pgw/Undo.py +++ /dev/null @@ -1,106 +0,0 @@ -# -*- coding: latin-1; -*- -# -# PgWorksheet - PostgreSQL Front End -# http://pgworksheet.projects.postgresql.org/ -# -# Copyright © 2004-2008 Henri Michelon & CML http://www.e-cml.org/ -# -# 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 (read LICENSE.txt). -# -# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# $Id: Undo.py,v 1.4 2008/03/12 20:26:23 hmichelon Exp $ -# - -# maxium size of the undo stack -UNDO_MAX = 1000 - - -class UndoAction: - """A user action : insert or delete""" - - def __init__(self, buffer, type, start, end, value): - self.buffer = buffer - self.type = type - self.start = start - self.end = end - self.value = value - - -class Undo: - """Records user actions and apply or revert them""" - - def __init__(self): - self.undo_stack = [] - self.redo_stack = [] - # locking is used to avoid recording - # our own undo/redo actions - self.lock = False - - - def reset(self): - """empty the stacks to restart the undo action""" - self.undo_stack = [] - self.redo_stack = [] - - - def text_inserted(self, buffer, iter, text, length): - """Called by Gtk when text is inserted in a buffer""" - if (not self.lock): - if (len(self.undo_stack) >= UNDO_MAX): - self.undo_stack.pop(0) - self.undo_stack.append(UndoAction(buffer, "insert", - iter.get_offset(), iter.get_offset() + length, - text)) - - - def text_deleted(self, buffer, start, end): - """Called by Gtk when text is deleted from a buffer""" - if (not self.lock): - if (len(self.undo_stack) >= UNDO_MAX): - self.undo_stack.pop(0) - self.undo_stack.append(UndoAction(buffer, "delete", - start.get_offset(), end.get_offset(), - buffer.get_text(start, end))) - - - def undo(self): - """Revert the last action""" - if (len(self.undo_stack) == 0): - return - self.lock = True - action = self.undo_stack.pop() - if (action.type == "insert"): - action.buffer.delete(action.buffer.get_iter_at_offset(action.start), - action.buffer.get_iter_at_offset(action.end)) - elif (action.type == "delete"): - action.buffer.insert(action.buffer.get_iter_at_offset(action.start), - action.value) - self.redo_stack.append(action) - self.lock = False - - - def redo(self): - """Apply the last reverted action""" - if (len(self.redo_stack) == 0): - return - self.lock = True - action = self.redo_stack.pop() - if (action.type == "insert"): - action.buffer.insert(action.buffer.get_iter_at_offset(action.start), - action.value) - elif (action.type == "delete"): - action.buffer.delete(action.buffer.get_iter_at_offset(action.start), - action.buffer.get_iter_at_offset(action.end)) - self.undo_stack.append(action) - self.lock = False diff --git a/pgworksheet_1.9/pgw/__init__.py b/pgworksheet_1.9/pgw/__init__.py deleted file mode 100644 index 2d6ffa0..0000000 --- a/pgworksheet_1.9/pgw/__init__.py +++ /dev/null @@ -1,86 +0,0 @@ -# -*- coding: latin-1; -*- -# -# PgWorksheet - PostgreSQL Front End -# http://pgworksheet.projects.postgresql.org/ -# -# Copyright © 2004-2008 Henri Michelon & CML http://www.e-cml.org/ -# -# 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 (read LICENSE.txt). -# -# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# $Id: __init__.py,v 1.10 2008/03/12 20:26:23 hmichelon Exp $ -# -import sys -import os -import string - - -def mswindows(): - """Return TRUE is we run under Microsoft Windows""" - return sys.platform == "win32" - - -def get_user_encoding(): - if (mswindows()): - return "ISO-8859-1" #"UTF-8" - try: - enc = os.environ['MM_CHARSET'] - return enc - except KeyError: - try: - enc = os.environ['LANG'] - except KeyError: - try: - enc = os.environ['LC_LANG'] - except KeyError: - try: - enc = os.environ['LC_ALL'] - except KeyError: - return "ISO8859-1" - parts = string.split(enc, '.') - if (len(parts) > 1) : - return parts[1] - return "ISO8859-1" - - -def set_proportional(buffer): - """Change the font of a widget to proportional""" - tagname = 'font-' + str(buffer) - try: - font = buffer.create_tag(tagname) - if (mswindows()): - font.set_property('font', 'Courier New 10') - else: - font.set_property('family', 'monospace') - buffer.apply_tag(font, buffer.get_start_iter(), buffer.get_end_iter()) - except TypeError: # tag already exists - buffer.apply_tag_by_name(tagname, buffer.get_start_iter(), buffer.get_end_iter()) - - -def get_user_configdir(): - """Return the directory where the configuration file is stored""" - if (mswindows()): - try: - return os.environ['USERPROFILE'] - except KeyError: - try: - return os.environ['ALLUSERSPROFILE'] - except KeyError: - return os.environ['SYSTEMROOT'] - else: - return os.environ['HOME'] - - -def get_config_path(): - return os.path.join(get_user_configdir(), '.pgworksheet') diff --git a/pgworksheet_1.9/pgworksheet b/pgworksheet_1.9/pgworksheet deleted file mode 100755 index 301e4e4..0000000 --- a/pgworksheet_1.9/pgworksheet +++ /dev/null @@ -1,606 +0,0 @@ -#!/usr/bin/env python -# -*- coding: latin-1; -*- -# -# PgWorksheet - PostgreSQL Front End -# http://pgworksheet.projects.postgresql.org/ -# -# Copyright © 2004-2008 Henri Michelon & CML http://www.e-cml.org/ -# -# 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 (read LICENSE.txt). -# -# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# $Id: pgworksheet,v 1.94 2008/03/13 11:05:32 hmichelon Exp $ -# -import os -import sys -# Application parameters -app_name = 'pgworksheet' -app_version = '1.9' -# Default pixmap path -pixmap_path = '@PIXMAP_PATH@' -# Find current pixmap path -if (not os.access(os.path.join(pixmap_path, 'pgworksheet-32.png'), os.F_OK)): - pixmap_path = os.path.join(sys.prefix, 'share/pixmaps/pgworksheet') -if (not os.access(os.path.join(pixmap_path, 'pgworksheet-32.png'), os.F_OK)): - pixmap_path = os.path.join(os.path.dirname(sys.argv[0]), 'pixmaps/pgworksheet') -# Find current locale path -locale_path = '@LOCALE_PATH@' -if (not os.access(os.path.join(locale_path, 'fr/LC_MESSAGES/pgworksheet.mo'), os.F_OK)): - locale_path = os.path.join(sys.prefix, 'share/locale') -if (not os.access(os.path.join(locale_path, 'fr/LC_MESSAGES/pgworksheet.mo'), os.F_OK)): - locale_path = os.path.join(os.path.dirname(sys.argv[0]), 'locale') - -import string -import gettext -import locale - -# Initialize I18N -if sys.platform == 'win32': - try: - # try to get the default language - lang = gettext.translation(app_name, locale_path, - [ locale.getdefaultlocale()[0] ]) - lang.install() - except IOError: - # fallback to the default method - gettext.bindtextdomain(app_name, locale_path) - gettext.textdomain(app_name) - gettext.install(app_name, locale_path, unicode=1) -else: - gettext.bindtextdomain(app_name, locale_path) - gettext.textdomain(app_name) - gettext.install(app_name, locale_path, unicode=1) - - -if sys.platform == 'win32': - # win32 platform, add the "lib" folder to the system path - os.environ['PATH'] = "gtk/bin;gtk/lib;" + os.environ['PATH'] - import pygtk - # search for the postgresql installation - import _winreg - reg = _winreg.ConnectRegistry(None, _winreg.HKEY_LOCAL_MACHINE) - try: - keyname = "SOFTWARE\PostgreSQL\Installations" - key = _winreg.OpenKey(reg, keyname) - keyname = keyname + "\\" + _winreg.EnumKey(key, 0); - _winreg.CloseKey(key) - key = _winreg.OpenKey(reg, keyname) - val, typ = _winreg.QueryValueEx(key, "Base Directory") - _winreg.CloseKey(key) - os.environ['PATH'] = val + "\\bin;" + os.environ['PATH'] - except WindowsError: - msg = _("Please install PostgreSQL.\n\nDownload it at http://www.postgresql.org/.\n\nNote : if you use PgWorksheet to connect to remote databases only, you don't need to install PostgreSQL as a service.") - print(msg) - import gtk - dialog = gtk.MessageDialog(None, - gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, - gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, msg) - result = dialog.run() - dialog.destroy() - sys.exit(0) -else: - import pygtk - # not win32, ensure version 2.0 of pygtk is imported - pygtk.require('2.0') - -import gtk -import ConfigParser - -import pgw -import pgw.UI -import pgw.RunSQL -import pgw.Execute -import pgw.DBConnection - -# maximum entries in the SQL queries history -PGW_MAX_HISTORY = 100 -# maximum entries in the connection parameters history -PGW_MAX_CONNECTION_HISTORY = 5 - - -class PgWorksheet: - - def __init__(self, app_name, app_version, pixmap_path): - # Build UI - self.ui = pgw.UI.UI(self, app_name, app_version, pixmap_path) - # Default connection state : not connected - self.db = None - self.disconnect() - # Initialize prev/next query lifos for history - self.prev_statements = [] - self.next_statements = [] - self.load_history() - self.prev_saved = 1 - # Display connection dialog on startup - self.on_menu_connect(None) - # Start application - gtk.main() - - - def add_prevstatement(self, sql): - """Add a query to the previous queries lifo""" - # do not add the same query two times - if (len(self.prev_statements) > 0): - prev = self.prev_statements[len(self.prev_statements)-1] - if (prev == sql): return - # add the query to the lifo - self.prev_statements.append(sql) - self.ui.enable_prevsql(len(self.prev_statements) > 0) - - - def get_history_path(self): - """Returns the path to the configuration file""" - return os.path.join(pgw.get_user_configdir(), '.pgworksheet_history'); - - - def save_history(self): - """Save the history in a text file""" - try: - fd = open(self.get_history_path(), 'w') - self.add_prevstatement(self.ui.get_sqlbuffer_text()) - for sql in self.prev_statements: - fd.write("\n#$#\n") - fd.write(string.rstrip(sql)) - for sql in self.next_statements: - fd.write("\n#$#\n") - fd.write(string.rstrip(sql)) - fd.write("\n#$#\n") - fd.close() - except IOError: - pass - - - def load_history(self): - """Load the history from a text file""" - try: - fd = open(self.get_history_path(), 'r') - sql = '' - count = 0 - for line in fd: - line = string.rstrip(line) - if (line == '') : - continue - try: - line = unicode(line, 'UTF-8') - except UnicodeDecodeError: - try: - line = unicode(line, pgw.get_user_encoding()) - except UnicodeDecodeError: - pass - if (line == '#$#'): - if (len(sql) > 0): - self.prev_statements.append(sql) - count = count + 1 - sql = '' - continue - sql += line - sql += '\n' - if (len(sql) > 0): - self.prev_statements.append(sql) - fd.close() - if (count > PGW_MAX_HISTORY): - self.prev_statements = self.prev_statements[count - PGW_MAX_HISTORY : count] - self.ui.enable_prevsql(len(self.prev_statements) > 0) - except IOError: - pass - - - def is_connected(self): - """Return TRUE if connected to a database""" - if (self.db is None): - return None - else: - return self.db.is_connected() - - - def connect(self, host = None, port = None, db = None, - user = None, password = None): - """Connect to a database""" - self.ui.wndmain.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH)) - self.ui.status(_('Trying to connect as %(user)s to %(db)s on %(host)s') % - {'user':user, 'db':db, 'host':host}, _('connecting...')) - while (gtk.events_pending() == True): - gtk.main_iteration_do(False) - # Disconnect then re-connect - self.disconnect() - self.db = pgw.DBConnection.DBConnection(host, port, db, user, password) - # we are connected - if (self.is_connected()): - # update the UI to reflect the connection state - self.ui.enable_disconnect() - self.ui.enable_runsql() - self.ui.status(_('connected as %(user)s to %(db)s on %(host)s') % - {'user':user, 'db':db, 'host':host}, self.db.pgversion()) - new_conn = "%s,%s,%s,%s" % (host, port, db, user) - # update the connection history - n = 0 - for conn in self.all_connections: - # remove the connection from the history if it already exists - if (conn == new_conn): - self.all_connections.pop(n) - break - n = n + 1 - # add the connection to the history, making it the first of the list - self.all_connections.insert(0, new_conn) - # save the connection history in the config file - cp = ConfigParser.ConfigParser() - try: - cp.readfp(open(pgw.get_config_path(), 'r')) - except IOError: - pass - if (not cp.has_section("connections")): - cp.add_section("connections") - n = 0 - while ((n <= PGW_MAX_CONNECTION_HISTORY) and - (n < len(self.all_connections))): - cp.set("connections", "conn%d" % (n + 1), self.all_connections[n]) - n = n + 1 - try: - cp.write(open(pgw.get_config_path(), 'w')) - except IOError: - pass - # ready to type queries, give the focus to the text field - self.ui.setfocus_sqlbuffer() - # initialize the objects used to execute the queries - self.execute = pgw.Execute.Execute(self.db) - self.run = pgw.RunSQL.RunSQL(self.execute, - self.ui.sqlview, - self.ui.resulttab, - self.ui.status_result) - self.ui.wndmain.window.set_cursor(None) - - - def disconnect(self): - """Disconnect from the current database""" - # disconnect from the database - if (self.is_connected()): self.db.disconnect() - # destroy the objects used for this connection - self.db = None - self.execute = None - self.run = None - # update the UI to reflect the connection state - self.ui.status(_('not connected'), 'PgWorksheet v' + app_version) - self.ui.enable_disconnect(False) - self.ui.enable_runsql(False) - - - def on_wndmain_destroy(self, widget): - """Called when the application quits""" - self.disconnect() - self.save_history() - gtk.main_quit() - sys.exit(0) - - - def on_wndmain_delete(self, widget, event): - """Called when the user wants to close the main window""" - return False - - - def on_menu_connect(self, widget): - """Called when the user want the connection dialog box""" - # fill the connection dialog box with default parameters - try: - self.username = os.environ['USERNAME'] - except KeyError: - try: - self.username = os.environ['USER'] - except KeyError: - pass - host = 'localhost' - port = '5432' - database = 'template1' - username = 'postgres' - self.display_connect_dialog(host, port, username, database, 0) - - - def display_connect_dialog(self, host, port, username, database, overwrite_entry): - # display and execute the connection dialog box - params = self.ui.connect_dialog(self, host, port, username, database, overwrite_entry) - # check if the user have clicked "Cancel" - if (params is not None): - # connect to the database - host, port, username, passwd, database = params; - self.connect(host, port, database, username, passwd) - # error connecting to the database, retry - if (not self.is_connected()): - self.ui.error_box(_('Error connecting to %s:%s@%s:%s') % - (username, database, host, port)) - self.display_connect_dialog(host, port, username, database, 1) - - - def on_dlgconnect_map(self, widget): - """Called when the connection dialog box is displayed""" - # clear the connections history - self.all_connections = [] - # load the connections history from the config file - cp = ConfigParser.ConfigParser() - try : - cp.readfp(open(pgw.get_config_path(), 'r')) - n = 1 - while n <= PGW_MAX_CONNECTION_HISTORY: - try: - line = cp.get("connections", "conn%d" % n) - # add the connection to the connections history - self.all_connections.append(line) - host, port, db, user = string.split(line, ',') - # add the connections to the connections history list of the dialog box - self.ui.storeconn.append(["%s:%s@%s" % (user, db, host), line]) - n = n + 1 - except: - break - # if we have at least one connection in the history, made it the default - if (n > 1) : - # select the last used connection - self.ui.viewconn.set_cursor(self.ui.storeconn.get_path( - self.ui.storeconn.get_iter_first())) - except IOError: - pass - - - def on_dlgconnect_change(self, treeview): - """Called when the user choose a connection in the connection history list""" - # fill the connection dialog with the selected connection parameters - model, iter = treeview.get_selection().get_selected() - host, port, db, user = string.split(model.get(iter, 1)[0], ',') - self.ui.entry_host.set_text(host) - self.ui.entry_port.set_text(port) - self.ui.entry_database.set_text(db) - self.ui.entry_user.set_text(user) - self.ui.entry_password.set_text('') - - - def on_menu_disconnect(self, widget): - """Called when the user wants to disconnect from the database""" - self.disconnect() - - - def on_menu_opensql(self, widget): - """The user wants to open a file with some queries""" - filename = self.ui.file_dialog(_('Select a SQL text file')); - if (filename is not None): - self.ui.undo.lock = True - for handler in self.ui.buffer_handlers: - self.ui.sqlbuffer.handler_block(handler) - self.ui.set_sqlbuffer_text('') - try: - input = open(filename, 'r') - for line in input: - try: - self.ui.sqlbuffer.insert_at_cursor(unicode(line, 'UTF-8')) - except UnicodeDecodeError: - try: - self.ui.sqlbuffer.insert_at_cursor(unicode(line, pgw.get_user_encoding())) - except UnicodeDecodeError: - self.ui.sqlbuffer.insert_at_cursor(line) - except IOError: - self.ui.error_box(_('Error while opening or reading from %s') %filename) - for handler in self.ui.buffer_handlers: - self.ui.sqlbuffer.handler_unblock(handler) - self.ui.undo.reset() - self.ui.undo.lock = False - self.ui.syntax.refresh() - pgw.set_proportional(self.ui.sqlbuffer) - - - def file_overwrite(self, title): - """Display a "Save As" dialopg box and prompt a confirmation if the selected file exists""" - filename = self.ui.file_dialog(title, gtk.FILE_CHOOSER_ACTION_SAVE, - gtk.STOCK_SAVE_AS); - if (filename is not None): - try: - os.stat(filename) - if (self.ui.yesno_box(_('%s already exists, overwrite ?') % filename) == - gtk.RESPONSE_YES): - return filename - return self.file_overwrite(title) - except OSError: # file does not exists - return filename - return None - - - def on_menu_savesql(self, widget): - """The user wants to save his queries""" - filename = self.file_overwrite(_('Save SQL queries')) - if (filename is not None): - try: - output = open(filename, 'w') - output.write(self.ui.get_sqlbuffer_text()) - except IOError: - self.ui.error_box(_('Error while creating or writing %s') % filename) - - - def save_list_row(self, model, path, iter, output): - """Save a row of a TreeView in a tabular form""" - col = 0 - while (col < model.get_n_columns()): - val = string.replace(model.get_value(iter, col), '"', '\"') - output.write('"' + val + '"') - col = col + 1 - if (col < model.get_n_columns()): - output.write('\t') - output.write('\n') - - - def saveresults(self, widget, output): - """Save the content of a TreeView to a tab separated file""" - widget = widget.get_child() - if (isinstance(widget, gtk.TextView)): - buffer = widget.get_buffer() - output.write(buffer.get_text(buffer.get_start_iter(), - buffer.get_end_iter())) - elif (isinstance(widget, gtk.TreeView)): - widget.get_model().foreach(self.save_list_row, output) - - - def on_menu_saveallresults(self, widget): - """The user wants to save ALL the results""" - if (self.ui.resulttab.get_n_pages() > 0): - filename = self.file_overwrite(_('Save all the results')) - if (filename is not None): - try: - output = open(filename, 'w') - page = 0 - while page < self.ui.resulttab.get_n_pages() : - self.saveresults(self.ui.resulttab.get_nth_page(page), output) - page = page + 1 - except IOError: - self.ui.error_box(_('Error while creating or writing %s') % filename) - - - def on_menu_saveresults(self, widget): - """The user wants to save the current result""" - if (self.ui.resulttab.get_n_pages() > 0): - filename = self.file_overwrite(_('Save the results')) - if (filename is not None): - try: - output = open(filename, 'w') - self.saveresults(self.ui.resulttab.get_nth_page( - self.ui.resulttab.get_current_page()), output) - except IOError: - self.ui.error_box(_('Error while creating or writing %s') % filename) - - - def on_menu_cut(self, widget): - """Cut text to the clipboard""" - w = self.ui.wndmain.get_focus() - if (isinstance(w, gtk.TextView)): - w.emit('cut-clipboard') - - - def on_menu_copy(self, widget): - """Copy text to the clipboard""" - w = self.ui.wndmain.get_focus() - if (isinstance(w, gtk.TextView)): - w.emit('copy-clipboard') - elif (isinstance(w, gtk.TreeView)): - model, iter = w.get_selection().get_selected() - if (iter is not None): - col = 0 - result = '' - while (col < model.get_n_columns()): - val = string.replace(model.get_value(iter, col), '"', '\"') - result = result + val - col = col + 1 - if (col < model.get_n_columns()): - result = result + '\t' - clip = gtk.Clipboard() - clip.set_text(result) - - - def on_menu_paste(self, widget): - """Paste from the clipboard""" - w = self.ui.wndmain.get_focus() - if (isinstance(w, gtk.TextView)): - w.emit('paste-clipboard') - - - def on_menu_selectall(self, widget): - """Select the entire text""" - w = self.ui.wndmain.get_focus() - if (isinstance(w, gtk.TextView)): - buffer = w.get_buffer() - buffer.move_mark_by_name('selection_bound', buffer.get_start_iter()) - buffer.move_mark_by_name('insert', buffer.get_end_iter()) - - - def on_sqlview_focus_in(self, widget, event): - self.ui.enable_cut() - self.ui.enable_paste() - - - def on_sqlview_focus_out(self, widget, event): - self.ui.enable_cut(False) - self.ui.enable_paste(False) - - - def on_sqlview_keypress(self, widget, event): - """Save the last statement in the history - if needed (after an execution""" - if (event is None) : return - if (event.keyval != 65507): - if (self.prev_saved == 0): - self.add_prevstatement(self.ui.get_sqlbuffer_text()) - self.prev_saved = 1 - - - def on_menu_about(self, widget): - self.ui.about_dialog() - - - def on_menu_runsql(self, widget): - """Execute the SQL queries""" - if (not self.is_connected()): - if (self.ui.yesno_box(_('Not connected to a database.\nDo you want to connect now ?')) == - gtk.RESPONSE_NO): - return - self.on_menu_connect(widget) - if (not self.is_connected()): - return - self.on_text_change(widget) - self.prev_saved = 0 - self.ui.wndmain.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH)) - self.run.run() - self.ui.enable_saveresult(self.ui.resulttab.get_n_pages() > 0) - self.ui.wndmain.window.set_cursor(None) - - - def on_menu_prevsql(self, widget): - """Display the previous statement from the history""" - self.ui.undo.lock = True - if (len(self.prev_statements) > 0): - s = self.prev_statements.pop() - self.next_statements.append(self.ui.get_sqlbuffer_text()) - self.ui.set_sqlbuffer_text(s) - self.prev = s - self.ui.enable_prevsql(len(self.prev_statements) > 0) - self.ui.enable_nextsql(len(self.next_statements) > 0) - self.ui.undo.lock = False - - - def on_menu_nextsql(self, widget): - """Display the next statement from the history""" - self.ui.undo.lock = True - if (len(self.next_statements) > 0): - s = self.next_statements.pop() - self.prev_statements.append(self.ui.get_sqlbuffer_text()) - self.ui.set_sqlbuffer_text(s) - self.prev = s - self.ui.enable_prevsql(len(self.prev_statements) > 0) - self.ui.enable_nextsql(len(self.next_statements) > 0) - self.ui.undo.lock = False - - - def on_text_change(self, widget): - """The text have been changed after navigation the history""" - if (self.ui.undo.lock): - return - if (len(self.next_statements) > 0): - if (self.next_statements[0] == ''): - self.next_statements.pop(0) - self.prev_statements.append(self.prev) - for i in reversed(self.next_statements): - self.prev_statements.append(i) - self.next_statements = [] - self.ui.enable_prevsql(len(self.prev_statements) > 0) - self.ui.enable_nextsql(len(self.next_statements) > 0) - - -# Start program -p = None -try: - p = PgWorksheet(app_name, app_version, pixmap_path) -except KeyboardInterrupt: - if (p is not None): - p.on_wndmain_destroy(None) diff --git a/pgworksheet_1.9/pixmaps/pgworksheet.png b/pgworksheet_1.9/pixmaps/pgworksheet.png deleted file mode 100644 index 24e6d3362ea3386b50d16ec5c0f8cbdcfeced9a9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcwPel00001 literal 1291 zcwPYu1@!ufP)Fv^1QZ-7h|~gu1qKHK76cp!SP&R!P+(OH0uC4& z9C%>C11Gt_cI;;-(N=EtziY~` zD*!~qlHDp$8Dl6*&GPfMJ_R7Qwpkhh;7932^BEu??rZoNsn^n{9r33CU}7oIF*c3# z_6g;yp?He%qohA=Z>_HgK)CRT7Jj`SIqfqB@=erQVsZmiT5H@O>D@yHPbi*ZreVWO zq*?2|OEVfpHeYiNdBHlGb;>oT+#n%;$pNaH)-R4~4)->GQub=_pbr&?>UXm}ydv9VX08MyU7U)i^e)2iTx#t3*2CFx9M&Q(1k6b|VSZ6`kIg@D4 z`U8sZnzGc^Tt5+Ic|jU4Pf5s7gVS*w=oP^mfcPPvC`Z+P8%jE9ue-Sh>E1(X%?*vS zJ>lSREK9a+Sx1-jG| z5vhzZthX7?ose&0LCb)CPhgJ*h$siQ2D_h_0M&1#s#1Z&u(VNH8_#YW^TV5O{tsqVRd{43_74C6002ovPDHLkV1i6q BM)Cjv diff --git a/pgworksheet_1.9/pixmaps/pgworksheet/about.png b/pgworksheet_1.9/pixmaps/pgworksheet/about.png deleted file mode 100644 index d66bfd7b02604ccf5ec74d9d284fa45498541868..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcwPel00001 literal 320 zcwPZO0l)r2cp?*Tb%RNC9{As}zd zO9A9JlV2=!ZLivoTMs#~e4St5`yNlv=PvKbZMS}xd+En5ykfx7ah2)B$;@7DoaSss zq=&$YE4^SkaTudIS|w}n`{I*G4+#SAXRF4jasa@1Y+nGZ%}V{p(L4o6Q*j0Fdce1o z^7%*wtrA3_-3fy~msr$jFk2k#4`?V_sG)}c4k5G#A+&>l1z198EsOH~LTJr@E4&(L2c`h4J9^0qcZ4j! zdNI&n&VlDZyAax1J00f|J&yT(+oF9B@3jmLJmt{gBjrNt=B)tS>blC4$GvUa{l2J_ zD!A+hLTC+As%TG7oE-){Iy)~Tgm%HsF6S>l7l)K8AMOaP z$kH>XP9UX9Rcg6DW%NHja=TYioG&svJ&AMgzA|4bSpej78Rm;7n_9hiJR1p~JYA*X zx^X>HMVjV!00Myn7~c$(QWynQ=JnJE0196vqa&}GnVMi?^1bbluJFYxRiwk=;A|*J zGC53BV-tp9kk4ky^|7~a0LbQYjE|2pH#(=yO;5!n}PMf@K4GIB&1Xbp&bRD g*-c(U4gU^504g%qVhqttJOBUy07*qoM6N<$f+`6L*#H0l diff --git a/pgworksheet_1.9/pixmaps/pgworksheet/disconnect.png b/pgworksheet_1.9/pixmaps/pgworksheet/disconnect.png deleted file mode 100644 index 0769aadcbba4111e2f998feb8a0bfa964a98ffdd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcwPel00001 literal 581 zcwPZT0=oT)P)+-Rc9(enTd4IS#?;ozPeM-p5^Cnm*nJ@sOQLh>|u3xpb8a02Qc6)bL&BON=?{sx+wSECG zJ$)AUr;C&lw<-O&_EvGVCue{D|c<541}0El@WfbAb!Jv`K>@w2z@HsjaQx5+<#%9m<|R;vZT+-%$c z3?WQI2-C`CGtAA#0cbX*UqEx?FJHw8;25ysg-!vb{WOjv0ir^fMUM|Kz(3*-w2J&- TB{7ON00000NkvXXu0mjfAfpTP diff --git a/pgworksheet_1.9/pixmaps/pgworksheet/pgworksheet-32.png b/pgworksheet_1.9/pixmaps/pgworksheet/pgworksheet-32.png deleted file mode 100644 index 24e6d3362ea3386b50d16ec5c0f8cbdcfeced9a9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcwPel00001 literal 1291 zcwPYu1@!ufP)Fv^1QZ-7h|~gu1qKHK76cp!SP&R!P+(OH0uC4& z9C%>C11Gt_cI;;-(N=EtziY~` zD*!~qlHDp$8Dl6*&GPfMJ_R7Qwpkhh;7932^BEu??rZoNsn^n{9r33CU}7oIF*c3# z_6g;yp?He%qohA=Z>_HgK)CRT7Jj`SIqfqB@=erQVsZmiT5H@O>D@yHPbi*ZreVWO zq*?2|OEVfpHeYiNdBHlGb;>oT+#n%;$pNaH)-R4~4)->GQub=_pbr&?>UXm}ydv9VX08MyU7U)i^e)2iTx#t3*2CFx9M&Q(1k6b|VSZ6`kIg@D4 z`U8sZnzGc^Tt5+Ic|jU4Pf5s7gVS*w=oP^mfcPPvC`Z+P8%jE9ue-Sh>E1(X%?*vS zJ>lSREK9a+Sx1-jG| z5vhzZthX7?ose&0LCb)CPhgJ*h$siQ2D_h_0M&1#s#1Z&u(VNH8_#YW^TV5O{tsqVRd{43_74C6002ovPDHLkV1i6q BM)Cjv diff --git a/pgworksheet_1.9/pixmaps/pgworksheet/pgworksheet.ico b/pgworksheet_1.9/pixmaps/pgworksheet/pgworksheet.ico deleted file mode 100644 index bda11bdd3363bd23134688bd42dee1e2ae50085d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcwPel00001 literal 16958 zcwX&WcUV-{w%1sq(e#^p(@ku2#FE4qTTHnoYBUj}!oXlblNe%(u|#8w4Q2+gcSTgB zDJY1bLTG}Df*>MIih%Tvn*Y{YYn`*toEgC6=6>(5_sq95`?S6H>c6%2rc0Nu_}}>P zUGV>Jbg`V!rOQ9Nbm?M=4R3W>+eNzH*}vA-R%mN$gZuaI1NEsF}vVeI>3 zVa&KOU~6v+&p!7o^W({v*CK$m3H&}H|tmPPt6ZCzs&pUrk=N|x=I;O$Vog` z_r-X0ZDVHxJ$m*4jjINdFC{}`W23UR`o?;=k#z(7{QY3M<^Ygm; zI(~K|`v#B0{hK%VoAQcsWvq~8s8I2L*g`~v+<+WGkN3V&(7?AzJx z-VrT2E*i=z%D8p*4)KJ>A(}o%nSTAv*YL+5e?VpNZ8*4WGI)O3AH19ffgYRZmjgks zv4Rupo#9q$6#9!6){ie|eF;5#_JoMYGYSu=ku1eJ|Em5I{Y_0x5Ed22>+=uxhlrR6 z2#p9;)|`-%!0#266e;%tP6qIMYT9n*+~jqXl^f{~ITOO~iI!WC%WEmPQvlCB{~T0S zRziJkB^+8d34ENbz}v+E3|egTtHI_*zjmOTH3-6e7C~!sBb3}N0V^9Tu&^2g&CSj2 z{GysRb>G}xg&tH^S3+!3EH{!by;D(Hq3A>8`AB~6O!OJPK5^;b*3^hz(bu~guZbrH7i%cYOoEo?7O=Fkgg5)Y zfjZG_Lf3zy{~}h=I!WF~f{w79g%2d17JL=-hew4g-_f|yvC#^>tp6(er*Y{$VVl%1 zM}IkJ-~cfA7@#yi6ZFmlQMUHrh4fJ)TGf5B2c4`728|8G9rJ>=`)x22{Xnl?z2HLZ z1x5eO{h`{=sr{Y#JEY^Z-oUUxxLbCYWlnOXM%VOB(&Z$DuEf+t_WNl!(v*9o|1{R0 z=|9CZitEP$jzK|sJm_W*U>ZrzZ2zv3{rkwiz*{5tNf%I0LN>d>{fGBKr}t#spwsJk zTy-peR8#AUc%Rm(_GO|GKgd7QJM|6qa5C~_hwqUOAU{Imnakf?|C3Xap?i<+=)WW2 zMtmrEp>I>`JomLmohSO~n)|Lp;P8@9p{=DEf`Wq>8@bJO<8jq->aXg*pr5`~%aYpZ z=+jVGTxjw=@gOca&g4Cck%WE3cz;HJLP7$sJ1IFHu0|cgcxTa0=jm4`^k2mfJ<`8( z!CO#UQ3Sd9xjfFucSoAg@}JQEDEw@WrOkb%ph@)2n^=>%&7C=O8oKrD1~)QqKthl& z+P|eFUl&={vi^&{x7uCMv_x@AAp_}7d7;{53E$p3$X zexW<&v_Ft_V*lP<(5p``C@v|6IRA}Eza7h4rdTe0hj^axAB=}S zefz-GYghjk{g2Xjb?b;f)Cju@T@u%n&ysK3qT2%B|L6f8-+RF7H7g-7C=jadmBH3+ zTcJ1RG9@J?aN+Pe^zC*`mtG?`qS3|JXIoJ0ADfdk#QG!tfA|1qI?aThkN1R>%PH;F zZ@y;p_5Ydvt8JKm8=D#->~t7-e7gvoW>1F&U%5kAco_Rc!t<1$I8L9+ISu)xjvD#> z*WY-ZWk&R$_gjZ@wKM9wtmlfq(@Hp4Tr)0qwSzF9Z<*KYH>~F|DW-I$za7cVTwgn* zU);NvehtP?7~hVbu8(zv(c?zL#?9;DndhG2c>KyMFT|!4n9)1cct16+U zrUqK^KJn&(nND{^ztCOrj=C?tNlZ$F{sa5-x`z%M0(yfEA`pL5-fC$*Sm6W7Vb$7I zP*9MMYincwB<6W2|B|0tv2q2x@UIux{x2L@1wL-Jf2#imjZyz82JHL(eQ0j1h1iSd zdH&a5e-#E>3u%C(Gzq!?%m4b|mPQd|t{RCG{sa5L*~OV_BV4b*T)pJhRY(lo3Wt|YMp;@TKkPWS58mPi z^)=-@-uXjFzee)^kHr6Ke?ZvC$r4KPGIgtfaMJrL-MyTDlY+eAR!S69mQbyM<=e8g13p&6U^p=72X*zwdNNKk4r* z=UM!oLGQ)S;sOmAcP)4wtef)s7^5Q|30SXz=B9d{W8$Y1O=85G{ojPF>?|H9a@WtW zdHQP*vSl9oZ_4G!{tepp`me_SqA&E{YxW>WIeQe>-wNS7enfr@#5{5!>|OjmobmO5 zbBESI6xvp}?;;3T;|MVaRzgc-J=^EB&!_Ra$X}^3z>>Zzx|!pZ`cEL$SYg*so5 zmCXKu`Ua=LlDyqa_20z*3mp(XlH@L%y6^N?y{85d5#?W=K$KOh+jf57nvuLYd} z=+lY*nX?_+%O7oJ>GGxgeD(U(thez2o{Tx!Ce?E2z$Zl?T#ajLfxP@YSif!!WMpRW z+|(q$iZ+Kly@$3Lx$`HKy}gp#o9MsjtDfn!#y-Ua(t*g`OF0)5K0D>|C9bW_Uoao$ zEtm((RxAS@#_Q;qXvoaUg!GJb#*9SYZ@;Z=NB_ObdmQU&zacj-7nH z%j==KXt38@#v4S#{)79Bw%64Zr#R1oA!OjUd%k&(c|vvVjMzZbd9wKh=sRttxNbJq zU%~&J56ga#;!kxs`mxp~Xs)kjd;R3oPnbrnRtxb7@vvwA9`N|V113$G1QRDugq5pT zLQzpsJN!@0ah4-I_Sj<(5)#7K$JRQsjN?+^HDgM`sT9BIqkDq<%G_R9@ zd!K#wS>7kf$;mN^@8%dsO@BjU1N7lXAq(oDA6P;(Ds)(6ZJeJ48qDE!YgLFD(5l~Z}$Ef{wmV4P1q zy$5wHm~GEvu?J%p$1fcf+ZHsdn;HWIg-Z1_7p;qg0m65Iezuk3^F?ej*I6H=!*}iw zs6h-swCzTJA#j3^h}}%THT-@|$2yQ0?1OTZ_B;NH{;U1JR0A2zdqS<~Ya{oqgqpHK zXhbZq`Zggclmwq7-{qjI1Hi+6K_wn7GmG~_H*1?yLK(hbLzCI(1JE8^j$4~K|j@^ zo`3#%ut3b#*4hRI=?Q3~781tO%Ja%Tr(NI43KBznm}end<|EH!jHng-aZv0;hxqKg z|3;qs;^7Ta-lHB%wiUhlTKqEJ9Kslv?a?d(4BKyLK|I<~3sB4~`r=!g=)9i@xUP7mscNZzmgR4MKlqIhgnLv#j9q*@HZv z|1Z;!9y`T9OM5n|KH`=mzf57=avSlxLaWS&N8x`T=HFnrjCM{qB|Zo-DdJ$V(YOFT zWBpLy?|9EN)UcSbVaUl4_UFUj9?rD^bF3@m@4nET`4kiq#N+s{{DSiw;lC6=@6tgZ z=Sw=djp;wRWsYR~vb{<)%kn2aQvKTfE!6)zhy^OZm*!B}m|p0+*4Q`5I!Ly%7kx`p z9p>HlN??ck+n7gSY(n~z!}f4}F?bW=Y4p2PQz*Z4llS5shB`10&YnHn&i@hpYdd*hnR^QD|o zud!*b@2YF%8}bQg=Sin_@OQrl=rGT*mgdLUa~)$2-9NBw8rzfsu~p3e)x0K8gQw&N zKA+T%eyUYpPruH1Z{(%9{|F4yJ;xoqq^Ostd{jNo$@wu&RU)GS9k;vn1U+^~biW=<`P)=4@ zm=CYK@)FlWXwOdV^QqDK65O&LwuX1EREB0f&MSPOw zXzthbXv0S^R<%|!q2q2P)1D>9Vnr}uni`nS#*0{4n;;rmVK z(`*&HQ0u>5rT;|7HusT?ttc1QYcMXO9~E;blaMdvw&*m2F2^osJHqbsK)|63t5{v_*!UTZp! z;{Ua>4kG;#JAY(5jy=8w$FSlWnz!7j&UH60opCMM6VEB@r?)fWjg`}&4edHIDw1iP z@ZkjZ`$X^FeS7)d`t|EsCr%-LFrYpAXpC|eF__O_$g&Z>P?A6TfBizVvo`eqTN#_P z+?f_z%=bTo;+v@$kFy|XlPjFr@souA5M%ku{#A@C{Hjv&*%4l`1uE> z-~YHjpD8);)4wI16FRT*T{>Zp!cJu!BVQDOzL~x!IruG|h?vYm_8+#8nHa9rq2dBO z;l}TQOiRGJ+48w2qs}X}P8Xy8lYX7_a_9JZIpP54I8|juocARl?$OQc4@u$sS)YS8 zBK~qS`UW1G;=nm6r}<>!$D9|&#GK{#C*d{mMDhu(NSCGbo$$Rv9&Sc@1tw79Ino&J z>%sga|4cC?GwC$fUUw~c3-)@9flx0uIP~KuaLUJnYc+RoUxn>+jCq2|xU%jFUXvVm zpuDT@7VvqjK1BX_T0d8pS+IDz&HsWz}-^9Gjp;vc?a z`Yo+3p~dxqZu^H17uUf!0KF zr+N_e$%o~nM8mFyBNzw%rTP!c!5;ZI9_|+2RBCG##kb*Z&NV2>&4gOahe-b}piOz9 z48@wsX2}+JfAub(HM@ExmGhjDquz$Px>}A2*2sfe#J#y0m$+^&u$sUxG`|{)_=wo( zBI6JA;d{RS0Gd!X1&G5uXS{}feF(#W&dx6B~bNhZ}Os!rg;}?ucRi(K~ zyrVs6I*a=f;zCpM3E)_Yu4=SXEkx-&jk$!?>u& z_(SW_yIA4+5wANV?V2G9c2UN1G0xKt|7+BJv~A2wy>U!moOkQ|Vc?6n_)c~z)4yl& zcnKTG-*Ak?@u-fKoqCq{>W7aQ&UKEwygcalMn673L;DtmnaL=-ev z2Sahrb!eb^vBy{tH2@!#o+$ppMXn2VFji;vpLX?6nLj?5dj+g_;`&!nW)kSW9Kg@i zHp{%m7?Bdbn{8*>G->}MJuM9!hB?5iufNLYyvotG2tSILCt-VsKgIt{3yz-}v7fPK znD@7=-<{!q9$RCyB~jz=4F8Mo75h_zB%zeAXT_Oi&wWn4UgIi8i`A5HMT#zE0{ zBYrZzW76;7S{aM^W-H+iq`fdJS+X&)9{GKdd+IPBJ}2kHw69C_p9(((?hEI#Ka9qB zNV41Z)o2s^C}MMG_@8yuMYc1HgH25hoQv#0f1v2Uyk1|S&u$LN*-r7jx&E8te+MHj za25JLgwFufRhDw?KX8K!%GkQYHA`p6Z6N0GIw==)lXAh+k*5*=?cx5q-_~*b4%>?O zPh%%zH&Z>(tNQBu!jE~;-cM{O>%i&l-vibD6)fiJpzI&2udlPEBuUvQ3XBrS|FP{pu*Ibf&9cj1YT9iVEOh3Ob>!!)~>b^Xu;{WCEDHqfu z=1mCl<~m&w#{caY19*={mbH2;R1HdedeP8mk){vbN#eOzw-wLinalKS4)2x;D4!vC;J(l_YAL|VM zdO8h+7{86Y$6ALmYwzL-oa2dc#rxuW$*yeR*l$|I%Z-qRKA&hGK5QsrrW&pV?AWn` z^})mAYu2Zm$!FMKD)>*4uS)J3v%af{b@p(0*(7MHuZBj%6#FnAF=*`-Kcts+(?|YB z`CjYLDgGyVd@-KrXAgpeU~gVCjqm@fBiG)2#M;Do!bj3Q#2fp*pMd$o9ZC16OS->d z({D=stKwb-|E(F-$LJg(*B4K0;ku&8p@{d2&v#ReFYB3j#y$?$6mxJL*SIO~+VkC5 z5H(R@Gm8HgV|8W=Xj8OrMmZ1Vc(k_aic;`fHC;M4>}KSZiQlI6qMaP3{aEyoWGla} zUd6Oi%%}Z5u^&Lcr@~J0evyr>HC#$b#8}u2$%q$7mRsk)C7mll8xyrf#WsYUk^B*( z)7ebQ_jfKF33=D!ndjwqvN1N!g}vWR;5{&^feT!!Zh{xYE1ioC<~*Z0cc(K2wfCgG zwd|C0aPY^8d&m4P}pAL0ehrWsGpfv6d_qQ;XX}Hc^ zap#tl>$JAO&7?DMXvx3XztG<`tSoV4s3*><{V(rlog6c z=sViqpEutPdi8po>z+%OErka3{pS0?YWl_AAbmS?)=c)3R4bqydCAX9;AGfIC@3g^ z($Z4SoydmhY*=AoAtWWmgYR}#o3>|9E^;F{d6MdfGvqUrw zRe6u)L3PLKs!BemdGqE?I2v#iu3ftZ)z#IUFDvJGZKv-BPY}mMg*GcEB=v&(BqW&h& zP0SOnKm3LBuj)Mkg-_V-p#KOv6NWKk1Gvs{g~^j9!=z6pahp7OGPr78`OMMY{d*xP zISKBfPKY_wx>iwM#^*?v{jvr!jvgf_`Ic)(=0xR(Y0Gw z6aG?+>hX9FZszBEUhDT7@?jS155=^0w5Zn7k^Xl`znPx!_5BA*>=3*aW2yJoJL=P~ z;0^sPEB*Z^ow=g?n_>=)EzNPCWtW|u4JSfQfWg-Qi+@}Ut{NwBbDqs@?z}lH`$K+* X;M&zIJdT>Sze0bP|Nr-Y`rrQmS`QGj diff --git a/pgworksheet_1.9/pixmaps/pgworksheet/pgworksheet.png b/pgworksheet_1.9/pixmaps/pgworksheet/pgworksheet.png deleted file mode 100644 index 8672762e613f43c81996154341d4a4b82e82e05c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcwPel00001 literal 14247 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 Nyp`kl*{{AZ_}@tkFsJ|k diff --git a/pgworksheet_1.9/setup.py b/pgworksheet_1.9/setup.py deleted file mode 100644 index feb6b1b..0000000 --- a/pgworksheet_1.9/setup.py +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env python -# -*- coding: latin-1; -*- -# -# Copyright (c) 2004-2008 -# Henri Michelon -# -# $Id: setup.py,v 1.14 2008/03/12 20:26:23 hmichelon Exp $ -# -from distutils.core import setup, Extension - -__version__ = "1.9" - -setup (name = 'pgworksheet', - version = __version__, - description = 'PgWorksheet - SQL Tool for PostgreSQL', - url = 'http://pgworksheet.projects.postgresql.org/', - license = 'GPL', - author = 'E-CML http://www.e-cml.org/', - scripts = [ 'pgworksheet' ], - packages = [ 'pgw' ], - data_files = [ - ('share/pixmaps', - [ 'pixmaps/pgworksheet.png' ]), - ('share/pixmaps/pgworksheet', - [ 'pixmaps/pgworksheet/connect.png', - 'pixmaps/pgworksheet/disconnect.png', - 'pixmaps/pgworksheet/about.png', - 'pixmaps/pgworksheet/pgworksheet-32.png', - 'pixmaps/pgworksheet/pgworksheet.png' ]), - ('share/locale/fr/LC_MESSAGES', - [ 'locale/fr/LC_MESSAGES/pgworksheet.mo' ]), - ('share/locale/ja/LC_MESSAGES', - [ 'locale/ja/LC_MESSAGES/pgworksheet.mo' ]), - ('share/applications', - [ 'applications/pgworksheet.desktop' ]), - ] - ) diff --git a/pgworksheet_yvesf/Makefile b/pgworksheet_yvesf/Makefile deleted file mode 100644 index e7ec4eb..0000000 --- a/pgworksheet_yvesf/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -gettext: - pygettext -d locale/pgworksheet `find . -name '*.py'` diff --git a/pgworksheet_yvesf/TODO b/pgworksheet_yvesf/TODO deleted file mode 100644 index 7db3d2f..0000000 --- a/pgworksheet_yvesf/TODO +++ /dev/null @@ -1,6 +0,0 @@ -*request -> result (resultview) concept is bad - * once QueryView a ResultView? - -*Configuration COncept - -*Database based Components (Snippets... ) (needs Abstraktion) diff --git a/pgworksheet_yvesf/applications/pgworksheet.desktop b/pgworksheet_yvesf/applications/pgworksheet.desktop deleted file mode 100644 index a2c16da..0000000 --- a/pgworksheet_yvesf/applications/pgworksheet.desktop +++ /dev/null @@ -1,11 +0,0 @@ -[Desktop Entry] -Name=PgWorksheet -GenericName= -Comment=PostgreSQL SQL Tool -Categories=Application;Development;Databases; -Encoding=UTF-8 -Exec=pgworksheet -Icon=pgworksheet.png -StartupNotify=true -Terminal=false -Type=Application diff --git a/pgworksheet_yvesf/doc/AUTHORS b/pgworksheet_yvesf/doc/AUTHORS deleted file mode 100644 index b4a29d3..0000000 --- a/pgworksheet_yvesf/doc/AUTHORS +++ /dev/null @@ -1,3 +0,0 @@ -Henri Michelon hmichelon at e-cml.org - -Yves Fischer yvesf at xapek org, Sidebar diff --git a/pgworksheet_yvesf/doc/LICENSE.txt b/pgworksheet_yvesf/doc/LICENSE.txt deleted file mode 100644 index 5b6e7c6..0000000 --- a/pgworksheet_yvesf/doc/LICENSE.txt +++ /dev/null @@ -1,340 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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. diff --git a/pgworksheet_yvesf/doc/README b/pgworksheet_yvesf/doc/README deleted file mode 100644 index 557792e..0000000 --- a/pgworksheet_yvesf/doc/README +++ /dev/null @@ -1,36 +0,0 @@ -THIS IS A MODIFIED VERSION; some code might be very experimental - -Contact, Yves Fischer yvesf[at]xapek org - - - - - - - -== General Informations == - -PgWorksheet is a simple GUI frontend to PostgreSQL -for executing SQL queries without using the psql command line tool. - -More informations on : http://pgworksheet.projects.postgresql.org/ - -== Operating systems == -PgWorksheet is certified to run on the following operating systems: - * FreeBSD - * Linux Ubuntu - * Linux Fedora - * Linux Mandriva - * Microsoft Windows XP - -== Depencies == -PgWorksheet requires the following softwares to run : - * Python 2.4 or better - * Python GTK+ 2.6 or better - * that requires GTK+ 2.6 or better - * pyPgSQL 2.4 or better - * http://people.rpath.com/~gafton/pgsql/ - * mxDateTime (required by pyPgSQL) - -== Installation == -Please refers to http://pgworksheet.projects.postgresql.org/install.html for installation instructions. diff --git a/pgworksheet_yvesf/locale/de/LC_MESSAGES/pgworksheet.mo b/pgworksheet_yvesf/locale/de/LC_MESSAGES/pgworksheet.mo deleted file mode 100644 index ce1bfec5a822ec2ac50ff86e64c14ce4f89f0815..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcwPel00001 literal 5064 zcwUWGUu+yl8J{K%iS5|Vo!b-&4FkbVo8%ljZfJ6K(m2jJaT7b2*hy#*I_=%f-7Q}4 zUT1fGu^*6l0ffX0&r|^2)giyeZhlP2H9}^-2ybSCIR)C)b`oKNF zZvyuLZvlsZzXI+8z7701@I5>KH{f32zkxe|nVqcnG2jUBY2c&4lfX{{7k9GWa3|~g zww1fJll^?%%Dn>|1%3d05}1WBOo$V^c;D$=ygmmU0|vkx@P|MO@f{$xir?*Gy?+EA z0R9u$2i(`k^G^YXfrUPf|7suWe+l?m;5zU#z#jmofN%7%{{QrGo*wFF%mN<=?gu^s zJZ0w>?RT}G<6g7#-?Q>}fCIp{`Z;L&6=l{2Z%!dyL+3)Qj(dU4}L%jc)A?Cxv5c^Rc zVm>v7INo*O6BL*I{^=0s?KeZ5pWoa4f3^EQvif%n^LZZ}=JPx^%<;OzoS)_}^LcHU z{r<)<+qrG!-n96()$=a!DT-s5^ST#5M}P?!RX^?rmB2^8l~_EN0oC zSF)VnA7wdjuVq=!>shw{R+i7_Pgd^zEXV($mH$VU^ZZ}CFFV3^4*(wno)}^I%Oh;> z3&2UBGs1db9$`NHc!cZkwGlqgUjRWTF)jFgQ%|8h5~pVb`#vX_%akXo0jk$0MfwmAsCJ1@ z#{~CadL9?O&wh*4zYg0m^|UAK_>@KJ&&0WH_M7rZIeiB2vx0d+s{v9s2(GGR3*gUuFbA!w!Q zkIAA|t8Ng7vJ&_{Cf&df#dJA{BmR}e`t?9BhYh77G1G9ggN<623VtQ1x_({E@IDy@ z(vejsa>`DqFxy;{q4HQGEk+F`E1ugd2ac|a8EC%G^4X4_&Y;UZan=p(m#pbv#cWLs z7qmvq9cjN#x<|wOXn5NE+Vxfg`H~eR*2vHdGD<_&mz$)5rt+;29Rv-H*^XETWL^|* zs!EK5F~J0Wq-fm1b>6E>3Lj;tXrF&}6JjnKW~m{V}fc}LJBoo3T>D`r|O z1RYi-Bg%yz^fHSUyQ#GhM4e-RL@zsvP8hZVoHGVnrz@pG7yo2V77<=uD~gHUr6BM` z(Nn~bmg7c;ZEnoLLk(Al<5y)(MU_Tp+ScFL*qA5=Iue&-H!=%F9n`h6A{L!h)t$Jz zCO9CIN3&F#_B?qdRm+o`CmaZM+23+RVC|Z#S|a7= z1ICy371HGeb>Vl@T=aBfkm<{q&dpVG*OU%XOL(n;$AckRR*?>{NVkHLlpGh0neR$h zX*7iPMj3%r8d|w!<CNwjTG~o)^G$#OA~6 zh_6bSq_(q&IbLu7vQ~p;8KeDrDokv2OyvdD=5!p^+8Ygu6Ax0DN;loZPg&!N1`tA>_y>9q$DLlHDT_!xGsfE96p zPNAEUnYJmW?YU5*-74pWc`|64BpQb2QEnFEOIWq3v@rW$22Db=Q7s@^n> zv*6q=ChK$q^<*hs>Wr{lO4E9u4Rv|1uAl}xaLd{UXHnADz{t6 z7V9!<)s(74+BAr^u3TiZOOQHe3{fboG;qIn-z{V#{c_@3*B6Q{sq`_NgC9rhowgy8 znlv4P37;0KT`o~^o5lt*Q^lPrDMzEGqfU@?vwAhvxnNN{rG@tGN`wA~C2{v2a{Coi u$5etyAH`~ydc{gz3AUH)v>y`LjdO\n" -"Language-Team: French\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" - -msgid "%d queries failed" -msgstr "%d Abfragen schlugen fehl" - -msgid "%d results" -msgstr "%d Ergebnisse" - -msgid "%d results or affected rows" -msgstr "%d results or affected rows" - -msgid "%d rows affected" -msgstr "%d Spalten betroffen" - -msgid "%s already exists, overwrite ?" -msgstr "Die Datei %s existiert, überschreiben?" - -msgid "1 query failed" -msgstr "1 Abfrage schlug fehl" - -msgid "1 result" -msgstr "1 Ergebniss" - -msgid "1 result or affected row" -msgstr "1 résultat ou registrement affecté" - -msgid "1 row affected" -msgstr "1 enregistrement affecté" - -msgid "5 Previous connections" -msgstr "Letzte Verbindungen" - -msgid "About" -msgstr "Über" - -msgid "About PgWorksheet" -msgstr "Über PgWorksheet" - -msgid "Character _Encoding" -msgstr "Zeichen Kodi_erung" - -msgid "Connect to a database" -msgstr "Mit einer Datenbank verbinden" - -msgid "Copy selection to the clipboard" -msgstr "Selektion Kopieren" - -msgid "Cut selection to the clipboard" -msgstr "Selektion ausschneiden" - -msgid "Database" -msgstr "Datenbank" - -msgid "Database connection" -msgstr "Datenbankverbindung" - -msgid "Disconnect from the database" -msgstr "Datenbank trennen" - -msgid "Error connecting to %s:%s@%s:%s" -msgstr "Fehler beim Verbinden zu %s:%s@%s:%s" - -msgid "Error while creating or writing in %s" -msgstr "Konnte nicht in %s schreiben" - -msgid "Error while opening or reading from %s" -msgstr "Konnte %s nicht öffnen und lesen" - -msgid "Errors" -msgstr "Fehler" - -msgid "Errors :" -msgstr "Fehler :" - -msgid "Execute the content of the SQL buffer" -msgstr "SQL Ausführen" - -msgid "Go backward in the executed statements history" -msgstr "Zurück in der SQL Historie" - -msgid "Go forward in the executed statements history" -msgstr "Vorwärts in der SQL Historie" - -msgid "Host" -msgstr "Server" - -msgid "License" -msgstr "Lizenz" - -msgid "Load SQL queries from a file" -msgstr "SQL Anweisen aus Datei laden" - -msgid "More information about this application" -msgstr "Mehr Informationen über dieses Programm" - -msgid "No result" -msgstr "Keine Ergebnisse" - -msgid "No result or no affected row" -msgstr "Keine Ergebnisse oder keine betroffenen Spalten" - -msgid "No row affected" -msgstr "Keine Spalte betroffen" - -msgid "Not connected to a database" -msgstr "Nicht mit einer Datenbank verbunden" - -msgid "Password" -msgstr "Passwort" - -msgid "Paste the content of the clipboard" -msgstr "Inhalt aus Zwischenablage Einfügen" - -msgid "PgWorksheet - PostgreSQL SQL Tool" -msgstr "PgWorksheet - PostgreSQL Tool" - -msgid "Please wait, executing the query and fetching the results..." -msgstr "Bitte warten, die Abfrage wird ausgeführt." - -msgid "Port" -msgstr "Port" - -msgid "Quit the Program" -msgstr "Beenden" - -msgid "Save SQL queries" -msgstr "SQL Abfragen speichern" - -msgid "Save SQL queries to a file" -msgstr "SQL Abfragen in Datei Speichern" - -msgid "Save _All Results..." -msgstr "_Alle Ergebnisse Speichern" - -msgid "Save _Results..." -msgstr "Speichere E_rgebnisse" - -msgid "Save all the results" -msgstr "_Alle Ergebnisse Speichern" - -msgid "Save all the results to a file" -msgstr "_Alle Ergebnisse in Datei Speichern" - -msgid "Save the results" -msgstr "Ergebnisse Speichern" - -msgid "Save the results to a file" -msgstr "Ergebnisse in Datei Speichern" - -msgid "Select _All" -msgstr "_Alles auswählen" - -msgid "Select a SQL text file" -msgstr "Datei mit SQL-Anweisungen auswählen" - -msgid "Select the character encoding for display" -msgstr "Zeichenkodierung für Anzeige auswählen" - -msgid "Trying to connect as %s to %s on %s" -msgstr "Versuche mich als %s mit %s auf %s zu verbinden." - -msgid "User" -msgstr "Benutzer" - -msgid "_About..." -msgstr "Über" - -msgid "_Connect" -msgstr "Verbinden" - -msgid "_Connect Server..." -msgstr "Mit Server Verbinden" - -msgid "_Disconnect" -msgstr "Verbin_dung schliessen" - -msgid "_Edit" -msgstr "B_earbeiten" - -msgid "_File" -msgstr "Datei" - -msgid "_Help" -msgstr "_Hilfe" - -msgid "_History" -msgstr "_Historie" - -msgid "_Next statements" -msgstr "_Nächste Anweisung" - -msgid "_Open SQL queries..." -msgstr "SQL Abfragen Öffnen" - -msgid "_Previous statements" -msgstr "Vorherige Abfrage" - -msgid "_Save SQL queries..." -msgstr "SQL Abfragen _Speichern" - -msgid "_Tools" -msgstr "_Tools" - -msgid "_View" -msgstr "_Ansicht" - -msgid "connected as %s to %s on %s" -msgstr "Verbunden als %s mit %s auf %s" - -msgid "connecting..." -msgstr "verbinde..." - -msgid "log" -msgstr "log" - -msgid "not connected" -msgstr "nicht verbunden" - -msgid "query failed" -msgstr "Fehler bei Abfrage" - diff --git a/pgworksheet_yvesf/locale/fr/LC_MESSAGES/pgworksheet.mo b/pgworksheet_yvesf/locale/fr/LC_MESSAGES/pgworksheet.mo deleted file mode 100644 index 1881c2a286bd54fb9db1d342bee7132c63e4e225..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcwPel00001 literal 5393 zcwUWGeP|rV6`wdC)`xBBq-)cB*qJs}03QLa9Av%W zLDu(eEBER_w)4kU?oHqT@D}hfU>}6Bgm|)p=bi1~@j2iyFaQ>S-viPX-vnZ+c&mf; z{vJ38{1>njc&wBAj{|#vrB2@el}^@w9r!WeP2fj?-vv$pf7QwQ|I^8Sx~q$^5BMPP zQD7c8Y5P~~f3=JEy>0tnvGO~>Zs2da*pI&hJ`Vf~a2%NH=JhUiv)zl`Y~M4$KHyq6 z&yTy=|6j8B6^q}n@-KGty5H$$dwyi`*B0OHX8+!@^Zp4O0sb3!82H2?A?^l_AL9QB z;32XLpNH-e;@TnRQFxfgzktsZz!wg)pMMG*1HN;Z?ddwgcJ~864txao0C46A^Xs!m zSZ)h=Kk$oo{1q$z`VrRuuEhgAyuU&Z$8EBQdE@l3Kfh}6^&XDrA9|P{|LtMF-q*|P z^!Bpcaf{2nEcbbfU+!fdy#PE4{7Emb`!+s9z(3jkUL?UO;Bb!pAw2ygmu8;TsY#-;x7VsqSWjp>xALqk+eVk7n_?!Sf+|PE* z0-pwcuAlw>i+;B2jed^TJN=x`?^*muKl_EqVd9l%Ui9aA{sVdD%|M>_Rm^kTp0(J> zv%kKXXI{LV=REy>o_YROp853GJg9 zyDgp(%vmsJebl zO!GV$1=5jKCvw)DP@%WJEkot8MjDJZl&pAeeJyZwRZK(k2Mo_7dXh%QJTc>j_D`mfnckb?RAe32u&(7VNZO<#YKG*`E?!loyeY*-#i|tz#@JxjSe^k|=|* ztFGD-DL?OUf9bhGy1bw!{4C8y+i46kJ%{eXT(xjj=@7Y8luH+`EiQk0WwumWm0e4V ztA%NE1_gcrC!H$FQzIj%3nOENQ{!@UqI5YiNQWDo3{9 z%qt}2qA17L+^CBRozhyxnrmKjhxqJ7yZ&SlgP>Z~Kn86OIzC_^Vsz{~IIlo@WIQO2 z8ft1Mszh_=x#nv_vJu3dx>;xtVZ6cSPDSGY(WaiVRa7SvE3$1eD7#{7L7M6BJu)V% zO8ai}2T0oXDl6+cs0V2Sf^FrNi!8!|0ZcV1Yt$f>Tcp#n`I?M{~`@@yLAA?G19tb&>NXK8j~?Xd8}Sxg$w)AcAm7$)+n-&A2GDGXCl@%5v-{ zq;BI(MMWTYwq~QQ(m=}LwhrcTb#On%8sU9MuTs|dgKSvcX>q!_vv2$ta7b2(L7}-C zdY*But@*Gd-o>%@n!gBFdFC9i2eHmv0mM}myHIu$^CA~UDm|2OE;15JAf#<|-h_29 z>#P+gZm1gW8c@_0a9Wc`cQJwEnu&%Lip+sRlIek#nO{!3`AU$k`vEie7;3E_s@Q8c zBD;@0jo3p=qF|Nof93Q9@X^}_YbJ%yGQFZA_6qOR>u8< zTDXGP^eVemmE1xoagqE<@Wa?`IAxzsgz_SvC>eK9mL;OJRywa-hwm%RovPxwdohb< pEXHN*3WrF!<)(D|ZOOKuS2B*w<^bPU{8WeFYDcONv{vGX{{sXa!A}4H diff --git a/pgworksheet_yvesf/locale/ja/LC_MESSAGES/pgworksheet.mo b/pgworksheet_yvesf/locale/ja/LC_MESSAGES/pgworksheet.mo deleted file mode 100644 index 2beed8722041864d36676256a1c9b527257854a8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcwPel00001 literal 5664 zcwVhmdr(x@89#|y1tP)%O`BGGTT8n{7ePy^M2!~l6(1<5owPGMm)!$wT=(L=7m?0% z#@+P^rco0_Bfe4}_yA+A3BI81WTw+;rqkrVwv*IY54L-{l2R@w2WY?Nb_D(3h zGtTT1UEU@`D-!0!NEP{t8#$qd@JVg{|R1C{~}pa*ykC_?-Qh^_478D#fQ!0!V8 z3Cse{$s)NMI15;vMe%RTBKy06-va&w_)Xwh;8NgV7TJH2MR|HAo6rS(0XP>}2wbk@ zwQBCqrnuXb{FKta2Fw9|m`!>7Bd`QG3|tG$&!O{P%OStLIpkje=mMHKwEsX3<^Q+kA{610praXrn1G9iLf$M=&fIn389|Q5nUdPY3pJA+3 zAm-gODWAWdNqPHtCh_G9;P-&ffi!c0D|3lI96uV+20jn$%q4$%b7|ji6#fPHRp38z zsZO~#qzw3?!XM3|d>oxcc|NajU>4Q=(^sd{nzuUSGyH*2Bdel) znr&#h=GSe#Ubi@;&25^+gJe-G+D%;Z1q03XhHm;<6)aD(yeeTQF-UQbtqNFbrZt$x zF1dB|;A+!E%n9vKqp)3URTf(-GBy~xU!FY5M&Y=wH6Sjw(J(nI!uBp*Rza8b zwqZ%ro123HpA@rAMuJtNBaw@ckhN? zb?LCp_u6SHGQFc0nX7v&IHvgnR&!8qV|8Ymx;lxArd!(5`sKy$7K@uD*3t#_%f+e` z`RkPc6q14_)QCiE8`POsHWHBpuWA;f1Fe>uXlHUQd99hZ+8@C0YT>naEe|&1SMl4s zNyL*RKJ#wI{Y)*5G&b7SQZ+M+C^ZFzu(mzGTUnB?|6{z#z9Vc0jYbwqy#_3;TZ3$` zL+n}S_iX2;g}YX%)vVdEdF!jSYpbj4wCtMAb)G8Oql}OTosd^*3(LwDdCDq03m0qU zWtEF6=9NJLMbB2mYo+N`c!cUpTG^t?g^TBvErH$!TsKdhsfVnfj%-$Hb-G`-ngZH- zW2fF2(3bLG19q0J5Mf)TmeFGRIEc~6OGDgVj{Tv=7QK;s>bSnEQd_S#>mhFO?2YR- zRwrX9FD=WiqU-FbYiou#f`bddtU%~xNj;0(%eK|6_AE~738&B;J&Es1rM9>}U}uXj zVr*ZB6Yd*6aCPY6J5KmU?9%OcXO|Pk-+=r*pQ3d4So~af=G+N)#2(##e14GBM=l-} z8h{k(s3}Wx!nfjG?~0RpPsO@>63eHZeUYL5_V}58C;UcI814|C;ivmpp6+7#(>yGn zz`+XmcWLOs<=7E8(HH;O<>B|=No$fg9vV(~zZ1SP@k0FMp;&L16X|iHcbv!_C;HHd z9&vlCOPCWqBxaF8Cwf{A?qQ=k=W)0{-hR%BoRC}I7R$n`D^BE=6TR+4qfWHTiFT7U zC)}Uh5IcOxiL}StyXpK1H;g@fGKYrxd&gbwa3V)=V*F$;OZoUC1O1~p!&Z!C0&gh6FJdiG6$Vb zO7us%rx0;+xdYKJJ>?aT4rUkZ(Zqw$jnwtx8QgIGuBq^d{WNK{31cHuTla2~!!uq?R^f8I)6xGs5;c`L@*Ge+Z9rp6@vQS22* zCAE*s)Z8LYvI&@)EY!#^V6uJa!6_$veDeQRoalbJ{RT@kioQh6dJ>`c#ojy_8|aGP zLEpJbO-DNU9x4H@IpOx$zyT+GQI0P-;Z8U&zBNwtth6mE3O{?D$a|7#7vSOW-N?}W zgDjmas9httHZ-vD-#Z9oOXer)O?` ziu$N!YCO_GO8r46(o39A-`Pi+Y~*6k@TL31Z}*4}FvsF;P$Q-f>R, YEAR. -# -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"POT-Creation-Date: 2008-10-26 17:34+CET\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FULL NAME \n" -"Language-Team: LANGUAGE \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=CHARSET\n" -"Content-Transfer-Encoding: ENCODING\n" -"Generated-By: pygettext.py 1.5\n" - - -#: ./pgw/ConnectDialog.py:66 -msgid "Open ConnectionParameter" -msgstr "" - -#: ./pgw/ConnectDialog.py:87 -msgid "Enter Connection details:" -msgstr "" - -#: ./pgw/ConnectDialog.py:90 -msgid "Local Connection" -msgstr "" - -#: ./pgw/ConnectDialog.py:91 -msgid "Network Connection" -msgstr "" - -#: ./pgw/ConnectDialog.py:99 -msgid "Session Name" -msgstr "" - -#: ./pgw/ConnectDialog.py:101 -msgid "Username" -msgstr "" - -#: ./pgw/ConnectDialog.py:103 ./pgw/UI.py:471 -msgid "Password" -msgstr "" - -#: ./pgw/ConnectDialog.py:105 ./pgw/UI.py:474 -msgid "Database" -msgstr "" - -#: ./pgw/ConnectDialog.py:107 ./pgw/UI.py:462 -msgid "Host" -msgstr "" - -#: ./pgw/ConnectDialog.py:109 ./pgw/UI.py:465 -msgid "Port" -msgstr "" - -#: ./pgw/ConnectDialog.py:131 -msgid "Last Connections" -msgstr "" - -#: ./pgw/ConnectDialog.py:137 -msgid "Connect" -msgstr "" - -#: ./pgw/ConnectDialog.py:142 -msgid "Cancel" -msgstr "" - -#: ./pgw/Notice.py:66 -msgid "Snippets" -msgstr "" - -#: ./pgw/QueryView.py:33 -msgid "Autocompletion" -msgstr "" - -#: ./pgw/QueryView.py:97 ./pgw/RunSQL.py:122 -msgid "Errors :" -msgstr "" - -#: ./pgw/QueryView.py:106 ./pgw/RunSQL.py:131 -msgid "No result" -msgstr "" - -#: ./pgw/QueryView.py:131 ./pgw/RunSQL.py:154 -msgid "query failed" -msgstr "" - -#: ./pgw/QueryView.py:139 ./pgw/RunSQL.py:162 -msgid "log" -msgstr "" - -#: ./pgw/QueryView.py:197 -msgid "Add" -msgstr "" - -#: ./pgw/ResultView.py:24 -msgid "Ansicht" -msgstr "" - -#: ./pgw/ResultView.py:46 -msgid "Tabellenansicht" -msgstr "" - -#: ./pgw/ResultView.py:155 -msgid "Persistent" -msgstr "" - -#: ./pgw/ResultView.py:159 -msgid "Close" -msgstr "" - -#: ./pgw/ResultView.py:207 ./pgw/ResultView.py:253 -msgid "No Title" -msgstr "" - -#: ./pgw/ResultView.py:269 -msgid "Error" -msgstr "" - -#: ./pgw/RunSQL.py:89 -msgid "Please wait, executing the query and fetching the results..." -msgstr "" - -#: ./pgw/UI.py:120 -msgid "Doing disconnect..." -msgstr "" - -#: ./pgw/UI.py:127 -msgid "Connection Failed:" -msgstr "" - -#: ./pgw/UI.py:134 -msgid "Connection Failed" -msgstr "" - -#: ./pgw/UI.py:225 -msgid "_Connect Server..." -msgstr "" - -#: ./pgw/UI.py:227 -msgid "_Disconnect" -msgstr "" - -#: ./pgw/UI.py:228 -msgid "Select _All" -msgstr "" - -#: ./pgw/UI.py:230 -msgid "Character _Encoding" -msgstr "" - -#: ./pgw/UI.py:231 -msgid "_About..." -msgstr "" - -#: ./pgw/UI.py:232 -msgid "_Connect" -msgstr "" - -#: ./pgw/UI.py:273 -msgid "_File" -msgstr "" - -#: ./pgw/UI.py:275 -msgid "Connect to a database" -msgstr "" - -#: ./pgw/UI.py:277 -msgid "Disconnect from the database" -msgstr "" - -#: ./pgw/UI.py:279 -msgid "Quit the Program" -msgstr "" - -#: ./pgw/UI.py:289 -msgid "PgWorksheet - PostgreSQL SQL Tool" -msgstr "" - -#: ./pgw/UI.py:435 -msgid "Database connection" -msgstr "" - -#: ./pgw/UI.py:447 -msgid "5 Previous connections" -msgstr "" - -#: ./pgw/UI.py:468 -msgid "User" -msgstr "" - -#: ./pgw/UI.py:543 -msgid "About PgWorksheet" -msgstr "" - -#: ./pgw/UI.py:575 -msgid "About" -msgstr "" - -#: ./pgw/UI.py:922 -msgid "License" -msgstr "" - -#: ./plugins/queryView/QueryViewNullPlugin.py:13 -msgid "Null Plugin" -msgstr "" - -#: ./plugins/resultView/ResultViewGraph.py:116 -msgid "Grafische Ansicht" -msgstr "" - -#: ./plugins/resultView/ResultViewNull.py:11 -msgid "Null View" -msgstr "" - -#: ./plugins/resultView/ResultViewSaveXML.py:25 -msgid "Als XML Speichern" -msgstr "" - -#: ./plugins/sidebar/FunctionBrowser.py:129 -#: ./plugins/sidebar/FunctionBrowser.py:144 ./plugins/sidebar/PgStats.py:150 -#: ./plugins/sidebar/PgStats.py:157 -msgid "All" -msgstr "" - diff --git a/pgworksheet_yvesf/pgw/ConnectDialog.py b/pgworksheet_yvesf/pgw/ConnectDialog.py deleted file mode 100644 index 143db4c..0000000 --- a/pgworksheet_yvesf/pgw/ConnectDialog.py +++ /dev/null @@ -1,271 +0,0 @@ -import pygtk -import gtk -import gettext; _ = gettext.gettext - -import ConfigParser -import pickle - -import pgw -from pgw.DBConnection import ConnectionParameter - -#TODO# from pgw.Widgets import LabeledEntry - - -class ListBox(gtk.ScrolledWindow): - def __init__(self, title, liststore): - gtk.ScrolledWindow.__init__(self) - - self.store = liststore - - self.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS) - self.set_shadow_type(gtk.SHADOW_NONE) - - self.view = gtk.TreeView(liststore) - - cell = gtk.CellRendererText() - column = gtk.TreeViewColumn(title) - column.pack_start(cell, True) - column.add_attribute(cell, 'text', 0) - column.set_sort_column_id(0) - self.view.append_column(column) - - self.add(self.view) - - def set_array(self, array): - self.store.clear() - for item in array: - self.store.append(item) - - def get(self): - tuple, treeview = self.view.get_cursor() - if tuple == None: - return None - return self.store[tuple[0]] - -class LabeledEntry(gtk.HBox): - def __init__(self, caption): - gtk.HBox.__init__(self) - self.entry = gtk.Entry() - self.label = gtk.Label(caption) - self.add(self.label) - self.add(self.entry) - - def connect(self, event, connection): - self.entry.connect(event, connection) - - def get_text(self): - return self.entry.get_text() - def grab_focus(self, eventFromWidget=None): - self.entry.grab_focus() - -class ConnectDialog(gtk.Window): - def __init__(self): - gtk.Window.__init__(self) - - self.set_modal(True) - self.set_title(_('Open ConnectionParameter')) - self.set_property("width-request", 620) - self.set_property("height-request", 400) - self.set_property("resizable", False) - - self.connection = ConnectionParameter(name="", user="", password="", db="", local=False, host="localhost", port="5432") - self.action_ok = None - - self.content = gtk.VBox() - - self.input = gtk.HBox() - self.input.set_homogeneous(True) - - self.bottom = gtk.HBox() - - self.left = gtk.VBox() - - self.right = gtk.VBox() - - -#Entrys - self.message = gtk.Label(_('Enter Connection details:')) - self.message.set_line_wrap(True) - - self.connect_style_local = gtk.RadioButton(group=None, label=_('Local Connection'), use_underline=True) - self.connect_style_network = gtk.RadioButton(group=self.connect_style_local, label=_('Network Connection'), use_underline=True) - - vbox = gtk.VBox() - vbox.add(self.message) - vbox.add(self.connect_style_local) - vbox.add(self.connect_style_network) - self.right.pack_start(vbox, expand=False, fill=False, padding=5) - - self.entry_name = LabeledEntry(_('Session Name')) - self.entry_name.entry.set_text(self.connection.name) - self.entry_user = LabeledEntry(_('Username')) - self.entry_user.entry.set_text(self.connection.user) - self.entry_password = LabeledEntry(_('Password')) - self.entry_password.entry.set_text(self.connection.password) - self.entry_db = LabeledEntry(_('Database')) - self.entry_db.entry.set_text(self.connection.db) - self.entry_host = LabeledEntry(_('Host')) - self.entry_host.entry.set_text(self.connection.host) - self.entry_port = LabeledEntry(_('Port')) - self.entry_port.entry.set_text(self.connection.port) - - entrys = [self.entry_name, self.entry_user, self.entry_password, self.entry_db, self.entry_host, self.entry_port] - for widget in entrys: - self.right.add(widget) - widget.connect("key-press-event", self.on_change) - try: - widget.connect("activate", entrys[entrys.index(widget) + 1].grab_focus) - except IndexError: - pass #last elem - - - - - self.connect_style_local.connect("toggled", self.on_change) - self.connect_style_network.connect("toggled", self.on_change) - self.connect_style_local.set_active(False) - self.connect_style_network.set_active(True) - - - # - self.listbox = ListBox(_('Last Connections'), gtk.ListStore( str, pgw.GObjectContainer )) - self.listbox.set_array([['Foo', pgw.GObjectContainer(ConnectionParameter("yvesf", "iii"))],["blafoo", pgw.GObjectContainer(ConnectionParameter("yvesf", "iii"))]]) - self.listbox.view.connect('cursor-changed', self.on_cursor_changed) - self.left.pack_start(self.listbox,True,True) - - # - button_connect = gtk.Button(_('Connect')) - button_connect.connect("clicked", self.on_clicked_ok) - button_connect.set_property("height-request", 45) - button_connect.set_property("width-request", 150) - - button_cancel = gtk.Button(_('Cancel')) - button_cancel.connect("clicked", self.on_clicked_cancel) - button_cancel.set_property("height-request", 45) - button_cancel.set_property("width-request", 150) - - self.bottom.pack_start(button_connect, True, False) - self.bottom.pack_start(button_cancel, True, False) - - self.input.add(self.left) - self.input.add(self.right) - self.content.pack_start(self.input) - self.content.pack_start(self.bottom, False, False) - self.add(self.content) - - self.on_change()#Check UI - self.entry_name.grab_focus() - - def set_error(self, message): - self.message.set_markup(message) - - def on_clicked_ok(self, widget): - cp = ConfigParser.ConfigParser() - try: - cp.readfp(open(pgw.get_config_path(), 'r')) - except IOError: - return - try: - if not cp.has_section("connection"): - cp.add_section("connection") - cp.set("connection", "connection", pickle.dumps([])) - except: - pass - - if self.action_ok: - return_value = self.action_ok(self, self.connection) - if return_value == True: - self.destroy() - else: - return - - def on_clicked_cancel(self, widget): - self.destroy() - - def on_cursor_changed(self, widget=None): - pass - - def on_change(self, widget=None, event=None): - """The User entered some new values in any widget""" - self.connection.name = self.entry_name.get_text() - self.connection.user = self.entry_user.get_text() - self.connection.password = self.entry_password.get_text() - self.connection.db = self.entry_db.get_text() - if self.connect_style_local.get_active(): #Lokale Verbindung - self.entry_host.hide() - self.entry_port.hide() - self.connection.local = True - self.connection.host = "" - self.connection.port = "" - elif self.connect_style_network.get_active(): - self.entry_host.show() - self.entry_port.show() - self.connection.local = False - self.connection.host = self.entry_host.get_text() - self.connection.port = self.entry_port.get_text() - else: - raise Exception("Something strange happen ;)") - - - def show(self): - self.show_all() - - def connect(self, event, conn): - if event == "clicked-ok": - self.action_ok = conn - else: - super.connect(event, conn) - - def on_dlgconnect_change(self, treeview): - """Called when the user choose a connection in the connection history list""" - # fill the connection dialog with the selected connection parameters - model, iter = treeview.get_selection().get_selected() - host, port, db, user = string.split(model.get(iter, 1)[0], ',') - self.ui.entry_host.set_text(host) - self.ui.entry_port.set_text(port) - self.ui.entry_database.set_text(db) - self.ui.entry_user.set_text(user) - self.ui.entry_password.set_text('') - - def on_dlgconnect_map(self, widget): - """Called when the connection dialog box is displayed""" - # load the connections history from the config file - cp = ConfigParser.ConfigParser() - try: - cp.readfp(open(pgw.get_config_path(), 'r')) - except IOError: - return - try: - pickled = cp.get("connection", "pickled") - old_connections = pickle.loads(pickled) - self.listbox.set_array(old_connections) - except: - if not cp.has_section("connection"): - cp.add_section("connection") - cp.set("connection", "connection", pickle.dumps([])) - - - - -if __name__ == "__main__": - import thread - import time - window = ConnectDialog() - def test(foo): - print "Hello" - print "Hello donw" - try: - print window.run() - time.sleep(1) - except Exception, err: - print err - #finally: - # import sys - ## gtk.main_quit() - # sys.exit(1) - thread.start_new_thread(test, ("foo",)) - - #thread.start_new_thread(gtk.main, ()) - - time.sleep(100) - diff --git a/pgworksheet_yvesf/pgw/DBConnection.py b/pgworksheet_yvesf/pgw/DBConnection.py deleted file mode 100644 index de5e439..0000000 --- a/pgworksheet_yvesf/pgw/DBConnection.py +++ /dev/null @@ -1,121 +0,0 @@ -# -*- coding: latin-1; -*- -# -# PgWorksheet - PostgreSQL Front End -# http://pgworksheet.projects.postgresql.org/ -# -# Copyright © 2004-2005 Henri Michelon & CML http://www.e-cml.org/ -# -# 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 (read LICENSE.txt). -# -# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# $Id: DBConnection.py,v 1.20 2005/03/01 16:09:57 hmichelon Exp $ -# -import string -import sys -#from mx import DateTime -from pyPgSQL import libpq -from pyPgSQL import PgSQL - -class ConnectionParameter: - def __init__(self, name="", user="", password="", db="", local=False, host="", port="5432"): - self.name = name - - self.user = user - self.password = password - self.db = db - - self.local = local - - self.host = host - self.port = port - - def get_dsn(self): - dsn = "" - if (self.host is not None): - dsn = self.host - - dsn = dsn + ":" - - if (self.port is not None): - dsn = dsn + str(self.port) - - dsn = dsn + ":" - - if (self.db is not None): - dsn = dsn + self.db - - dsn = dsn + ":" - - if (self.user is not None): - dsn = dsn + self.user - - dsn = dsn + ":" - if (self.password is not None): - dsn = dsn + self.password - - return dsn - def dump(self): - print "NAME=%s : user=%s, password=%s, db=%s, local=%s, host=%s, port=%s"%(self.name, self.user, self.password, self.db, self.local, self.host, self.port) - - -DatabaseError = libpq.DatabaseError - -class DBConnection: - """Database connection/deconnection and query execution""" - - def __init__(self): - self.db = None - - def connect(self, connectionParameter): - """Try to connect to a database""" - self.connectionParameter = connectionParameter - #self.db = MyPgSQL.connect(dsn) #delete see svn history for MyPgSQL.py. i dunno why this was necessary - self.db = PgSQL.connect(connectionParameter.get_dsn()) - self.db.autocommit = 1 - return self.db - - - def pgversion(self): - if (self.is_connected()): - v = string.split(str(self.db.version), ',') - return v.pop(0) - return '' - - - def query(self, sql): - """Execute a query and return the corresponding DB-API cursor.""" - if not self.is_connected() : return None - cursor = self.db.cursor() - try: - cursor.execute("SET CLIENT_ENCODING TO 'UTF-8'") - cursor.execute(sql) - except libpq.OperationalError, msg: - cursor.close() - return { 'error' : str(msg), 'notices' : self.db.notices } - return { 'cursor' : cursor, 'notices' : self.db.notices } - - - def commit(self): - if not self.is_connected() : return - self.db.commit() - - - def is_connected(self): - return (self.db != None) - - - def disconnect(self): - if not self.is_connected() : return - self.db.close() - self.db = None diff --git a/pgworksheet_yvesf/pgw/Execute.py b/pgworksheet_yvesf/pgw/Execute.py deleted file mode 100644 index c131562..0000000 --- a/pgworksheet_yvesf/pgw/Execute.py +++ /dev/null @@ -1,136 +0,0 @@ -# -*- coding: latin-1; -*- -# -# PgWorksheet - PostgreSQL Front End -# http://pgworksheet.projects.postgresql.org/ -# -# Copyright © 2004-2005 Henri Michelon & CML http://www.e-cml.org/ -# -# 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 (read LICENSE.txt). -# -# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# $Id: Execute.py,v 1.26 2005/06/10 12:54:30 hmichelon Exp $ -# -import os -import sys -import popen2 -import string -import gtk - -import pgw -import pgw.Lexical - - -class Execute: - """SQL query and psql commands handling""" - - - def __init__(self, db): - self.db = db - self.lexical = pgw.Lexical.Lexical() - - - def execute_one(self, sql): - """Execute one query""" - if (len(sql) > 0) : - # psql commands - if (sql[0] == '\\'): - sql = string.replace(sql, '\\\\', '\\') - if (pgw.mswindows()): - cmd = "psql.exe" - sql = string.strip(sql) - else: - cmd = "psql" - if (self.db.user is not None): - cmd += ' -U "' + self.db.user + '"' - if (self.db.host is not None): - cmd += ' -h "' + self.db.host + '"' - if (self.db.port is not None): - cmd += ' -p ' + self.db.port - if (self.db.database is not None): - cmd += ' -d "' + self.db.database + '"' - cmd += ' -c "' + sql + '"' - if (self.db.password is not None): - os.putenv("PGPASSWORD", self.db.password) - #os.putenv("PGCLIENTENCODING", pgw.get_user_encoding()) - output, input = popen2.popen4(cmd) - result = output.read() - output.close() - input.close() - #os.putenv("PGCLIENTENCODING", "") - os.putenv("PGPASSWORD", "") - return { 'text' : result } - else: - # SQL query - return self.db.query(sql) - - - def execute(self, sql): - """Execute SQL queries or psql commands""" - if not self.db.is_connected() : return - # SQL query - sqls = self.split(sql) - if (len(sqls) > 1): - # multiple queries - results = [] - for sql in sqls: - sql = string.strip(sql) - if (len(sql) > 0): - results.append(self.execute_one(sql)) - if (len(results) == 1): - return results[0] - return results - else: - # unique query - return self.execute_one(sqls[0]) - - - def split(self, oldsql): - """Split multiple queries""" - # a new textbuffer, because we don't want to modify the original - buffer = gtk.TextBuffer() - buffer.set_text(oldsql) - - # filter comments - tokens = self.lexical.analyse(buffer, buffer.get_start_iter(), - buffer.get_end_iter()) - for token in tokens: - if (token.token == 'comment'): - buffer.delete(token.start_iter, token.end_iter) - - # restart without the comments - buffer.set_text(buffer.get_text(buffer.get_start_iter(), - buffer.get_end_iter())) - start = buffer.get_start_iter() - end = buffer.get_end_iter() - tokens = self.lexical.analyse(buffer, start, end) - - # create a list of queries - sql = buffer.get_text(start, end) - parts = [] - stop = start - while (len(tokens) > 0): - token = tokens.pop(0) - if (token.token == 'psql'): - i = token.start_iter - i.backward_char() - parts.append(buffer.get_text(stop, i)) - parts.append(token.value) - stop = token.end_iter - elif (token.value == ';'): - i = token.start_iter - parts.append(buffer.get_text(stop, i)) - stop = token.end_iter - if (stop != end): - parts.append(buffer.get_text(stop, end)) - return parts diff --git a/pgworksheet_yvesf/pgw/Lexical.py b/pgworksheet_yvesf/pgw/Lexical.py deleted file mode 100644 index ea1c038..0000000 --- a/pgworksheet_yvesf/pgw/Lexical.py +++ /dev/null @@ -1,357 +0,0 @@ -#!/usr/bin/env python -# -*- coding: latin-1; -*- -# -# PgWorksheet - PostgreSQL Front End -# http://pgworksheet.projects.postgresql.org/ -# -# Copyright © 2004-2005 Henri Michelon & CML http://www.e-cml.org/ -# -# 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 (read LICENSE.txt). -# -# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# $Id: Lexical.py,v 1.6 2005/10/25 17:31:24 hmichelon Exp $ -# - -# http://www.postgresql.org/docs/8.0/static/sql-syntax.html - -# basic characters sets -SPACES = [ ' ', '\t', '\n' ] -DIGITS = [ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9' ] -NUMERIC = DIGITS + [ 'e', '.', '+', '-' ] -OPERATOR_CHARS = [ '+', '-', '*', '/', '<', '>', '=', '~', '!', \ - '@', '#', '%', '^', '&', '|', '`', '?' ] -SPECIAL_CHARS = [ '(', ')', '[', ']', ',', ';', ':', '*', '.' ] -OPERATORS = OPERATOR_CHARS + SPECIAL_CHARS - -# not the first character of an identifier -NOT_IDENT_START = SPECIAL_CHARS + OPERATOR_CHARS + DIGITS + [ '$' ] -# not a character of an identifier -NOT_IDENT_CHAR = SPECIAL_CHARS + OPERATOR_CHARS + SPACES + [ "'" ] -# not a character of a dollar quoted string -NOT_DOLLAR_QUOTED = [ '$' ] + SPACES - - -class Token: - - def __init__(self, token, start_iter, end_iter, value=None): - self.token = token - self.start_iter = start_iter - self.end_iter = end_iter - self.value = value - - -class Eob: - """End of Buffer Exception""" - - -class Lexical: - """Simplified lexical analyser""" - - def analyse(self, buffer, start, end): - """Run the lexical and syntaxical analysers then - apply the syntax highlight to the buffer""" - self.buffer = buffer - self.current = start.copy() - self.tokens = []; - try: - self.lexical_analyser(end.copy()) - except Eob: - pass - return self.tokens - - - def next_char(self): - """Returns the next character to analyse""" - if (self.current.is_end()): - raise Eob() - c = self.current.get_char() - self.current.forward_char() - return c - - - def skip_spaces(self, c): - """Skips everything that looks like a space/tab/etc...""" - while (c in SPACES): - c = self.next_char() - return c - - - def string(self): - """Single quoted strings""" - start = self.current.copy() - start.backward_char() - prev = None - c = self.next_char() - try: - while (True): - if ((c == "'") and (prev != '\\')): # a single quote in the string... - c = self.next_char() - if (c != "'"): - break - prev = c - c = self.next_char() - except Eob: - end = self.current.copy() - self.tokens.append(Token('string', start, end)) - raise - end = self.current.copy() - end.backward_char() - self.tokens.append(Token('string', start, end)) - return c - - - def dollar_string(self): - """Dollar-quoted strings""" - # first bound - start = self.current.copy() - start.backward_char() - c = self.next_char() - string_tag = '' - try: - while (c not in NOT_DOLLAR_QUOTED): - string_tag = string_tag + c - c = self.next_char() - except Eob: - end = self.current.copy() - self.tokens.append(Token('identifier', start, end, string_tag.upper())) - raise - end = self.current.copy() - end.backward_char() - if (c != '$'): - self.tokens.append(Token('identifier', start, end, string_tag.upper())) - return c - self.tokens.append(Token('dollarquote', start, end, string_tag.upper())) - - # string content - start = self.current.copy() - try: - c = self.next_char() - except Eob: - end = self.current.copy() - self.tokens.append(Token('identifier', start, end, string_tag.upper())) - raise - try: - while (True): - if (c == '$'): - string_end = self.current.copy() - c = self.next_char() - s = '' - while (c not in NOT_DOLLAR_QUOTED): - s = s + c - c = self.next_char() - if (s == string_tag): - string_end.backward_char() - self.tokens.append(Token('string', start, string_end)) - end = self.current.copy() - end.backward_char() - self.tokens.append(Token('dollarquote', start, end, s.upper())) - return c - else: - c = self.next_char() - except Eob: - end = self.current.copy() - self.tokens.append(Token('string', start, end)) - raise - end = self.current.copy() - end.backward_char() - self.tokens.append(Token('string', start, end)) - return c - - def bit_string_constant(self, start): - """Binary and Hexadecimal numeric constants using strings""" - c = self.next_char() - if (c == "'"): - c = self.next_char() - start = self.current.copy() - start.backward_char() - start.backward_char() - start.backward_char() - while (c != "'"): - c = self.next_char() - end = self.current.copy() - self.tokens.append(Token('numeric_constant', start, end)) - return self.next_char() - else: - return self.identifier(c, start) - - - def identifier(self, c, ident = ''): - """An identifier, keyword, type name, etc...""" - start = self.current.copy() - for i in range(0, len(ident) + 1): - start.backward_char() - try: - while (c not in NOT_IDENT_CHAR): - ident = ident + c - c = self.next_char() - except Eob: - end = self.current.copy() - self.tokens.append(Token('identifier', start, end, ident.upper())) - raise - end = self.current.copy() - end.backward_char() - self.tokens.append(Token('identifier', start, end, ident.upper())) - return c - - - def numeric(self, c): - """A numeric constant""" - start = self.current.copy() - start.backward_char() - try: - while (c in NUMERIC): - c = self.next_char() - except Eob: - end = self.current.copy() - self.tokens.append(Token('numeric_constant', start, end)) - raise - end = self.current.copy() - end.backward_char() - self.tokens.append(Token('numeric_constant', start, end)) - return c - - - def simple_comment(self): - """One line comment using --""" - start = self.current.copy() - start.backward_char() - start.backward_char() - c = self.next_char() - try: - while (c != '\n'): - c = self.next_char() - except Eob: - end = self.current.copy() - self.tokens.append(Token('comment', start, end)) - raise - end = self.current.copy() - self.tokens.append(Token('comment', start, end)) - - - def comment(self): - """Multi lines comments using /* */""" - start = self.current.copy() - start.backward_char() - start.backward_char() - c = self.next_char() - prev = None - nested = 0 - try: - while (True): - if (c == '*'): - c = self.next_char() - if (prev == '/'): - nested = nested + 1 - continue - if (c == '/'): - if (nested == 0): - c = self.next_char() - break - else: - nested = nested - 1 - else: - prev = c - continue - prev = c - c = self.next_char() - except Eob: - end = self.current.copy() - self.tokens.append(Token('comment', start, end)) - raise - end = self.current.copy() - end.backward_char() - self.tokens.append(Token('comment', start, end)) - return c - - - def psql(self): - """A PgSQL Command""" - start = self.current.copy() - start.backward_char() - c = self.next_char() - cmd = '\\' - try: - while (c != '\n') and (c != ';'): - cmd = cmd + c - c = self.next_char() - except: - end = self.current.copy() - self.tokens.append(Token('psql', start, end, cmd)) - raise - end = self.current.copy() - self.tokens.append(Token('psql', start, end, cmd)) - - - def lexical_analyser(self, fin): - """A simplified lexical analyser""" - c = self.next_char() - while (self.current.compare(fin) <= 0): - c = self.skip_spaces(c) - # Multi lines comments - if (c == '/'): - c = self.next_char() - if (c == '*'): - c = self.comment() - continue - else: - self.current.backward_char() - # One line comments - elif (c == '-'): - c = self.next_char() - if (c == '-'): - self.simple_comment() - else: - self.current.backward_char() - # psql commands - elif (c == '\\'): - self.psql() - # numeric - elif (c in DIGITS): - c = self.numeric(c) - continue - # bit strings - elif (c == 'B') or (c == 'b') or (c == 'H') or (c == 'h'): - c = self.bit_string_constant(c) - continue - # strings - elif (c == "'"): - c = self.string() - continue - # dollar-quoted strings - elif (c == '$'): - c = self.dollar_string() - continue - # numeric - elif (c == '.'): - c = self.next_char() - if (c in DIGITS): - self.current.backward_char() - c = self.numeric(self.current.get_char()) - continue - # quoted identifiers - elif (c == '"'): - c = self.next_char() - while (c != '"'): - c = self.next_char() - # operators - elif (c in OPERATORS): - start = self.current.copy() - start.backward_char() - end = self.current.copy() - self.tokens.append(Token('operator', start, end, c)) - # everything else - elif (c not in NOT_IDENT_START): - c = self.identifier(c) - continue - c = self.next_char() diff --git a/pgworksheet_yvesf/pgw/Notice.py b/pgworksheet_yvesf/pgw/Notice.py deleted file mode 100644 index b107b9f..0000000 --- a/pgworksheet_yvesf/pgw/Notice.py +++ /dev/null @@ -1,262 +0,0 @@ -# -*- coding: latin-1; -*- -# -# Snippet Extension to pgw -# Copyright © 2007 Yves Fischer, yvesf at xapek org -# -# 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 (read LICENSE.txt). -# -# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# -# - -import pygtk; -import gtk; -import ConfigParser; - -import pgw; - -class NoticeWidget(gtk.VBox): - def __init__(self, sqlview): - gtk.VBox.__init__(self); - self.set_property("width-request", 150); - self.sqlview = sqlview; - - self.snippets = []; - - #Create Widgets - self.h = gtk.HBox(homogeneous=False, spacing=2); - - self.h_b_hide = gtk.Button(">"); - self.h_b_hide.connect("pressed", self.hide_snippets) - self.h.add(self.h_b_hide) - - self.h_b_add = gtk.Button("Add Snippet"); - self.h_b_add.connect('pressed', self.button_add); - self.h.add(self.h_b_add); - - self.h_b_del = gtk.Button("Del Snippet"); - self.h_b_del.connect("pressed", self.button_del); - self.h.add(self.h_b_del); - - self.pack_start(self.h, expand=False, fill=True, padding=0); - - self.vpane = gtk.VPaned(); - #Listbox - scroll = gtk.ScrolledWindow() - scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - scroll.set_property("height-request", 100) - scroll.set_shadow_type(gtk.SHADOW_NONE) - - self.storeconn = gtk.ListStore(str, str); - self.viewconn = gtk.TreeView(self.storeconn); - self.viewconn.connect("cursor-changed", self.treeview_cursor) - - cell = gtk.CellRendererText() - column = gtk.TreeViewColumn(_('Snippets')) - column.pack_start(cell, True) - column.add_attribute(cell, 'text', 0) - column.set_sort_column_id(0) - self.viewconn.append_column(column) - - scroll.add(self.viewconn) - self.vpane.pack1(scroll, True, False); - - #sql-snippet view - scroll2 = gtk.ScrolledWindow() - scroll2.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - scroll2.set_property("height-request", 30) - scroll2.set_shadow_type(gtk.SHADOW_NONE) - self.sqlbuffer = gtk.TextBuffer() - self.sqlbuffer.connect("modified-changed", self.sqlbuffer_modified) - self.syntax = pgw.Syntax.Syntax(self.sqlbuffer) - - self.sqlbuffer.connect('delete-range', self.syntax.text_deleted) - self.sqlbuffer.connect('insert-text', self.syntax.text_inserted) - self.sqlbuffer.connect('changed', self.syntax.text_changed) - - - self.snippetview = gtk.TextView(self.sqlbuffer) - - scroll2.add(self.snippetview) - self.vpane.add2(scroll2); - - self.add(self.vpane) - self.vpane.set_position(50) - - #Save Changes Button - self.h2 = gtk.HBox() - self.h2.set_property("height-request",35); - - self.h2_b_save_changes = gtk.Button("Save Changes"); - self.h2_b_save_changes.connect("pressed", self.sqlbuffer_save_changes) - self.h2.add(self.h2_b_save_changes); - - - self.read_snippets() - self.set_snippets(); - self.sqlbuffer.set_text("Click on a Snippet to see it here!") - self.sqlbuffer.set_modified(False) - self.h2_b_save_changes.set_property("visible", False); - - def sqlbuffer_save_changes(self, widget, data=None): - tuple, treeview = self.viewconn.get_cursor() - if tuple == None: #No entry selected->New snipped (can only happen after start) - dialog = self.GtkInputDialog("Snippet Name?"); - dialog.connect_ok(self.sqlbuffer_save_changes_addNew); - dialog.connect_validation(self.add_validation); - dialog.show_all(); - self.sqlbuffer.set_modified(False) - return - - index = tuple[0] - self.snippets[index][1] = self.sqlbuffer.get_text(self.sqlbuffer.get_start_iter(), self.sqlbuffer.get_end_iter()) - self.save_snippets() - self.sqlbuffer.set_modified(False) - - def sqlbuffer_save_changes_addNew(self, text): - self.snippets.append([text, self.sqlbuffer.get_text(self.sqlbuffer.get_start_iter(), self.sqlbuffer.get_end_iter())]) - self.save_snippets() - self.set_snippets() - self.viewconn.set_cursor(self.storeconn.get_path( self.storeconn.get_iter_first())); - - - - def sqlbuffer_modified(self, sqlbuffer): - if sqlbuffer.get_modified(): - self.pack_end(self.h2, expand=False, fill=True, padding=0) - self.h2.show_all() - else: - self.remove(self.h2) - - def hide_snippets(self, widget, data=None): - self.get_parent().set_property("position-set", True) - self.get_parent().set_property("position", self.get_parent().get_property("max-position")) - - def add_validation(self, text): - if text == "": - return False - else: - return True - - def treeview_cursor(self, treeview): - tuple, treeview = self.viewconn.get_cursor() - snippet = self.snippets[tuple[0]][1] - self.sqlbuffer.set_text(snippet) - self.sqlbuffer.set_modified(False) - - - def button_add(self, widget, data=None): - dialog = self.GtkInputDialog("Snippet Name?"); - dialog.connect_ok(self.button_add2); - dialog.connect_validation(self.add_validation); - dialog.show_all(); - def button_add2(self, text): - self.snippets.append([text, self.sqlview.get_text(self.sqlview.get_start_iter(), self.sqlview.get_end_iter())]) - self.save_snippets() - self.set_snippets() - self.viewconn.set_cursor(self.storeconn.get_path( self.storeconn.get_iter_first())); - - def button_del(self, widget, data=None): - tuple, treeview = self.viewconn.get_cursor() - if tuple == None: #nothin selected - return - self.snippets.pop(tuple[0]) - self.save_snippets(); - self.set_snippets(); - - - #saves Array self.snippets to pgworksheet Config - def save_snippets(self): - print "Save Snippets" - cp = ConfigParser.ConfigParser(); - try: - cp.readfp(open(pgw.get_config_path(), 'r')); - except IOError: - print "IOerror ;) Cant save Snippets :("; - return #go home - - if (not cp.has_section("snippets")): - cp.add_section("snippets"); - else: #um alte einträge zu entfenerne - cp.remove_section("snippets") - cp.add_section("snippets") - n = 1 - for snippet in self.snippets: - cp.set("snippets", "snippet%d_name" % n, snippet[0]) - cp.set("snippets", "snippet%d_content" % n, snippet[1]) - n += 1 - print "%d Snippets saved" % (n-1) - cp.write(open(pgw.get_config_path(), 'w')) - - def read_snippets(self): - cp = ConfigParser.ConfigParser(); - try: - cp.readfp(open(pgw.get_config_path(), 'r')); - except IOError: - print "IOerror ;) therefore no snippets :("; - return; - n = 1 - while 1==1: - try: - snippet_content = cp.get("snippets", \ - "snippet"+str(n)+"_content") - snippet_name = cp.get("snippets", ("snippet%d_name" % n)) - self.snippets.append([snippet_name, snippet_content]) - n += 1 - except Exception, inst: - print "%d snippets read" % (n-1) - break - def set_snippets(self): - self.storeconn.clear() - for snippet in self.snippets: - self.storeconn.append(snippet) - - class GtkInputDialog(gtk.Dialog): - def __init__(self, title=None, parent=None, flags=0, buttons=None): - gtk.Dialog.__init__(self, title, parent, flags, buttons); - - self.entry = gtk.Entry() - self.entry.connect("activate", self.pressed_ok) - - self.vbox.add(self.entry) - - self.button_ok = gtk.Button("OK") - self.vbox.add(self.button_ok) - self.button_ok_action = lambda x:() - self.button_ok.connect("pressed", self.pressed_ok) - - self.button_cancel = gtk.Button("Cancel") - self.vbox.add(self.button_cancel) - self.button_cancel_action = lambda x:() - self.button_cancel.connect("pressed", self.pressed_cancel) - - self.validation_action = lambda x:() - - def connect_ok(self, connection): - self.button_ok_action = connection - - def connect_cancel(self, connection): - self.button_ok_cancel = connection - def connect_validation(self, connection): - self.validation_action = connection - - def pressed_ok(self, widget, data=None): - if self.validation_action(self.entry.get_text()): - self.button_ok_action(self.entry.get_text()) - self.destroy() - def pressed_cancel(self, widget, data=None): - self.button_cancel_action(self.entry.get_text()) - self.destroy() - - diff --git a/pgworksheet_yvesf/pgw/Plugin.py b/pgworksheet_yvesf/pgw/Plugin.py deleted file mode 100644 index 4ed6d92..0000000 --- a/pgworksheet_yvesf/pgw/Plugin.py +++ /dev/null @@ -1,111 +0,0 @@ -# -*- coding: utf-8; -*- - -#This Class contains Code from http://cheeseshop.python.org/pypi/sprinkles -# License :: OSI Approved :: MIT License -# Author: Andy Smith -# Home Page: http://an9.org/w/SprinklesPy -# License: MIT License - -import pygtk; -import gtk; -import imp; -import os - -#Prototype, subclass it to creat a Plugin -class SidebarPlugin(gtk.VBox): - name = "Default Name, forgot to set it?" - def __init__(self, ui): - gtk.VBox.__init__(self) - self.db = ui.db - self.ui = ui - def on_init(self): - pass #to be overwritten - def on_connection(self): - pass #to be used also - -class ResultViewPlugin(gtk.HBox): - name = "Default Name" - def __init__(self, ui, result): - gtk.HBox.__init__(self) - self.ui = ui - self.result = result - - def update(self): - raise Exception( "Plugin:: update() should be overwritten" ) - - def on_init(self): - print "on_init should be overwritten" - -class QueryViewPlugin(gtk.HBox): - name = "Default Name" - def __init__(self, db, result): - gtk.HBox.__init__(self) - self.db = db - self.result = result - - -def get_files(path): - ret = [] - for root, dirs, files in os.walk(path, topdown=False): - for file in files: - if not str(file).startswith(".") and str(file).endswith(".py"): - ret.append(os.path.join(root, file)) - return ret - -def fromPath(path, subclass=None): - def filterer(item): - return issubclass(item, subclass) - - print "Plugins: "+'Looking for sprinkles in path: %s...'%(path) - o = [] - - files = get_files(path) - for f in files: - print "Plugins: "+'Found file: %s'%(f) - loaded = fromFile(os.path.dirname(f), os.path.basename(f)) - o = o + loaded - if subclass: - print "Plugins: "+'Filtering with %s'%(subclass) - o = filter(filterer, o) - print "Plugins: Passed: %s"%(o) - return o - -def fromFile(path, filename, filterer=None): - o = [] - mod_name = os.path.splitext(filename)[0] - new_mod = None - try: - fp, pathname, desc = imp.find_module(mod_name,[path]) - try: - new_mod = imp.load_module(mod_name,fp,pathname,desc) - print "Plugins: "+'Loaded: %s'%(new_mod) - finally: - if fp: fp.close() - except ImportError, err: - print "Plugins: "+'Failed to import %s, %s'%(mod_name, err) - if not new_mod: - return [] - o = fromModule(new_mod) - if filterer: - o = filter(filterer, o) - return o - -def fromModule(mod, filterer=None): - o = [] - if type(mod) is type(""): - mod = _import(mod) - if hasattr(mod, "EXPORTS"): - s = getattr(mod, "EXPORTS") - else: - #s = [getattr(mod, x) for x in dir(mod)] - s=[] - #s = filter(lambda _: (type(_) is type(object)), s) - #o = filter(SidebarPlugin.implementedBy, s) - #TODO - #print "Plugins: "+"Found sprinkles: %s"%(o) -# if filterer: - # print "Plugins: "+'Filtering %s with %s'%(o, filterer) - # o = filter(filterer, o) - return s - - diff --git a/pgworksheet_yvesf/pgw/QueryView.py b/pgworksheet_yvesf/pgw/QueryView.py deleted file mode 100644 index b9a791e..0000000 --- a/pgworksheet_yvesf/pgw/QueryView.py +++ /dev/null @@ -1,223 +0,0 @@ -import sys -import string -import pygtk; -import gtk; -import gettext - -import pgw -import pgw.Plugin -import pgw.Syntax -import pgw.Undo -import pgw.Execute -import pgw.RunSQL; -import pgw.Widgets -import pgw.ResultView - -_ = gettext.gettext - -class QueryViewSQLEditor(pgw.Plugin.QueryViewPlugin): - name = "SQL Editor" - def __init__(self,db,result): - pgw.Plugin.QueryViewPlugin.__init__(self,db,result) - self.content = gtk.VBox() - - - - self.toolbar = gtk.Toolbar() - self.toolbar.set_style(gtk.TOOLBAR_BOTH) - self.toolbar.set_property("height-request", 55) - self.tb_run = gtk.ToolButton(None, "Run SQL") - self.tb_run.set_stock_id(gtk.STOCK_EXECUTE) - self.tb_run.connect("clicked", self.on_run) - self.tb_completion = gtk.ToggleToolButton() - self.tb_completion.set_label(_('Autocompletion')) - self.tb_completion.set_stock_id(gtk.STOCK_ADD) - self.tb_completion.set_active(True) - self.tb_completion.connect("toggled", self.on_toggle_autocompletion) - - - self.toolbar.insert(self.tb_completion, 0) - self.toolbar.insert(self.tb_run, 0) - self.content.pack_start(self.toolbar, False, False) - - self.sqltextview = pgw.Widgets.SQLTextView(self.db) - - self.content.add(self.sqltextview) - - self.add(self.content) - - def on_toggle_autocompletion(self, widget): - self.sqltextview.enable_completion = widget.get_active() - - def on_run(self, widget=None): - if not self.db.is_connected: - return - - # clear the treeviews and the error text buffers - #self.result.clear() - - print "Please wait, executing the query and fetching the results..." - # update the display - while (gtk.events_pending() == True): - gtk.main_iteration_do(False) - - # execute the query - sql = self.sqltextview.buffer.get_text(self.sqltextview.buffer.get_start_iter(), self.sqltextview.buffer.get_end_iter()) - - execute = pgw.Execute.Execute(self.db) - - notices = [] - try: - result = execute.execute(sql) - rows = 0 - if (isinstance(result, list)): - # multiple queries and multiple results... - parts = execute.split(sql) - sqls = [] - have_errors = 0 - for sql in parts : - sql = string.strip(sql) - if (len(sql) > 0) : - sqls.append(sql) - for res in result: - sql = sqls.pop(0) - try: - if (res['cursor'].description is not None): - result = pgw.RunSQL.Result(sql, res['cursor']) - self.result.add_results(result) - #self.fill_treeview(sql, res['cursor']) - rows += res['cursor'].rowcount - notices = res['notices'] - except KeyError: - try: - self.result.add_error(res['text'], "psql : " + sql) - except KeyError: - notices = res['notices'] - self.result.add_error(res['error'], - '' + _('Errors :') + ' ' + - sql) - have_errors += 1 - #self.result.set_current_page(0) - else: # one query - sql = self.sqltextview.buffer.get_text(self.sqltextview.buffer.get_start_iter(), - self.sqltextview.buffer.get_end_iter()) - try: - if (result is None): - self.result.add_error(_("No result")) - elif (result['cursor'].description is None): - # not a SELECT - rows = result['cursor'].rowcount - notices = result['notices'] - else: - # only one SELECT - result = pgw.RunSQL.Result(sql, result['cursor']) - self.result.add_results(result) - - #notices = result['notices'] # for what??? - except KeyError: - try: - self.result.add_error(result['text'], "psql : " + sql) - except KeyError: - self.result.add_error(result['error']) - notices = result['notices'] - - buffer = self.sqltextview.buffer - buffer.move_mark_by_name('selection_bound', buffer.get_start_iter()); - buffer.move_mark_by_name('insert', buffer.get_end_iter()); - - except Exception, errstr: - import traceback - info= sys.exc_info() - self.result.add_error('' + _('query failed') + '') - self.result.add_error("Fehler %s in line %d"%(str(errstr), traceback.tb_lineno(info[2]) )) - traceback.print_tb(info[2]) - - if (len(notices) > 0): - msg = "" - while len(notices): - msg += notices.pop() - self.result.add_error(msg, ''+ _("log") + '') - - #self.result("") - # restore the focus - self.sqltextview.textview.grab_focus() - for page in self.result.get_children(): - if isinstance(page, pgw.ResultView.ResultViewPluginContainer): - print page.result.sql - print self.result.page_num(page) - print "==" - - - - -class NotebookLabel(gtk.HBox): - def __init__(self, page, notebook): - gtk.HBox.__init__(self) - self.page = page - self.notebook = notebook - - self.label = gtk.Label(page.name) - self.label.set_property("height-request", 20) - self.add(self.label) - - self.button = gtk.Button("x") - self.button.connect("clicked", self.on_button_close) - self.button.set_property("height-request", 25) - - self.add(self.button) - self.show_all() - - def on_button_close(self, widget=None): - self.notebook.remove(self.page) - -class QueryView(gtk.VBox): - def __init__(self, db, result): - gtk.VBox.__init__(self) - self.db = db - self.resultview = result - - #LAYOUT - self.toolbox = gtk.HBox() - self.toolbox.set_property("height-request", 30) - #dropdown - self.combobox_store = gtk.ListStore( str, pgw.GObjectContainer ) - self.combobox = gtk.ComboBox(self.combobox_store) - cell = gtk.CellRendererText() - self.combobox.pack_start(cell, True) - self.combobox.add_attribute(cell, 'text', 0) - self.toolbox.add(self.combobox) - - self.combobox_store.append([QueryViewSQLEditor.name, pgw.GObjectContainer(QueryViewSQLEditor)]) - self.combobox.set_active(0) - for plugin in pgw.Plugin.fromPath(sys.path[0] + "/plugins/", pgw.Plugin.QueryViewPlugin): - self.combobox_store.append([plugin.name, pgw.GObjectContainer(plugin)]) - - - #button "add" - self.button_add = gtk.Button(_('Add')) - self.button_add.connect("clicked", self.button_add_clicked) - self.toolbox.add(self.button_add) - - self.pack_start(self.toolbox, expand=False, fill=True) - - #Query View's - self.notebook = gtk.Notebook() - self.notebook.set_scrollable(True) - sqleditor = QueryViewSQLEditor(self.db, self.resultview) - self.notebook.append_page(sqleditor, NotebookLabel(sqleditor, self.notebook)) - self.notebook.set_current_page(0) - - self.add(self.notebook) #, expand=True, fill=True) - - - self.show_all() - - def button_add_clicked(self, widget=None): - plugin_gobj = (self.combobox_store[ self.combobox.get_property("active") ][1] ) - plugin_class = plugin_gobj.get() - plugin = plugin_class(self.db, self.resultview) - self.notebook.append_page(plugin, NotebookLabel(plugin, self.notebook)) - n = self.notebook.page_num(plugin) - plugin.show_all() - self.notebook.set_current_page(n) - diff --git a/pgworksheet_yvesf/pgw/ResultView.py b/pgworksheet_yvesf/pgw/ResultView.py deleted file mode 100644 index 487a96d..0000000 --- a/pgworksheet_yvesf/pgw/ResultView.py +++ /dev/null @@ -1,291 +0,0 @@ -import string -import pygtk; -import gtk; -import gobject; -import sys - -import pgw; -import pgw.Plugin; -import gettext -_ = gettext.gettext -class ListBox(gtk.ScrolledWindow): - def __init__(self, store=None): - gtk.ScrolledWindow.__init__(self) - self.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS) - self.set_shadow_type(gtk.SHADOW_NONE) - - if store: - self.store = store - else: - self.store = gtk.ListStore(str) - self.view = gtk.TreeView(self.store) - - cell = gtk.CellRendererText() - column = gtk.TreeViewColumn(_('Ansicht')) - column.pack_start(cell, True) - column.add_attribute(cell, 'text', 0) - column.set_sort_column_id(0) - self.view.append_column(column) - - self.add(self.view) - - def set_array(self, array): - self.store.clear() - for item in array: - self.store.append(item) - - def get(self): - tuple, treeview = self.view.get_cursor() - if tuple == None: - return None - return self.store[tuple[0]] - - - -class ResultViewTable(pgw.Plugin.ResultViewPlugin): - name = _('Tabellenansicht') - def __init__(self, ui, result): - pgw.Plugin.ResultViewPlugin.__init__(self, ui, result) - - sql = result.sql.strip() - scroll = gtk.ScrolledWindow() - tvw = gtk.TreeView() - scroll.add(tvw) - self.add(scroll) - - type_str = "" - cell = gtk.CellRendererText() - ncol = 0 - for col in result.description: - column = gtk.TreeViewColumn(string.replace(col.name, "_", "__")) - column.pack_start(cell, True) - column.add_attribute(cell, 'text', ncol) - column.set_sort_column_id(ncol) - tvw.append_column(column) - ncol = ncol + 1 - if (type_str == ""): - type_str = "str" - else: - type_str = type_str + ",str" - pass - # dynamically create the liststore, crazy - code = "liststore = gtk.ListStore(" + type_str + ")" - print code - exec compile(code, "", 'exec') - - for row in result.rows: - c = 0 - while c < len(row): - if row[c] is None: - row[c] = '(null)' - c += 1 - liststore.append(row) - - tvw.set_model(liststore) - tvw.set_reorderable(True) - tvw.columns_autosize() - - self.show_all() - - def update(self): - type_str = "" - cell = gtk.CellRendererText() - ncol = 0 - for col in self.result.description: - column = gtk.TreeViewColumn(string.replace(col.name, "_", "__")) - column.pack_start(cell, True) - column.add_attribute(cell, 'text', ncol) - column.set_sort_column_id(ncol) - tvw.append_column(column) - ncol = ncol + 1 - if (type_str == ""): - type_str = "str" - else: - type_str = type_str + ",str" - pass - # dynamically create the liststore, crazy - code = "liststore = gtk.ListStore(" + type_str + ")" - print code - exec compile(code, "", 'exec') - - for row in self.result.rows: - c = 0 - while c < len(row): - if row[c] is None: - row[c] = '(null)' - c += 1 - liststore.append(row) - - tvw.set_model(liststore) - tvw.set_reorderable(True) - tvw.columns_autosize() - - - -class GObjectContainer(gobject.GObject): - def __init__(self, data): - gobject.GObject.__init__(self) - self.set_data("key", data) - - def get(self): - return self.get_data("key") - - def set(self, data): - self.set_data("key", data) - return data - -class ResultViewPluginContainer(gtk.HPaned): - def __init__(self,app, result): - gtk.HPaned.__init__(self) - self.app = app - self.result = result - self.is_persistent = False - self.plugins = [ResultViewTable] - for plugin in pgw.Plugin.fromPath(sys.path[0] + "/plugins/", pgw.Plugin.ResultViewPlugin): - self.plugins.append(plugin) - - self.listbox = ListBox(gtk.ListStore(str,GObjectContainer)) - data = [] - for plugin in self.plugins: - data.append([plugin.name, GObjectContainer(plugin)]) - self.listbox.set_array(data) - self.listbox.view.set_property("width-request", 170) - self.listbox.view.connect("cursor-changed", self.set_plugin) - - self.persistent = gtk.CheckButton(_('Persistent')) - self.persistent.connect("clicked", self.sig_set_persistense) - self.persistent.set_property("height-request", 30) - - self.suicide = gtk.Button(_('Close')) - self.suicide.connect("clicked", self.remove_myself) - self.suicide.set_property("height-request", 30) - - self.vbox_hbox = gtk.HBox() - self.vbox_hbox.add(self.persistent) - self.vbox_hbox.add(self.suicide) - - self.vbox = gtk.VBox() - self.vbox.pack_start(self.vbox_hbox, False, False) - self.vbox.pack_start(self.listbox, True, True) - - self.pack2(self.vbox, False, True) - self.vbox.show_all() - - self.show() - - self.set_plugin() #set default plugin - - def remove_myself(self, widget=None): - self.parent.remove(self) - - def sig_set_persistense(self, widget=None): - self.is_persistent = self.persistent.get_property("active") - - def set_plugin(self, widget=None): - print str(self) + "set_plugin" - tuple, tvw = self.listbox.view.get_cursor() - if tuple == None: #nothin selected - tuple = (0,) #select 0 - plugin_class = self.listbox.store[tuple[0]][1].get() - - if plugin_class == None: #Plugin is in ListBox but not registered, should never happen - print "plugin_class == None" - raise Exception("plugin_class should contain a plugin and not None") - - oldchild = self.get_child1() - if oldchild: - self.remove(oldchild) - - self.plugin = plugin_class(self.app, self.result) - self.pack1(self.plugin, resize=True, shrink=True) - -class CloseLabel(gtk.HBox): - def __init__(self, widget, caption): - gtk.HBox.__init__(self) - self.page = widget - - self.label = gtk.Label(_('No Title')) - if type(caption) == str: - self.label.set_text(caption) - elif type(caption) == gtk.Label: - self.label.set_text(caption.get_text()) - - self.label.set_property("height-request", 20) - self.add(self.label) - - self.button = gtk.Button("x") - self.button.connect("clicked", self.on_button_close) - self.button.set_property("height-request", 25) - - self.add(self.button) - self.show_all() - - def on_button_close(self, widget=None): - self.parent.remove(self.page) - - -class ResultView(gtk.Notebook): - def __init__(self, app): - gtk.Notebook.__init__(self) - self.app = app -# self.connect("page-added", self.check_hiding) -# self.connect("page-removed", self.check_hiding) - - - def check_hiding(self, notebook=None, child=None, page_num=None): - print self.get_n_pages() - if self.get_n_pages() == 0: - self.hide_all() - else: - self.show_all() - - def add_results(self, result): - new_page = ResultViewPluginContainer(self.app, result) - self.append_page(new_page, None) - n=self.page_num(new_page) + 1 - sql = result.sql.strip() - title = "%d: %s"%(n, sql) - self.set_tab_label(new_page, CloseLabel(new_page, title)) - - - def add_widget(self, widget, label=None): - if label == None: - label = _('No Title') - self.append_page(widget, CloseLabel(widget,label)) - - def add_error(self, msg, title=None): - box = gtk.HBox() - - scroll = gtk.ScrolledWindow() - txt = gtk.TextView() - txt.get_buffer().set_text(unicode(msg, pgw.get_user_encoding())) - pgw.set_proportional(txt.get_buffer()) - txt.set_editable(False) - scroll.add(txt) - scroll.show_all() - if title: - title = title - else: - title = _('Error') - scroll.is_persistent = False - - def anon_closure(widget=None): - self.remove(box) - button_close = gtk.Button("Close") - button_close.connect("clicked", anon_closure) - - box.add(scroll) - box.add(button_close) - self.append_page(box, CloseLabel(box, title)) - - def append_page(self, widget, label): - gtk.Notebook.append_page(self, widget, label) - n = self.page_num(widget) - self.set_current_page(n) - - def clear(self): - for child in self.get_children(): - if not child.is_persistent: - self.remove(child) - - diff --git a/pgworksheet_yvesf/pgw/RunSQL.py b/pgworksheet_yvesf/pgw/RunSQL.py deleted file mode 100755 index 48367e4..0000000 --- a/pgworksheet_yvesf/pgw/RunSQL.py +++ /dev/null @@ -1,167 +0,0 @@ -# -*- coding: latin-1; -*- -# -# PgWorksheet - PostgreSQL Front End -# http://pgworksheet.projects.postgresql.org/ -# -# Copyright © 2004-2005 Henri Michelon & CML http://www.e-cml.org/ -# -# 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 (read LICENSE.txt). -# -# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# $Id -# -import string -import pygtk -import gtk -import sys - -import pgw - -class Column: - def __init__(self, col): - self.name = col[0] - self.type_code = col[1] - self.display_size = col[2] - self.internal_size = col[3] - self.precision = col[4] - self.scale = col[5] - self.null_ok = col[6] - -class Result: - def __init__(self, sql, result): - self.sql = sql - - self.description = [] #(name, type_code, display_size, internal_size, precision, scale,null_ok) - for col in result.description: - self.description.append(Column(col)) - - self.rows = [] - row = result.fetchone() - while row is not None: - self.rows.append(row) - row = result.fetchone() - - - -class RunSQL: - """Execute the SQL buffer and fill the GtkNotebook with the results.""" - - def __init__(self, execute, txtSQL, tabResult): - self.execute = execute - self.txtSQL = txtSQL - self.tabResult = tabResult - self.error_font = {} - - - def result(self, msg): - """update status bar text""" - print '' + msg + '' - - - def str_limit(self, s, max = 20): - s = string.replace(s, '\\\\', '\\') - if (len(s) > (max + 3)): - return s[:max] + "..." - return s - - - def fill_treeview(self, sql, cursor): - result = Result(sql, cursor) - self.tabResult.add_results(result) - return 0#XXX remove this dependency - - def run(self): - """Run the query and update the results""" - # clear the treeviews and the error text buffers - self.tabResult.clear() - - self.result(_("Please wait, executing the query and fetching the results...")) - # update the display - while (gtk.events_pending() == True): - gtk.main_iteration_do(False) - - # execute the query - sqlbuffer= self.txtSQL.get_buffer() - notices = [] - try: - result = self.execute.execute(sqlbuffer) - rows = 0 - if (isinstance(result, list)): - # multiple queries and multiple results... - parts = self.execute.split(sqlbuffer) - sqls = [] - have_errors = 0 - for sql in parts : - sql = string.strip(sql) - if (len(sql) > 0) : - sqls.append(sql) - for res in result: - sql = sqls.pop(0) - try: - if (res['cursor'].description is not None): - self.fill_treeview(sql, res['cursor']) - rows += res['cursor'].rowcount - notices = res['notices'] - except KeyError: - try: - self.tabResult.add_error(res['text'], "psql : " + self.str_limit(sql)) - except KeyError: - notices = res['notices'] - self.tabResult.add_error(res['error'], - '' + _('Errors :') + ' ' + - self.str_limit(sql)) - have_errors += 1 - self.tabResult.set_current_page(0) - else: # one query - sql = sqlbuffer.get_text(sqlbuffer.get_start_iter(), - sqlbuffer.get_end_iter()) - try: - if (result is None): - self.result(_("No result")) - elif (result['cursor'].description is None): - # not a SELECT - rows = result['cursor'].rowcount - notices = result['notices'] - else: - # only one SELECT - rows = self.fill_treeview(sql, result['cursor']) - notices = result['notices'] - except KeyError: - try: - self.tabResult.add_error(result['text'], "psql : " + self.str_limit(sql)) - except KeyError: - self.tabResult.add_error(result['error']) - notices = result['notices'] - - buffer = self.txtSQL.get_buffer() - buffer.move_mark_by_name('selection_bound', buffer.get_start_iter()); - buffer.move_mark_by_name('insert', buffer.get_end_iter()); - - except Exception, errstr: - import traceback - info= sys.exc_info() - self.result('' + _('query failed') + '') - self.tabResult.add_error("Fehler %s in line %d"%(str(errstr), traceback.tb_lineno(info[2]) )) - traceback.print_tb(info[2]) - - if (len(notices) > 0): - msg = "" - while len(notices): - msg += notices.pop() - self.tabResult.add_error(msg, ''+ _("log") + '') - - self.result("") - # restore the focus - self.txtSQL.grab_focus() - diff --git a/pgworksheet_yvesf/pgw/Syntax.py b/pgworksheet_yvesf/pgw/Syntax.py deleted file mode 100644 index 5e7ea68..0000000 --- a/pgworksheet_yvesf/pgw/Syntax.py +++ /dev/null @@ -1,782 +0,0 @@ -#!/usr/bin/env python -# -*- coding: latin-1; -*- -# -# PgWorksheet - PostgreSQL Front End -# http://pgworksheet.projects.postgresql.org/ -# -# Copyright © 2004-2005 Henri Michelon & CML http://www.e-cml.org/ -# -# 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 (read LICENSE.txt). -# -# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# $Id: Syntax.py,v 1.27 2005/06/10 15:14:33 hmichelon Exp $ -# -import gtk.gdk -import pango -import pgw -import pgw.Lexical - -# built-in data types and extensions -TYPES = [ 'BIGINT', 'INT8', 'BIGSERIAL', 'SERIAL8', 'BIT', 'VARYING', - 'VARBIT', 'BOOL', 'BOOLEAN', 'BOX', 'BYTEA', 'CHARACTER', 'VARCHAR', - 'CHAR', 'CIDR', 'CIRCLE', 'DATE', 'DOUBLE', 'PRECISION', - 'INET', 'INTEGER', 'FLOAT8', 'INT', 'INT4', 'INTERVAL', - 'LINE', 'LSEG', 'MACADDR', 'MONEY', 'NUMERIC', 'DECIMAL', - 'PATH', 'POINT', 'POLYGON', 'REAL', 'FLOAT4', 'SMALLINT', - 'INT2', 'SERIAL', 'SERIAL4', 'TEXT','TIME', 'TIMESTAMP', - 'TIMETZ', 'TIMESTAMPTZ', 'WITHOUT', 'TIME', 'ZONE' - ] - -# special constants -SPECIALS = [ 'FALSE', 'NULL', 'TRUE', 'UNKNOWN', 'ALL', 'ANY', 'SOME' ] - - -# named operators, constructs, conditionals and subqueries -OPERATORS2 = [ 'OVERLAPS', 'AND', 'OR', 'NOT', 'BETWEEN', 'IS', 'ISNULL', - 'NOTNULL', 'CAST', 'LIKE', 'ILIKE', 'SIMILAR', - 'EXISTS', 'IN', - 'CASE', 'WHEN', 'THEN', 'ELSE', 'END', - 'UNION', 'ARRAY', - ] - -# SQL and PostgreSQL statements -STATEMENTS = [ 'ABORT', 'ALTER', 'ANALYSE', 'BEGIN', 'CHECKPOINT', 'CLOSE', - 'CLUSTER', 'COMMENT', 'COMMIT', 'COPY', 'CREATE', 'DEALLOCATE', - 'DECLARE', 'DELETE', 'DROP', 'END', 'EXECUTE', 'EXPLAIN', - 'FETCH', 'GRANT', 'INSERT', 'LISTEN', 'LOAD', 'LOCK', 'MOVE', - 'NOTIFY', 'PREPARE', 'REINDEX', 'RELEASE', 'RESET', 'REVOKE', - 'ROLLBACK', 'SAVEPOINT', 'SELECT', 'SET', 'SHOW', 'START', - 'TRUNCATE', 'UNLISTEN', 'UPDATE', 'VACUUM' ] - -# built-in functions -BUILTINS = [ - # MATH - 'ABS', 'CBTR', 'CEIL', 'CEILING', 'DEGREES', 'EXP', 'FLOOR', 'LN', - 'LOG', 'MOD', 'PI', 'POWER', 'RADIANS', 'RANDOM', 'ROUND', - 'SETSEED', 'SIGN', 'SQRT', 'TRUNC', 'WIDTH_BUCKET', 'ACOS', - 'ASIN', 'ATAN', 'ATAN2', 'COS', 'COT', 'SIN', 'TAN', - # STRING - 'BIT_LENGTH', 'CHAR_LENGTH', 'CONVERT', 'LOWER', 'OCTET_LENGTH', - 'OVERLAY', 'POSITION', 'SUBSTRING', 'TRIM', 'UPPER', 'ASCII', - 'BTRIM', 'CHR', 'DECODE', 'ENCODE', 'INITCAP', 'LENGTH', - 'LPAD', 'LTRIM', 'MD5', 'PG_CLIENT_ENCODING', 'QUOTE_IDENT', - 'QUOTE_LITERAL', 'REPEAT', 'RPAD', 'RTRIM', 'SPLIT_PART', - 'STRPOS', 'TO_ASCII', 'TO_HEX', 'TRANSLATE', - # BSTRING - 'GET_BYTE', 'SET_BYTE', 'GET_BIT', 'SET_BIT', - # DATE - 'TO_CHAR', 'TO_DATE', 'TO_TIMESTAMP', 'TO_NUMBER', - 'AGE', 'DATE_PART', 'DATE_TRUNC', 'EXTRACT', 'ISFINITE', - 'NOW', 'TIMEOFDAY', - # GEOMETRIC - 'AREA', 'BOX_INTERSECT', 'CENTER', 'DIAMETER', 'HEIGHT', - 'ISCLOSED', 'ISOPEN', 'LENGTH', 'NPOINTS', 'PCLOSE', - 'POPEN', 'RADIUS', 'WIDTH', 'BOX', 'CIRCLE', 'LSEG', - 'PATH', 'POINT', 'POLYGON', - # NETWORK - 'BROADCAST', 'HOST', 'MASKLEN', 'SET_MASKLEN', - 'NETMASK', 'HOSTMASK', 'NETWORK', 'TEXT', 'ABBREV', - 'FAMILY', 'TRUNC', - # SEQUENCES - 'NEXTVAL', 'CURRVAL', - # CONDITIONAL - 'COALESCE', 'NULLIF', - # ARRAY - 'ARRAY_CAT', 'ARRAY_APPEND', 'ARRAY_PREPEND', 'ARRAY_DIMS', - 'ARRAY_LOWER', 'ARRAY_UPPER', 'ARRAY_TO_STRING', - 'STRING_TO_ARRAY' - # AGGREGATE - 'AVG', 'BIT_AND', 'BIT_OR', 'BOOL_AND', 'BOOL_OR', - 'COUNT', 'EVERY', 'MAX', 'MIN', 'STDDEV', 'SUM', - 'VARIANCE' - # SETS - 'GENERATE_SERIES', - # SYSTEM - 'CURRENT_DATABASE', 'CURRENT_SCHEMA', - 'INET_CLIENT_ADDR', 'INET_CLIENT_PORT', - 'INET_SERVER_ADDR', 'INET_SERVER_PORT', 'VERSION', - 'HAS_TABLE_PRIVILEGE', 'HAS_DATABASE_PRIVILEGE', - 'HAS_FUNCTION_PRIVILEGE', 'HAS_LANGUAGE_PRIVILEGE', - 'HAS_SCHEMA_PRIVILEGE', 'HAS_TABLESPACE_PRIVILEGE' - 'PG_TABLE_IS_VISIBLE', 'PG_TYPE_IS_VISIBLE', - 'PG_FUNCTION_IS_VISIBLE', 'PG_OPERATOR_IS_VISIBLE', - 'PG_OPCLASS_IS_VISIBLE', 'PG_CONVERSION_IS_VISIBLE', - 'FORMAT_TYPE', 'PG_GET_VIEWDEF', 'PG_GET_RULEGET', - 'PG_GET_INDEXDEF', 'PG_GET_TRIGGERDEF', - 'PG_GET_CONSTRAINTDEF', 'PG_GET_EXPR', 'PG_GET_USERBYID', - 'PG_GET_SERIAL_SEQUENCE', 'PG_TABLESPACE_DATABASES', - 'OBJ_DESCRIPITION', - # SYSTEM ADMIN - 'CURRENT_SETTINGS', 'SET_CONFIG', 'PG_CANCEL_BACKEND', - 'PG_START_BACKUP', 'PG_STOP_BACKUP', - - ] - -# built-in functions that can be used without () -# or conditional expressions -BUILTINS2 = [ # DATE - 'CURRENT_DATE', 'CURRENT_TIME', 'CURRENT_TIMESTAMP', - 'LOCALTIME', 'LOCALTIMESTAMP', - # SYSTEM - 'CURRENT_USER', 'SESSION_USER', 'USER', - ] - - -#""" -# PL/PgSQL keywords -PLPGSQL = [ # structure - 'DECLARE', 'BEGIN', 'END', - # declarations - 'RECORD', 'DEFAULT', 'CONSTANT', 'ALIAS', 'FOR', 'TYPE', 'ROWTYPE', - 'RENAME', 'TO', - # Statements - 'FOUND', 'PERFORM', 'GET', 'DIAGNOSTICS', - # Control Structures - 'RETURN', 'NEXT', 'IF', 'THEN', 'ELSE', 'END', 'ELSIF', 'LOOP', - 'EXIT', 'WHILE', 'REVERSE', 'IN', 'EXCEPTION', 'WHEN', - # Cursors - 'CURSOR', 'OPEN', 'EXECUTE', 'FETCH', 'INTO', 'CLOSE', - # Errors - 'RAISE', 'DEBUG', 'LOG', 'INFO', 'NOTICE', 'WARNING', 'EXCEPTION', - # Trigger Procedures - 'NEW', 'OLD', 'TG_NAME', 'TG_WHEN', 'TG_LEVEL', 'TG_OP', - 'TG_RELID', 'TG_RELNAME', 'TG_NARGS', 'TG_ARGV', - ] -#""" - -# keywords for each statement -KEYWORDS = { 'ABORT' : [ 'WORK', 'TRANSACTION' ], - 'ALTER' : { 'AGGREGATE' : [ [ 'RENAME', 'TO' ], - [ 'OWNER', 'TO' ] - ], - 'CONVERSION' : [ [ 'RENAME', 'TO' ], - [ 'OWNER', 'TO' ] - ], - 'DATABASE' : [ 'SET', 'TO', 'DEFAULT', - 'RESET', [ 'RENAME', 'TO' ], - [ 'OWNER', 'TO' ] - ], - 'DOMAIN' : [ [ 'SET', 'DEFAULT' ], - [ 'DROP', 'DEFAULT' ], - 'ADD', - [ 'DROP', 'CONSTRAINT' ], - 'RESTRICT', 'CASCADE', - [ 'OWNER', 'TO' ] - ], - 'FUNCTION' : [ [ 'RENAME', 'TO' ], - [ 'OWNER', 'TO' ] - ], - 'GROUP' : [ [ 'ADD', 'USER' ], - [ 'DROP', 'USER' ], - [ 'RENAME', 'TO' ] - ], - 'INDEX' : [ [ 'RENAME', 'TO' ], - [ 'OWNER', 'TO' ], - [ 'SET', 'TABLESPACE' ] - ], - 'LANGUAGE' : [ [ 'RENAME', 'TO' ] ], - 'OPERATOR' : [ 'NONE', [ 'OWNER', 'TO' ], - 'CLASS', 'USING' - ], - 'SCHEMA' : [ [ 'RENAME', 'TO' ], - [ 'OWNER', 'TO' ] - ], - 'SEQUENCE' : [ [ 'INCREMENT', 'BY' ], - 'MINVALUE', 'MAXVALUE', - [ 'RESTART', 'WITH' ], 'CACHE', - 'NO', 'CYCLE' - ], - 'TABLE' : [ 'ONLY', [ 'RENAME', 'COLUMN' ], - [ 'RENAME', 'TO' ], 'TO', - [ 'ADD', 'COLUMN' ], - [ 'DROP', 'COLUMN' ], 'RESTRICT', - 'CASCADE', 'TYPE', 'USING', - [ 'ALTER', 'COLUMN' ], - [ 'SET', 'DEFAULT' ], - [ 'DROP', 'DEFAULT' ], - 'SET', 'DROP', - [ 'SET', 'STATISTICS' ], - [ 'SET', 'STORAGE' ], 'PLAIN', - 'EXTERNAL', 'EXTERNAL', 'MAIN', - [ 'DROP', 'CONSTRAINT' ], - [ 'CLUSTER', 'ON' ], - [ 'SET', 'WITHOUT', 'CLUSTER' ], - [ 'SET', 'WITHOUT', 'OIDS' ], - [ 'OWNER', 'TO' ], - [ 'SET', 'TABLESPACE' ], - 'CHECK', - [ 'FOREIGN', 'KEY' ], 'CASCADE', - [ 'PRIMARY', 'KEY' ], - [ 'ON', 'DELETE' ], - [ 'ON', 'UPDATE' ], 'REFERENCES', - ], - 'TABLESPACE' : [ [ 'RENAME', 'TO' ], - [ 'OWNER', 'TO' ] - ], - 'TRIGGER' : [ 'ON', [ 'RENAME', 'TO' ] ], - 'TYPE' : [ [ 'OWNER', 'TO' ] ], - 'USER' : [ 'WITH', 'CREATEDB', 'NOCREATEDB', - 'CREATEUSER', 'NOCREATEUSER', - 'ENCRYPTED', 'UNENCRYPTED', - 'PASSWORD', [ 'VALID', 'UNTIL' ], - [ 'RENAME', 'TO' ], 'SET', - 'TO', 'DEFAULT', 'RESET' - ], - }, - 'ANALYZE' : [ 'VERBOSE' ], - 'BEGIN' : [ 'WORK', 'TRANSACTION', [ 'ISOLATION', 'LEVEL' ], - 'SERIALIZABLE', [ 'REPEATABLE', 'READ' ], - [ 'READ', 'COMMITTED' ], [ 'READ', 'UNCOMMITTED' ], - [ 'READ', 'WRITE' ], [ 'READ', 'ONLY' ] - ], - 'CHECKPOINT' : [], - 'CLOSE' : [], - 'CLUSTER' : [ 'ON' ], - 'COMMENT' : { 'ON' : [ 'TABLE', 'COLUMN', 'AGGREGATE', 'CAST', - 'AS', 'CONSTRAINT', 'ON', 'CONVERSION', - 'DATABASE', 'DOMAIN', 'FUNCTION', 'INDEX', - [ 'LARGE', 'OBJECT' ], 'OPERATOR', - [ 'OPERATOR', 'CLASS' ], 'USING', - 'PROCEDURAL', 'LANGUAGE', 'RULE', - 'SCHEMA', 'SEQUENCE', 'TRIGGER', - 'TYPE', 'VIEW', 'IS' - ] - }, - 'COMMIT' : [ 'WORK', 'TRANSACTION' ], - 'COPY' : [ 'FROM', 'STDIN', 'WITH', 'BINARY', 'OIDS', - 'DELIMITER', 'CSV', 'AS', 'ESCAPE' - 'FORCE', 'TO', 'STDOUT', 'QUOTE' - ], - 'CREATE' : { 'AGGREGATE' : [ 'BASETYPE', 'SFUNC', 'STYPE', - 'FINALFUNC', 'INITCOND' ], - 'CAST' : [ [ 'WITH', 'FUNCTION' ], - [ 'AS', 'ASSIGNMENT' ], - [ 'AS', 'IMPLICIT' ], - [ 'WITHOUT', 'FUNCTION'] - ], - 'CONSTRAINT' : [ 'TRIGGER', 'AFTER', 'ON', - [ 'FOR', 'EACH', 'ROW', 'EXECUTE' - 'PROCEDURE' ] - ], - 'CONVERSION' : [ 'FOR', 'TO', 'FROM' ], - 'DEFAULT' : [ 'CONVERSION', 'FOR', - 'TO', 'FROM' ], - 'DATABASE' : [ 'WITH', 'OWNER', 'TEMPLATE', - 'ENCODING', 'TABLESPACE', - 'DEFAULT' ], - 'DOMAIN' : [ 'AS', 'DEFAULT', 'CONSTRAINT', - 'CHECK' - ], - 'OR' : [ 'REPLACE', 'FUNCTION', - 'RETURNS', 'LANGUAGE', 'AS', - 'IMMUTABLE', 'STABLE', - 'VOLATILE', [ 'CALLED', 'ON', - 'NULL', 'INPUT' ], [ 'RETURNS', - 'NULL', 'ON', 'NULL', 'INPUT' ], - 'STRICT', 'EXTERNAL', - [ 'SECURITY', 'INVOKER' ], - [ 'SECURITY', 'DEFINER' ], 'WITH', - # XXX: for RULE - 'RULE', - 'AS', 'ON', 'TO', 'WHERE', - 'DO', 'ALSO', 'INSTEAD', - 'NOTHING', - 'VIEW' - ], - 'FUNCTION' : [ 'RETURNS', 'LANGUAGE', 'AS', - 'IMMUTABLE', 'STABLE', - 'VOLATILE', [ 'CALLED', 'ON', - 'NULL', 'INPUT' ], [ 'RETURNS', - 'NULL', 'ON', 'NULL', 'INPUT' ], - 'STRICT', 'EXTERNAL', - [ 'SECURITY', 'INVOKER' ], - [ 'SECURITY', 'DEFINER' ], 'WITH' - ], - 'GROUP' : [ 'WITH', 'SYSID', 'USER' ], - 'UNIQUE' : [ 'ON', 'USING', 'TABLESPACE', - 'WHERE', 'INDEX' ], - 'INDEX' : [ 'ON', 'USING', 'TABLESPACE', - 'WHERE', 'RTREE', 'HASH' ], - 'LANGUAGE' : [ 'HANDLER', 'VALIDATOR' ], - 'PROCEDURAL' : [ 'HANDLER', 'VALIDATOR', - 'LANGUAGE' ], - 'TRUSTED' : [ 'HANDLER', 'VALIDATOR', - 'LANGUAGE' ], - 'OPERATOR' : [ 'PROCEDURE', 'LEFTARG', - 'RIGHTARG', 'COMMUTATOR', - 'NEGATOR', 'RESTRICT', - 'JOIN', 'HASHES', 'MERGES', - 'SORT1', 'SORT2', 'LTCMP', - 'GTCMP', - 'CLASS', 'DEFAULT', - [ 'FOR', 'TYPE' ], 'USING', - 'AS', 'OPERATOR', 'RECHECK', - 'FUNCTION', 'STORAGE' ], - 'RULE' : [ 'AS', 'ON', 'TO', 'WHERE', - 'DO', 'ALSO', 'INSTEAD', - 'NOTHING' ], - 'SCHEMA' : [ 'AUTHORIZATION' ], - 'SEQUENCE' : [ 'INCREMENT', 'BY', 'MINVALUE', - 'NO', 'MAXVALUE', [ 'START', - 'WITH' ], 'CACHE', 'CYCLE' ], - 'TEMPORARY' : [ 'SEQUENCE', - 'INCREMENT', 'BY', 'MINVALUE', - 'NO', 'MAXVALUE', [ 'START', - 'WITH' ], 'CACHE', 'CYCLE', - # CREATE TABLE - 'TABLE', - 'DEFAULT', 'INCLUDING', - 'EXCLUDING', 'DEFAULTS', - 'INHERITS', 'WITH', - 'WITHOUT', 'OIDS', - [ 'ON', 'COMMIT' ], - [ 'PRESERVE', 'ROWS' ], - [ 'DELETE', 'ROWS' ], 'DROP', - 'TABLESPACE', 'CONSTRAINT', - 'UNIQUE', - [ 'USING', 'INDEX', 'TABLESPACE'], - [ 'PRIMARY', 'KEY' ], 'CHECK', - 'REFERENCES', [ 'MATCH', 'FULL' ], - [ 'MATCH', 'PARTIAL' ], - [ 'MATCH', 'SIMPLE' ], - [ 'ON', 'DELETE' ], - [ 'ON', 'UPDATE' ], 'DEFERRABLE', - [ 'INITIALLY', 'DEFERRED' ], - [ 'INITIALLY', 'IMMEDIATE' ], - [ 'FOREIGN', 'KEY' ], - 'CHECK', - ], - 'TEMP' : [ 'SEQUENCE', - 'INCREMENT', 'BY', 'MINVALUE', - 'NO', 'MAXVALUE', [ 'START', - 'WITH' ], 'CACHE', 'CYCLE', - # CREATE TABLE - 'TABLE', - 'DEFAULT', 'INCLUDING', - 'EXCLUDING', 'DEFAULTS', - 'INHERITS', 'WITH', 'OIDS', - 'WITHOUT', - [ 'ON', 'COMMIT' ], - [ 'PRESERVE', 'ROWS' ], - [ 'DELETE', 'ROWS' ], 'DROP', - 'TABLESPACE', 'CONSTRAINT', - 'UNIQUE', - [ 'USING', 'INDEX', 'TABLESPACE'], - [ 'PRIMARY', 'KEY' ], 'CHECK', - 'REFERENCES', [ 'MATCH', 'FULL' ], - [ 'MATCH', 'PARTIAL' ], - [ 'MATCH', 'SIMPLE' ], - [ 'ON', 'DELETE' ], - [ 'ON', 'UPDATE' ], 'DEFERRABLE', - [ 'INITIALLY', 'DEFERRED' ], - [ 'INITIALLY', 'IMMEDIATE' ], - [ 'FOREIGN', 'KEY' ], - 'CHECK', - ], - 'LOCAL' : [ 'TABLE', - 'DEFAULT', 'INCLUDING', - 'EXCLUDING', 'DEFAULTS', - 'INHERITS', 'WITH', - 'WITHOUT', 'OIDS', - [ 'ON', 'COMMIT' ], - [ 'PRESERVE', 'ROWS' ], - [ 'DELETE', 'ROWS' ], 'DROP', - 'TABLESPACE', 'CONSTRAINT', - 'UNIQUE', - [ 'USING', 'INDEX', 'TABLESPACE'], - [ 'PRIMARY', 'KEY' ], 'CHECK', - 'REFERENCES', [ 'MATCH', 'FULL' ], - [ 'MATCH', 'PARTIAL' ], - [ 'MATCH', 'SIMPLE' ], - [ 'ON', 'DELETE' ], - [ 'ON', 'UPDATE' ], 'DEFERRABLE', - [ 'INITIALLY', 'DEFERRED' ], - [ 'INITIALLY', 'IMMEDIATE' ], - [ 'FOREIGN', 'KEY' ], - 'CHECK', - ], - 'GLOBAL' : [ 'TABLE', - 'DEFAULT', 'INCLUDING', - 'EXCLUDING', 'DEFAULTS', - 'INHERITS', 'WITH', 'OIDS', - 'WITHOUT', - [ 'ON', 'COMMIT' ], - [ 'PRESERVE', 'ROWS' ], - [ 'DELETE', 'ROWS' ], 'DROP', - 'TABLESPACE', 'CONSTRAINT', - 'UNIQUE', - [ 'USING', 'INDEX', 'TABLESPACE'], - [ 'PRIMARY', 'KEY' ], 'CHECK', - 'REFERENCES', [ 'MATCH', 'FULL' ], - [ 'MATCH', 'PARTIAL' ], - [ 'MATCH', 'SIMPLE' ], - [ 'ON', 'DELETE' ], - [ 'ON', 'UPDATE' ], 'DEFERRABLE', - [ 'INITIALLY', 'DEFERRED' ], - [ 'INITIALLY', 'IMMEDIATE' ], - [ 'FOREIGN', 'KEY' ], - 'CHECK', - ], - 'TABLE' : [ 'DEFAULT', 'INCLUDING', - 'EXCLUDING', 'DEFAULTS', - 'INHERITS', 'WITH', 'OIDS', - 'WITHOUT', - [ 'ON', 'COMMIT' ], - [ 'PRESERVE', 'ROWS' ], - [ 'DELETE', 'ROWS' ], 'DROP', - 'TABLESPACE', 'CONSTRAINT', - 'UNIQUE', - [ 'USING', 'INDEX', 'TABLESPACE'], - [ 'PRIMARY', 'KEY' ], 'CHECK', - 'REFERENCES', [ 'MATCH', 'FULL' ], - [ 'MATCH', 'PARTIAL' ], - [ 'MATCH', 'SIMPLE' ], - [ 'ON', 'DELETE' ], - [ 'ON', 'UPDATE' ], 'DEFERRABLE', - 'INITIALLY', 'DEFERRED', - 'IMMEDIATE', 'RESTRICT', - [ 'FOREIGN', 'KEY' ], 'CASCADE' - 'CHECK', - ], - 'TABLESPACE' : [ 'OWNER', 'LOCATION' ], - 'TRIGGER' : [ 'BEFORE', 'AFTER', 'OR', 'ON', - 'FOR', 'EACH', 'ROW', 'STATEMENT', - [ 'EXECUTE', 'PROCEDURE' ] - ], - 'TYPE' : [ 'AS', 'INPUT', 'OUTPUT', - 'RECEIVE', 'SEND', 'ANALYZE', - 'INTERNALLENGTH', 'VARIABLE', - 'PASSEDBYVALUE', 'ALIGNMENT', - 'STORAGE', 'DEFAULT', - 'ELEMENT', 'DELIMITER' ], - 'USER' : [ 'WITH', 'SYSID', 'CREATEDB', - 'NOCREATEDB', 'CREATEUSER', - 'NOCREATEUSER', [ 'IN', 'GROUP' ], - 'ENCRYPTED', 'UNENCRYPTED', - 'PASSWORD', [ 'VALID', 'UNTIL' ] - ], - 'VIEW' : [ 'AS' , - # select - 'SELECT', 'DISTINCT', 'ON', - 'AS', 'FROM', 'WHERE', - [ 'GROUP', 'BY' ], 'HAVING', - 'UNION', 'INTERSECT', 'EXCEPT', - [ 'ORDER', 'BY' ], 'ASC', - 'DESC', 'USING', 'LIMIT', - 'OFFSET', [ 'FOR', 'UPDATE', - 'OF' ], 'ONLY', 'NATURAL', - 'USING', 'INNER', 'LEFT', 'OUTER', - 'RIGHT', 'FULL', 'JOIN', 'CROSS', - 'INTO' ], - }, - 'DEALLOCATE': [ 'PREPARE' ], - 'DECLARE' : [ 'BINARY', 'INSENSITIVE', 'NO', 'SCROLL', - 'CURSOR', 'WITH', 'WITHOUT', 'HOLD', 'FOR', - [ 'READ', 'ONLY' ], 'UPDATE', 'OF' ], - 'DELETE' : { 'FROM' : [ 'ONLY', 'WHERE' ] }, - 'DROP' : { 'AGGREGATE' : [ 'CASCADE', 'RESTRICT' ], - 'CAST' : [ 'AS', 'CASCADE', 'RESTRICT' ], - 'CONVERSION' : [ 'CASCADE', 'RESTRICT' ], - 'DATABASE' : [], - 'DOMAIN' : [ 'CASCADE', 'RESTRICT' ], - 'FUNCTION' : [ 'CASCADE', 'RESTRICT' ], - 'GROUP' : [], - 'INDEX' : [ 'CASCADE', 'RESTRICT' ], - 'LANGUAGE' : [ 'CASCADE', 'RESTRICT' ], - 'PROCEDURAL' : ['LANGUAGE', 'CASCADE', 'RESTRICT'], - 'OPERATOR' : [ 'NONE', 'CASCADE', 'RESTRICT', - 'CLASS', 'USING' ], - 'RULE' : [ 'ON', 'CASCADE', 'RESTRICT' ], - 'SCHEMA' : [ 'CASCADE', 'RESTRICT' ], - 'SEQUENCE' : [ 'CASCADE', 'RESTRICT' ], - 'TABLE' : [ 'CASCADE', 'RESTRICT' ], - 'TABLESPACE' : [], - 'TRIGGER' : [ 'ON', 'CASCADE', 'RESTRICT' ], - 'TYPE' : [ 'CASCADE', 'RESTRICT' ], - 'USER' : [], - 'VIEW' : [ 'CASCADE', 'RESTRICT' ], - }, - 'END' : [ 'WORK', 'TRANSACTION' ], - 'EXECUTE' : [], - 'EXPLAIN' : [ 'ANALYZE', 'VERBOSE' ], - 'FETCH' : [ 'FROM', 'IN', 'NEXT', 'PRIOR', 'FIRST', 'LAST', - 'ABSOLUTE', 'RELATIVE', 'FORWARD', - 'BACKWARD' ], - 'GRANT' : [ 'SELECT', 'INSERT', 'UPDATE', 'DELETE', 'RULE', - 'REFERENCES', 'TRIGGER', 'PRIVILEGES', - 'ON', 'TABLE', 'TO', 'GROUP', 'PUBLIC', - [ 'WITH', 'GRANT', 'OPTION' ], - 'CREATE', 'TEMPORARY', 'TEMP', 'PRIVILEGES', - 'DATABASE', 'EXECUTE', 'FUNCTION', 'USAGE', - 'LANGUAGE', 'SCHEMA', 'TABLESPACE' ], - 'INSERT' : { 'INTO' : [ 'DEFAULT', 'VALUES', - 'SELECT', 'DISTINCT', 'ON', 'AS', - 'FROM', 'WHERE', [ 'GROUP', 'BY' ], - 'HAVING', 'UNION', 'INTERSECT', 'EXCEPT', - [ 'ORDER', 'BY' ], - 'ASC', 'DESC', 'USING', 'LIMIT', - 'OFFSET', [ 'FOR', 'UPDATE', 'OF' ], - 'ONLY', 'NATURAL', 'USING', 'INNER', - 'LEFT', 'OUTER', 'RIGHT', 'FULL', - 'JOIN', 'CROSS', 'INTO', - ] - }, - 'LISTEN' : [], - 'LOAD' : [], - 'LOCK' : [ 'TABLE', 'IN', 'MODE', 'NOWAIT', - [ 'ACCESS', 'SHARE' ], [ 'ROW', 'SHARE' ], - [ 'ROW', 'EXCLUSIVE' ], - [ 'SHARE', 'UPDATE', 'EXCLUSIVE' ], - 'SHARE', [ 'SHARE', 'ROW', 'EXCLUSIVE' ], - 'EXCLUSIVE', [ 'ACCESS', 'EXCLUSIVE' ] ], - 'MOVE' : [ 'FROM', 'IN' ], - 'NOTIFY' : [], - 'PREPARE' : [ 'AS' ], - 'REINDEX' : [ 'DATABASE', 'TABLE', 'TABLE', 'FORCE' ], - 'RELEASE' : [ 'SAVEPOINT' ], - 'RESET' : [ ], - 'REVOKE' : [ [ 'GRANT', 'OPTION', 'FOR' ], 'SELECT', 'INSERT', - 'UPDATE', 'DELETE', 'RULE', 'REFERENCES', - 'TRIGGER', 'PRIVILEGES', 'ON', 'TABLE', - 'FROM', 'GROUP', 'PUBLIC', 'CASCADE', 'RESTRICT', - 'CREATE', 'TEMPORARY', 'TEMP', 'EXECUTE', - 'USAGE', 'SCHEMA', 'LANGUAGE', 'TABLESPACE' ], - 'ROLLBACK' : [ 'WORK', 'TRANSACTION', 'TO', 'SAVEPOINT' ], - 'SAVEPOINT': [], - - 'SELECT' : [ 'SELECT', 'INTO', 'DISTINCT', 'ON', 'AS', 'FROM', - 'WHERE', [ 'GROUP', 'BY' ], 'HAVING', 'UNION', - 'INTERSECT', 'EXCEPT', [ 'ORDER', 'BY' ], - 'ASC', 'DESC', 'USING', 'LIMIT', 'OFFSET', - [ 'FOR', 'UPDATE', 'OF' ], 'ONLY', 'NATURAL', - 'USING', 'INNER', 'LEFT', 'OUTER', 'RIGHT', 'FULL', - 'JOIN', 'CROSS', 'INTO' ], - 'SET' : [ 'SESSION', 'LOCAL', 'TO', 'DEFAULT', 'LOCAL', - [ 'TIME', 'ZONE' ], 'CONSTRAINTS', - 'DEFERRED', 'IMMEDIATE', 'AUTHORIZATION', - 'TRANSACTION', 'CHARACTERISTICS', - [ 'ISOLATION', 'LEVEL' ], 'SERIALIZABLE', - [ 'REPEATABLE', 'READ' ], [ 'READ', 'COMMITTED' ], - [ 'READ', 'UNCOMMITTED' ], [ 'READ', 'WRITE' ], - [ 'READ', 'ONLY' ] - ], - 'SHOW' : [ 'ALL' ], - 'START' : { 'TRANSACTION' : [ [ 'ISOLATION', 'LEVEL' ], - 'SERIALIZABLE', - [ 'REPEATABLE', 'READ' ], - [ 'READ', 'COMMITTED' ], - [ 'READ', 'UNCOMMITTED' ], - [ 'READ', 'WRITE' ], - [ 'READ', 'ONLY' ] - ], - }, - 'TRUNCATE' : [ 'TABLE' ], - 'UNLISTEN' : [], - 'UPDATE' : [ 'ONLY', 'SET', 'DEFAULT', 'FROM', 'WHERE' ], - 'VACUUM' : [ 'FULL', 'FREEZE', 'VERBOSE', 'ANALYSE' ] - } - - -class Syntax: - """Syntax highlight""" - - def __init__(self, buffer): - self.lexical = pgw.Lexical.Lexical() - self.buffer = buffer - self.last = None - # default colors - self.tag = {} - self.tag['font'] = self.buffer.create_tag("font") - if (pgw.mswindows()): - self.tag['font'].set_property('font', 'Courier New 10') - else: - self.tag['font'].set_property('family', 'monospace') - self.tag['function'] = self.buffer.create_tag("function") - self.tag['function'].set_property('foreground', '#009999') - self.tag['dollarquote'] = self.buffer.create_tag("dollarquote") - self.tag['dollarquote'].set_property('foreground', '#000000') - self.tag['identifier'] = self.buffer.create_tag("identifier") - self.tag['identifier'].set_property('foreground', '#000000') - self.tag['keyword'] = self.buffer.create_tag("keyword") - self.tag['keyword'].set_property('foreground', '#0000FF') - self.tag['type'] = self.buffer.create_tag("type") - self.tag['type'].set_property('foreground', '#009900') - self.tag['string'] = self.buffer.create_tag("string") - self.tag['string'].set_property('foreground', '#F700BF') - self.tag['numeric_constant'] = self.buffer.create_tag("numeric_constant") - self.tag['numeric_constant'].set_property('foreground', '#c53838') - self.tag['special'] = self.buffer.create_tag("special") - self.tag['special'].set_property('foreground', '#c53838') - self.tag['comment'] = self.buffer.create_tag("comment") - self.tag['comment'].set_property('foreground', '#999999') - self.tag['comment2'] = self.buffer.create_tag("comment2") - self.tag['comment2'].set_property('style', pango.STYLE_ITALIC) - self.tag['operator'] = self.buffer.create_tag("operator") - self.tag['operator'].set_property('foreground', '#555555') - self.tag['psql'] = self.buffer.create_tag("psql") - self.tag['psql'].set_property('background', '#d0d4df') - - - def start_of_prev_statement(self, iter): - """Find the first character of a statement""" - if (self.last is not None): - self.found = None - for token in self.last: - if (token.start_iter.compare(iter) >= 0): - if (self.found is None): - break - return self.found.start_iter - if (token.value == ';'): - self.found = token - if (self.found): - return self.found.start_iter - return iter.get_buffer().get_start_iter() - - - def start_of_next_statement(self, iter): - """Find the last character of a statement""" - if (self.last is not None): - self.found = None - for token in reversed(self.last): - if (token.end_iter.compare(iter) <= 0): - if (self.found is None): - break - return self.found.end_iter - if (token.value == ';'): - self.found = token - if (self.found): - return self.found.end_iter - return iter.get_buffer().get_end_iter() - - - def text_inserted(self, buffer, iter, text, length): - """Called by Gtk when text is inserted in the buffer: - prepare 'start' and 'end' for text_changed()""" - self.start = self.start_of_prev_statement(iter.copy()).get_offset() - self.end = self.start_of_next_statement(iter.copy()).get_offset() + length - - - def text_deleted(self, buffer, start, end): - """Called by Gtk when text is deleted from the buffer: - prepare 'start' and 'end' for text_changed()""" - self.start = self.start_of_prev_statement(start.copy()).get_offset() - self.end = self.start_of_next_statement(end.copy()).get_offset() - - - def text_changed(self, buffer): - """Called bu Gtk when (after) text is deleted or inserted - in the buffer. Uses 'start' and 'end' prepared in text_inserted - and text_deleted then run the analyse""" - start = self.buffer.get_iter_at_offset(self.start) - end = self.buffer.get_iter_at_offset(self.end) - self.analyse(start, end) - - - def refresh(self): - """Used when you want to manually refresh the syntax highlight - a the whole buffer""" - start = self.buffer.get_start_iter() - end = self.buffer.get_end_iter() - self.analyse(start, end) - - - def analyse(self, start, end): - """Run the lexical and syntaxical analysers then - apply the syntax highlight to the buffer""" - self.tokens = self.lexical.analyse(self.buffer, start, end) - self.syntaxical_analyser() - self.buffer.remove_all_tags(start, end) - self.buffer.apply_tag(self.tag['font'], start, end) - self.last = self.tokens - for token in self.tokens: - self.buffer.apply_tag(self.tag[token.token], \ - token.start_iter, \ - token.end_iter) - if (token.token == 'comment'): - self.buffer.apply_tag(self.tag['comment2'], \ - token.start_iter, \ - token.end_iter) - - - def syntaxical_analyser(self): - """Find keywords""" - tokens = self.tokens - self.tokens = [] - try: - while (len(tokens) > 0): - token = tokens.pop(0) - # only statements, other tokens - # are analysed below or already founds in - # the lexical analyser - if (token.value in STATEMENTS): - token.token = 'keyword' - self.tokens.append(token) - statement = token.value - token = tokens.pop(0) - # get the list containing the - # keywords for this statement - try: - keywords = KEYWORDS[statement] - except KeyError: - continue - if (type(keywords) is dict): - try: - keywords = keywords[token.value] - token.token = 'keyword' - self.tokens.append(token) - token = tokens.pop(0) - except KeyError: - pass - self.tokens.append(token) - # identify each token inside the statement - while (token.value != ';'): - # only identifiers, other tokens are - # analysed in the lexical analyser - if (token.token == 'identifier'): - # special constants - if (token.value in SPECIALS): - token.token = 'special' - # buit-in data types - elif (token.value in TYPES): - # TODO : manager composed types names - token.token = 'type' - # names operators - elif (token.value in OPERATORS2): - token.token = 'operator' - # built-in functions - elif (token.value in BUILTINS): - next = tokens.pop(0) - if (next.value == '('): - token.token = 'function' - self.tokens.append(next) - else: - tokens.insert(0, next) - # built-in function that can be used without () - if (token.value in BUILTINS2): - token.token = 'function' - # everything else : keywords or indentifiers - else: - for keyword in keywords: - if (type(keyword) is list): - # TODO : write the right code here - # to manage composed keywords - if (token.value in keyword): - token.token = 'keyword' - elif (token.value == keyword): - token.token = 'keyword' - self.tokens.append(token) - token = tokens.pop(0) - self.tokens.append(token) - except IndexError: - pass diff --git a/pgworksheet_yvesf/pgw/UI.py b/pgworksheet_yvesf/pgw/UI.py deleted file mode 100644 index 2b09702..0000000 --- a/pgworksheet_yvesf/pgw/UI.py +++ /dev/null @@ -1,937 +0,0 @@ -# -*- coding: utf-8; -*- -# -# PgWorksheet - PostgreSQL Front End -# http://pgworksheet.projects.postgresql.org/ -# -# Copyright © 2004-2005 Henri Michelon & CML http://www.e-cml.org/ -# -# 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 (read LICENSE.txt). -# -# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# $Id: UI.py,v 1.23 2005/06/10 14:22:37 hmichelon Exp $ -# -import os -import sys -import ConfigParser -import pygtk -import gtk -import gettext; _ = gettext.gettext - -import pgw -import pgw.Syntax -import pgw.Undo -import pgw.Plugin -import pgw.ResultView -import pgw.DBConnection; -import pgw.QueryView; -import pgw.ConnectDialog -import pgw.Widgets - - -PGW_CONNECT = 'pgw-connect' -PGW_CONNECTNOW = 'pgw-connectnow' -PGW_DISCONNECT = 'pwg-disconnect' -PGW_SELECTALL = 'pwg-selectall' -PGW_ENCODING = 'pwg-encoding' -PGW_ABOUT = 'pwg-about' - - -class UI(gtk.Window): - """UI Construction and management""" - - def __init__(self, app, pixmap_path): - gtk.Window.__init__(self, gtk.WINDOW_TOPLEVEL) - - self.sidebar_plugins = [] - self.db = pgw.DBConnection.DBConnection() - - self.pixmap_path = pixmap_path - self.register_stock_items() - self.file_dialog_path = None - self.define_ui(app) - - self.load_user_parameters() - self.show_all() - - - - def on_state(self, widget, event): - cp = ConfigParser.ConfigParser() - try: - cp.readfp(open(pgw.get_config_path(), 'r')) - except IOError: - pass - if (not cp.has_section("window")): - cp.add_section("window") - if (event.new_window_state == gtk.gdk.WINDOW_STATE_MAXIMIZED): - cp.set("window", "maximized", "1") - else: - cp.set("window", "maximized", "0") - self.write_config(cp) - - - def on_configure(self, widget, event): - cp = ConfigParser.ConfigParser() - try: - cp.readfp(open(pgw.get_config_path(), 'r')) - except IOError: - pass - if (not cp.has_section("window")): - cp.add_section("window") - x, y = widget.get_position() - cp.set("window", "x", x) - cp.set("window", "y", y) - width, height = widget.get_size() - cp.set("window", "width", width) - cp.set("window", "height", height) - self.write_config(cp) - - def on_delete(self, widget=None, event=None): - return False - - - def on_destroy(self, widget=None): - self.db.disconnect() - #XXX self.save_history() - gtk.main_quit() - sys.exit() - -#####Menu - def on_menu_connect(self, widget): - """Called when the user want the connection dialog box""" - dlg = pgw.ConnectDialog.ConnectDialog() - dlg.connect("clicked-ok", self.connect_db) - dlg.show() - - def connect_db(self, dialog, connectionParameter): - cp = connectionParameter - if self.db.is_connected(): - dialog.set_error('' + _('Doing disconnect...')+'') - self.db.disconnect() - dialog.set_error("") - - try: - self.db.connect(cp) - except pgw.DBConnection.DatabaseError, errstr: - dialog.set_error('' + _('Connection Failed:') + "%s"%errstr) - return False - - if self.db.is_connected(): - self.enable_disconnect(True) - return True - else: - dialog.set_error(''+_("Connection Failed")+"") - print "Connection Failed" - return False - - def on_menu_disconnect(self, widget): - self.db.disconnect() - self.enable_disconnect(False) - - def load_user_parameters(self): - cp = ConfigParser.ConfigParser() - try: - cp.readfp(open(pgw.get_config_path(), 'r')) - maximized = 0 - try: - maximized = int(cp.get("window", "maximized")) - except: - pass - if (maximized): - self.maximize() - else: - width, height = self.get_size() - try: - width = int(cp.get("window", "width")) - except: - pass - try: - height = int(cp.get("window", "height")) - except: - pass - self.resize(width, height) - x, y = self.get_position() - try: - x = int(cp.get("window", "x")) - except: - pass - try: - y = int(cp.get("window", "y")) - except: - pass - self.move(x, y) - try: - self.vmain.set_position(int(cp.get("window", "divider"))) - except: - pass - except IOError: - pass - return cp - - - def message_dialog(self, msg, type, buttons = gtk.BUTTONS_OK): - dialog = gtk.MessageDialog(self, - gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, - type, buttons, msg) - result = dialog.run() - dialog.destroy() - return result - - - def message_box(self, msg): - self.message_dialog(msg, gtk.MESSAGE_INFO) - - - def error_box(self, msg): - self.message_dialog(msg, gtk.MESSAGE_ERROR) - - - def yesno_box(self, msg): - return self.message_dialog(msg, gtk.MESSAGE_QUESTION, gtk.BUTTONS_YES_NO) - - - def file_dialog(self, msg, action = gtk.FILE_CHOOSER_ACTION_OPEN, - button = gtk.STOCK_OPEN): - fb = gtk.FileChooserDialog(msg, self, - action, - (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, - button, gtk.RESPONSE_OK)) - if (self.file_dialog_path is not None): - fb.set_current_folder_uri(self.file_dialog_path) - fb.show_all() - result = fb.run() - if (result == gtk.RESPONSE_OK): - filename = fb.get_filename() - else: - filename = None - self.file_dialog_path = fb.get_current_folder_uri() - fb.destroy() - return filename - - - def register_stock_items(self): - gtk.stock_add([ - (PGW_CONNECT, _('_Connect Server...'), gtk.gdk.CONTROL_MASK, - gtk.gdk.keyval_from_name('N'), None), - (PGW_DISCONNECT, _('_Disconnect'), 0, -1, None), - (PGW_SELECTALL, _('Select _All'), gtk.gdk.CONTROL_MASK, - gtk.gdk.keyval_from_name('A'), None), - (PGW_ENCODING, _('Character _Encoding'), 0, -1, None), - (PGW_ABOUT, _('_About...'), 0, -1, None), - (PGW_CONNECTNOW, _('_Connect'), 0, -1, None), - ]) - self.factory = gtk.IconFactory() - self.factory.add_default() - self.factory.add(PGW_CONNECTNOW, gtk.IconSet(gtk.gdk.pixbuf_new_from_file( - os.path.join(self.pixmap_path, "connect.png")))) - self.factory.add(PGW_CONNECT, gtk.IconSet(gtk.gdk.pixbuf_new_from_file( - os.path.join(self.pixmap_path, "connect.png")))) - self.factory.add(PGW_DISCONNECT, gtk.IconSet(gtk.gdk.pixbuf_new_from_file( - os.path.join(self.pixmap_path, "disconnect.png")))) - self.factory.add(PGW_ABOUT, gtk.IconSet(gtk.gdk.pixbuf_new_from_file( - os.path.join(self.pixmap_path, "about.png")))) - - - def define_ui(self, app): - self.ui = ''' - - - - - - - - - - - - - - - - - - - ''' - - self.undo = pgw.Undo.Undo() - self.uimanager = gtk.UIManager() - self.accelgroup = self.uimanager.get_accel_group() - self.actiongroup = gtk.ActionGroup('UIManagerMenuBar') - self.actiongroup.add_actions([ - ('File', None, _('_File')), - ('Connect', PGW_CONNECT, None, None, - _('Connect to a database'), self.on_menu_connect), - ('Disconnect', PGW_DISCONNECT, None, '', - _('Disconnect from the database'), self.on_menu_disconnect), - ('Quit', gtk.STOCK_QUIT, None, None, - _('Quit the Program'), self.on_destroy), - ]) - self.uimanager.insert_action_group(self.actiongroup, 0) - self.uimanager.add_ui_from_string(self.ui) -# self.uimanager.get_widget('/MenuBar/Help').set_right_justified(True) - self.create_vpaned(app) - self.create_statusbar() - self.enable_disconnect(False) -# self.uimanager.get_widget('/ToolBar').set_style(gtk.TOOLBAR_ICONS) - - self.set_title(_('PgWorksheet - PostgreSQL SQL Tool')) - self.set_icon_from_file(os.path.join("pixmaps/pgworksheet", "pgworksheet-32.png")) - self.add_accel_group(self.accelgroup) - self.set_default_size(640, 480) - self.connect('window-state-event', self.on_state) - self.connect('configure-event', self.on_configure) - self.connect('destroy', self.on_destroy) - self.connect('delete_event',self.on_delete) - - hbox = gtk.VBox(False) - hbox.pack_start(self.uimanager.get_widget('/MenuBar'), False) - #hbox.pack_start(self.uimanager.get_widget('/ToolBar'), False) - hbox.pack_start(self.vmain, True, True) - hbox.pack_start(self.statusbar, False, False) - self.add(hbox) - - - def create_vpaned(self, app): - self.vmain = gtk.VPaned() - self.vmain.connect("event", self.on_vpaned_accept) - self.hmain = gtk.HPaned(); - self.hmain.set_property("height-request", 350); - -# scroll = gtk.ScrolledWindow() -# scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) -# scroll.set_property("height-request", 150) -# scroll.set_shadow_type(gtk.SHADOW_NONE) -# self.sqlbuffer = gtk.TextBuffer() -# self.sqlbuffer.connect('delete-range', self.undo.text_deleted) -# self.sqlbuffer.connect('insert-text', self.undo.text_inserted) -# self.syntax = pgw.Syntax.Syntax(self.sqlbuffer) -# self.buffer_handlers = [] - #XXX -# self.buffer_handlers.append(self.sqlbuffer.connect('delete-range', -# self.syntax.text_deleted)) -# self.buffer_handlers.append(self.sqlbuffer.connect('insert-text', -# self.syntax.text_inserted)) -# self.buffer_handlers.append(self.sqlbuffer.connect('changed', -# self.syntax.text_changed)) -# self.buffer_handlers.append(self.sqlbuffer.connect('changed', -# app.on_text_change)) -# self.sqlview = gtk.TextView(self.sqlbuffer) -# self.sqlview.connect('focus-in-event', app.on_sqlview_focus_in) -# self.sqlview.connect('focus-out-event', app.on_sqlview_focus_out) -# self.sqlview.connect('key-press-event', app.on_sqlview_keypress) -# scroll.add(self.sqlview) -# scroll.set_property("width-request", 380); -# self.hmain.pack1(scroll, resize=True, shrink=False) - self.resulttab = pgw.ResultView.ResultView(app) - self.resulttab.set_tab_pos(gtk.POS_BOTTOM) - self.resulttab.set_scrollable(True) - self.vmain.pack2(self.resulttab, resize=True, shrink=False) - - - - self.sidebar = gtk.Notebook(); - self.sidebar.set_property("width-request", 200) - for plugin_class in pgw.Plugin.fromPath(sys.path[0] + "/plugins/", pgw.Plugin.SidebarPlugin): - try: - child = plugin_class(self) - self.sidebar.add(child); - self.sidebar.set_tab_label(child, gtk.Label(child.name)) - self.sidebar_plugins.append(child); - except Exception, errstr: - print child, errstr - - self.queryview = pgw.QueryView.QueryView(self.db, self.resulttab) - self.queryview.set_property("width-request", 500) - self.hmain.pack1(self.queryview, resize=True, shrink=True) - - self.hmain.pack2(self.sidebar, resize=True, shrink=True); - - self.hmain.set_position(-1) #reccalculate by widget propertys - - self.vmain.pack1(self.hmain, resize=True, shrink=False) - - - def create_statusbar(self): - self.statusbar = gtk.Statusbar() - self.statusbar.set_border_width(0) - - f = self.statusbar.get_children()[0] - f.set_shadow_type(gtk.SHADOW_IN) - self.statusbar.set_child_packing(f, True, True, 0, gtk.PACK_START) - - self.status_connect = gtk.Label(); - self.status_connect.set_justify(gtk.JUSTIFY_LEFT) - f = gtk.Frame() - f.set_shadow_type(gtk.SHADOW_IN) - f.add(self.status_connect) - self.statusbar.pack_start(f, False, False) - - f = gtk.Label(' ') - self.statusbar.pack_start(f, False, False) - - self.traffic_light = pgw.Widgets.TrafficLight(False) - self.traffic_light.set_property("height-request", 20) - self.traffic_light.set_property("width-request", 14) - self.statusbar.pack_start(self.traffic_light, False, False) - - - def status(self, message): - """Update the status bar text""" - self.status_connect.set_markup(" " + connect + " ") - - - def setfocus_sqlbuffer(self): - self.sqlview.grab_focus() - - - def enable_disconnect(self, state = True): - self.uimanager.get_widget('/MenuBar/File/Disconnect').\ - set_sensitive(state) - - self.traffic_light.set(state) - - if state == True: #that should mean we are connected now - for plugin in self.sidebar_plugins: - try: - plugin.on_connection() - except Exception, ersstr: - print "Exception in plugin %s"%plugin - print ersstr - - def get_text(self, buffer): - """Return the text of a widget""" - c1 = buffer.get_start_iter() - c2 = buffer.get_end_iter() - return buffer.get_slice(c1, c2, True) - - - def get_sqlbuffer_text(self): - return self.get_text(self.sqlbuffer) - - - def set_sqlbuffer_text(self, text): - self.sqlbuffer.set_text(text) - - - def on_connect_event(self, widget, event): - if ((not self.entry_password.is_focus()) and - self.viewconn.is_focus()): - self.entry_password.grab_focus() - - - def connect_dialog(self): - dlg = gtk.Dialog(_('Database connection'), - self, - gtk.DIALOG_MODAL or gtk.DIALOG_DESTROY_WITH_PARENT, - ((gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, - PGW_CONNECTNOW, gtk.RESPONSE_OK))) - dlg.set_resizable(False) - - mbox = gtk.HBox() - box = gtk.Frame() - self.storeconn = gtk.ListStore(str, str) - self.viewconn = gtk.TreeView(self.storeconn) - cell = gtk.CellRendererText() - column = gtk.TreeViewColumn(_('5 Previous connections')) - column.pack_start(cell, True) - column.add_attribute(cell, 'text', 0) - column.set_sort_column_id(0) - self.viewconn.append_column(column) - self.viewconn.connect('cursor-changed', self.on_dlgconnect_change) - box.add(self.viewconn) - mbox.pack_start(box, True, True) - - hbox = gtk.HBox(False) - hbox.set_border_width(10) - hbox.set_spacing(10) - - box = gtk.VBox(True) - box.set_spacing(10) - lbl = gtk.Label(_('Host')) - lbl.set_alignment(0, 0.1) - box.pack_start(lbl, True, True) - lbl = gtk.Label(_('Port')) - lbl.set_alignment(0, 0.1) - box.pack_start(lbl, True, True) - lbl = gtk.Label(_('User')) - lbl.set_alignment(0, 0.1) - box.pack_start(lbl, True, True) - lbl = gtk.Label(_('Password')) - lbl.set_alignment(0, 0.1) - box.pack_start(lbl, True, True) - lbl = gtk.Label(_('Database')) - lbl.set_alignment(0, 0.1) - box.pack_start(lbl, True, True) - hbox.pack_start(box, False, False) - - box = gtk.VBox(False) - box.set_spacing(10) - self.entry_host = gtk.Entry() - self.entry_host.connect('activate', lambda w: dlg.response(gtk.RESPONSE_OK)) - box.pack_start(self.entry_host, True, True) - self.entry_port = gtk.Entry() - self.entry_port.connect('activate', lambda w: dlg.response(gtk.RESPONSE_OK)) - box.pack_start(self.entry_port, True, True) - self.entry_user = gtk.Entry() - self.entry_user.connect('activate', lambda w: dlg.response(gtk.RESPONSE_OK)) - box.pack_start(self.entry_user, True, True) - self.entry_password = gtk.Entry() - self.entry_password.set_visibility(False) - self.entry_password.connect('activate', lambda w: dlg.response(gtk.RESPONSE_OK)) - box.pack_start(self.entry_password, True, True) - self.entry_database = gtk.Entry() - self.entry_database.connect('activate', lambda w: dlg.response(gtk.RESPONSE_OK)) - box.pack_start(self.entry_database, True, True) - hbox.pack_start(box, True, True) - - mbox.pack_start(hbox, True, True) - - dlg.vbox.pack_start(mbox, True, True, 0) - app.on_dlgconnect_map(None) - if (overwrite_entry or (not self.storeconn.iter_n_children(None))): - self.entry_host.set_text(host) - self.entry_port.set_text(str(port)) - self.entry_user.set_text(user) - self.entry_database.set_text(database) - dlg.set_default_response(gtk.RESPONSE_OK) - dlg.connect('event-after', self.on_connect_event) - dlg.vbox.show_all() - self.entry_password.grab_focus() - result = None - if (dlg.run() == gtk.RESPONSE_OK): - result = (self.entry_host.get_text(), - self.entry_port.get_text(), - self.entry_user.get_text(), - self.entry_password.get_text(), - self.entry_database.get_text()) - dlg.destroy() - return result - - - def write_config(self, cp): - try: - cp.write(open(pgw.get_config_path(), 'w')) - except IOError: - pass - - - def on_vpaned_accept(self, widget, event): - cp = ConfigParser.ConfigParser() - try: - cp.readfp(open(pgw.get_config_path(), 'r')) - except IOError: - pass - if (not cp.has_section("window")): - cp.add_section("window") - cp.set("window", "divider", str(widget.get_position())) - self.write_config(cp) - - - def about_dialog(self): - dlg = gtk.Dialog(_('About PgWorksheet'), - self, - gtk.DIALOG_MODAL or gtk.DIALOG_DESTROY_WITH_PARENT, - ((gtk.STOCK_CLOSE, gtk.RESPONSE_CLOSE))) - nbk = gtk.Notebook() - - box = gtk.VBox(False) - - lbl = gtk.Label() - lbl.set_markup(''' -PgWorksheet - PostgreSQL Front End -Version ''' + """self.app_version""" + ''' -http://pgworksheet.projects.postgresql.org/ - -Copyright © 2004-2005, Henri Michelon and CML -http://www.e-cml.org/ - ''') - lbl.set_justify(gtk.JUSTIFY_CENTER) - lbl.set_padding(10, 10) - box.pack_start(lbl, True) - lbl = gtk.Label() - lbl.set_markup(''' -Internationalization: -French : Henri Michelon <hmichelon@e-cml.org> -Japanese : Tadashi Jokagi <elf2000@users.sourceforge.net> - ''') - lbl.set_padding(10, 0) - box.pack_start(lbl, True) - pix = gtk.Image() - pix.set_from_file(os.path.join(self.pixmap_path, "pgworksheet.png")) - pix.set_padding(10, 10) - box.pack_start(pix, False) - nbk.append_page(box, gtk.Label(_('About'))) - - txt = gtk.TextBuffer() - txt.set_text(''' - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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. - ''') - scroll = gtk.ScrolledWindow() - scroll.add(gtk.TextView(txt)) - nbk.append_page(scroll, gtk.Label(_('License'))) - - dlg.vbox.pack_start(nbk, True, True, 0) - nbk.show_all() - dlg.run() - dlg.destroy() - - - -if __name__ == "__main__": - window = UI.new() - window.show_all() - gtk.main() - - - diff --git a/pgworksheet_yvesf/pgw/Undo.py b/pgworksheet_yvesf/pgw/Undo.py deleted file mode 100644 index ff7b025..0000000 --- a/pgworksheet_yvesf/pgw/Undo.py +++ /dev/null @@ -1,106 +0,0 @@ -# -*- coding: latin-1; -*- -# -# PgWorksheet - PostgreSQL Front End -# http://pgworksheet.projects.postgresql.org/ -# -# Copyright © 2004-2005 Henri Michelon & CML http://www.e-cml.org/ -# -# 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 (read LICENSE.txt). -# -# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# $Id: Undo.py,v 1.2 2005/10/24 14:16:02 hmichelon Exp $ -# - -# maxium size of the undo stack -UNDO_MAX = 1000 - - -class UndoAction: - """A user action : insert or delete""" - - def __init__(self, buffer, type, start, end, value): - self.buffer = buffer - self.type = type - self.start = start - self.end = end - self.value = value - - -class Undo: - """Records user actions and apply or revert them""" - - def __init__(self): - self.undo_stack = [] - self.redo_stack = [] - # locking is used to avoid recording - # our own undo/redo actions - self.lock = False - - - def reset(self): - """empty the stacks to restart the undo action""" - self.undo_stack = [] - self.redo_stack = [] - - - def text_inserted(self, buffer, iter, text, length): - """Called by Gtk when text is inserted in a buffer""" - if (not self.lock): - if (len(self.undo_stack) >= UNDO_MAX): - self.undo_stack.pop(0) - self.undo_stack.append(UndoAction(buffer, "insert", - iter.get_offset(), iter.get_offset() + length, - text)) - - - def text_deleted(self, buffer, start, end): - """Called by Gtk when text is deleted from a buffer""" - if (not self.lock): - if (len(self.undo_stack) >= UNDO_MAX): - self.undo_stack.pop(0) - self.undo_stack.append(UndoAction(buffer, "delete", - start.get_offset(), end.get_offset(), - buffer.get_text(start, end))) - - - def undo(self): - """Revert the last action""" - if (len(self.undo_stack) == 0): - return - self.lock = True - action = self.undo_stack.pop() - if (action.type == "insert"): - action.buffer.delete(action.buffer.get_iter_at_offset(action.start), - action.buffer.get_iter_at_offset(action.end)) - elif (action.type == "delete"): - action.buffer.insert(action.buffer.get_iter_at_offset(action.start), - action.value) - self.redo_stack.append(action) - self.lock = False - - - def redo(self): - """Apply the last reverted action""" - if (len(self.redo_stack) == 0): - return - self.lock = True - action = self.redo_stack.pop() - if (action.type == "insert"): - action.buffer.insert(action.buffer.get_iter_at_offset(action.start), - action.value) - elif (action.type == "delete"): - action.buffer.delete(action.buffer.get_iter_at_offset(action.start), - action.buffer.get_iter_at_offset(action.end)) - self.undo_stack.append(action) - self.lock = False diff --git a/pgworksheet_yvesf/pgw/Widgets.py b/pgworksheet_yvesf/pgw/Widgets.py deleted file mode 100644 index e0d779e..0000000 --- a/pgworksheet_yvesf/pgw/Widgets.py +++ /dev/null @@ -1,389 +0,0 @@ -import gtk -import math - -class TrafficLight(gtk.DrawingArea): - def __init__(self, start=False): - gtk.DrawingArea.__init__(self) - self.connect("expose_event", self.expose) - self.status = start - - def expose(self, widget, event): - self.context = widget.window.cairo_create() - self.draw(self.context) - - return False - - def draw(self, context): - rect = self.get_allocation() - padding = 1 - - context.rectangle(0, 0, rect.width, rect.height) - context.stroke() - - sub = 1 - #False => Red - if self.status == False: - context.set_source_rgb(1.0, 0.0, 0.0) - context.arc(rect.width / 2, 1 * (rect.height / 4), min([(rect.width/2)-sub, (rect.height/4)-sub]), 0, 2.0 * math.pi) - context.fill() - - context.set_source_rgb(0.0, 0.0, 0.0) - context.arc(rect.width / 2, 1 * (rect.height / 4), min([(rect.width/2)-sub, (rect.height/4)-sub]), math.pi, 2*math.pi) - context.stroke() - - - #True => Green - if self.status == True: - context.arc(rect.width / 2, 3 * (rect.height / 4), min([(rect.width/2)-sub, (rect.height/4)-sub]), 0, 2.0 * math.pi) - context.set_source_rgb(0.0, 1.0, 0.0) - context.fill() - - context.set_source_rgb(0.0, 0.0, 0.0) - context.arc(rect.width / 2, 3 * (rect.height / 4), min([(rect.width/2)-sub, (rect.height/4)-sub]), math.pi, 2*math.pi) - context.stroke() - - def get(self): - return self.status - def set(self, status): - self.status = status - - self.hide() - self.show() - def toggle(self): - self.set(not self.get()) - - - - - -#=======================================================================================================0 -#=======================================================================================================0 -#=======================================================================================================0 -#=======================================================================================================0 -#=======================================================================================================0 -"""Autocomplete feature for gtk.TextView -This code is inspired and adapted from the Advene Project who has been inspired by the Scribes project -(http://scribes.sf.net/) - GPLv2 -""" - - -import pygtk, gtk -import pgw, pgw.Undo, pgw.Syntax -import gettext; _ = gettext.gettext -class SQLTextView(gtk.VBox): - def __init__(self, db): - gtk.VBox.__init__(self) - - self.enable_completion = True - - undo = pgw.Undo.Undo() - scroll = gtk.ScrolledWindow() - scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - scroll.set_property("height-request", 150) - scroll.set_shadow_type(gtk.SHADOW_NONE) - self.buffer = gtk.TextBuffer() - self.buffer.connect('delete-range', undo.text_deleted) - self.buffer.connect('insert-text', undo.text_inserted) - - syntax = pgw.Syntax.Syntax(self.buffer) - buffer_handlers = [] - buffer_handlers.append(self.buffer.connect('delete-range', - syntax.text_deleted)) - buffer_handlers.append(self.buffer.connect('insert-text', - syntax.text_inserted)) - buffer_handlers.append(self.buffer.connect('changed', - syntax.text_changed)) - self.textview = gtk.TextView(self.buffer) - scroll.add(self.textview) - - self.add(scroll) - - self.is_visible=False - self.word_list=None - - #Completion - self.widget=self.build_widget() - self.last = "" - - - self.connect() - - def connect(self): - """Register the various callbacks for completion. - """ - self.textview.connect("key-press-event", self.key_press_event_cb) - self.textview.connect("focus-out-event", self.hide_completion_window) - self.textview.get_buffer().connect("delete-range", self.hide_completion_window) - self.textview.get_buffer().connect_after("insert-text", self.insert_text_cb) - self.textview.connect("paste-clipboard", self.hide_completion_window) - self.textview.connect_after("paste-clipboard", self.hide_completion_window) - #self.textview.connect("button-press-event", self.__button_press_event_cb) - return True - - def insert_text_cb(self, textbuffer, iterator, text, length): - """Handles callback when the "insert-text" signal is emitted. - """ - if length > 1: - self.hide_completion_window() - else: - self.check_completion() - return False - - def hide_completion_window(self, *p): - self.widget.hide_all() - self.is_visible=False - - def show_completion_window(self, *p): - width, height = self.widget.size_request() - if width <= 200: - width=200 - else: - width += 28 - if height <= 200: - height=200 - else: - height += 28 - self.widget.resize(width, height) - self.widget.set_property("width-request", width) - self.widget.set_property("height-request", height) - self.position_window(width, height) - self.widget.show_all() - self.position_window(width, height) - self.is_visible=True - - def get_cursor_rectangle(self): - b=self.textview.get_buffer() - cursor_iterator=b.get_iter_at_mark(b.get_insert()) - rectangle = self.textview.get_iter_location(cursor_iterator) - return rectangle - - def get_cursor_textview_coordinates(self): - rectangle=self.get_cursor_rectangle() - # Get the cursor's window coordinates. - position = self.textview.buffer_to_window_coords(gtk.TEXT_WINDOW_TEXT, rectangle.x, rectangle.y) - cursor_x = position[0] - cursor_y = position[1] - return cursor_x, cursor_y - - def get_cursor_size(self): - """Get the cursor's size. - """ - rectangle=self.get_cursor_rectangle() - return rectangle.width, rectangle.height - - def position_window(self, width, height): - """Position the completion window in the text editor's buffer. - - @param width: The completion window's width. - @type width: An Integer object. - - @param height: The completion window's height. - @type height: An Integer object. - """ - # Get the cursor's coordinate and size. - cursor_x, cursor_y = self.get_cursor_textview_coordinates() - cursor_height = self.get_cursor_size()[1] - # Get the text editor's textview coordinate and size. - window = self.textview.get_window(gtk.TEXT_WINDOW_TEXT) - rectangle = self.textview.get_visible_rect() - window_x, window_y = window.get_origin() - window_width, window_height = rectangle.width, rectangle.height - - # Determine where to position the completion window. - position_x = window_x + cursor_x - position_y = window_y + cursor_y + cursor_height - - # If the completion window extends past the text editor's buffer, - # reposition the completion window inside the text editor's buffer area. - if position_x + width > window_x + window_width: - position_x = (window_x + window_width) - width - if position_y + height > window_y + window_height: - position_y = (window_y + cursor_y) - height - #if not_(self.__signals_are_blocked): - x, y = self.widget.get_position() - - if position_y != y: - position_x = x - - if position_x != x or position_y != y: - # Set the window's new position. - self.widget.move(position_x, position_y) - - def populate_model(self, completion_list): - """Populate the view's data model. - - @param self: Reference to the CompletionTreeView instance. - @type self: A CompletionTreeView object. - """ - if completion_list != self.word_list: - self.word_list = completion_list - self.model.clear() - for word in self.word_list: - self.model.append([word]) - self.treeview.columns_autosize() - self.treeview.get_selection().select_path(0) - - def get_word_before_cursor(self): - b=self.textview.get_buffer() - cursor_position=b.get_iter_at_mark(b.get_insert()) - word_start=cursor_position.copy() - word_start.backward_word_start() - return word_start.get_text(cursor_position) - - def insert_word_completion(self, path): - """Insert item selected in the completion window into the text editor's - buffer. - - @param path: The selected row in the completion window. - @type path: A gtk.TreeRow object. - """ - # Get the selected completion string. - completion_string = self.model[path[0]][0].decode("utf8") - - word=self.get_word_before_cursor().encode('utf8') - complete=completion_string.replace(word, '') - b=self.textview.get_buffer() - b.begin_user_action() - b.insert_at_cursor(complete) - b.end_user_action() - return - - """ Returns a sorted list of Completions""" - def get_completions(self, word, context): - print "SQLTextView: get_completions(word=%s, context=%s)"%(word, context) - - b=self.textview.get_buffer() - cursor_pos = b.get_iter_at_mark(b.get_insert()) - w_start = cursor_pos.copy() - w_start.backward_word_start() - word = w_start.get_text( cursor_pos) - if word != "" and word.strip() in pgw.Syntax.KEYWORDS: - self.last = word.strip() - return pgw.Syntax.KEYWORDS[word.strip()] - elif word != "" and self.last in pgw.Syntax.KEYWORDS: - ret = [] - for it in pgw.Syntax.KEYWORDS[self.last]: - if type(it) == str and it.startswith(word): - ret.append(it) - return ret - ret = [] - for it in pgw.Syntax.KEYWORDS.keys(): - if type(it) == str and it.startswith(word): - ret.append(it) - return ret - - - def check_completion(self): - word = self.get_word_before_cursor() - if self.enable_completion and word: - if len(word) < 1: - return False - matches=self.get_completions(word, context=self.buffer) - if matches: - self.populate_model(matches) - self.show_completion_window() - else: - # Hide the window - self.hide_completion_window() - else: - self.hide_completion_window() - return False - - def key_press_event_cb(self, widget, event): - """Handles "key-press-event" for the treeview and textview. - - This function allows the "Up" and "Down" arrow keys to work in - the word completion window. - """ - if not self.is_visible: - return False - - if event.keyval in (gtk.keysyms.Tab, gtk.keysyms.Right, gtk.keysyms.Left, - gtk.keysyms.Home, gtk.keysyms.End, gtk.keysyms.Insert, - gtk.keysyms.Delete, - gtk.keysyms.Page_Up, gtk.keysyms.Page_Down, - gtk.keysyms.Escape): - self.hide_completion_window() - return True - - # Get the selected item on the completion window. - selection = self.treeview.get_selection() - # Get the model and iterator of the selected item. - model, iterator = selection.get_selected() - # If for whatever reason the selection is lost, select the first row - # automatically when the up or down arrow key is pressed. - if not iterator: - selection.select_path((0,)) - model, iterator = selection.get_selected() - path = model.get_path(iterator) - if event.keyval == gtk.keysyms.Return: - # Insert the selected item into the editor's buffer when the enter key - # event is detected. - self.treeview.row_activated(path, self.treeview.get_column(0)) - elif event.keyval == gtk.keysyms.Up: - # If the up key is pressed check to see if the first row is selected. - # If it is, select the last row. Otherwise, get the path to the row - # above and select it. - if not path[0]: - number_of_rows = len(model) - selection.select_path(number_of_rows - 1) - self.treeview.scroll_to_cell(number_of_rows - 1) - else: - selection.select_path((path[0] - 1, )) - self.treeview.scroll_to_cell((path[0] - 1, )) - elif event.keyval == gtk.keysyms.Down: - # Get the iterator of the next row. - next_iterator = model.iter_next(iterator) - # If the next row exists, select it, if not select the first row. - if next_iterator: - selection.select_iter(next_iterator) - path = model.get_path(next_iterator) - self.treeview.scroll_to_cell(path) - else: - selection.select_path(0) - self.treeview.scroll_to_cell(0) - else: - return False - return True - - def build_widget(self): - w=gtk.Window(gtk.WINDOW_POPUP) - - w.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_MENU) - w.set_size_request(200, 200) - - self.treeview=gtk.TreeView() - - self.model = gtk.ListStore(str) - renderer = gtk.CellRendererText() - col=gtk.TreeViewColumn("", renderer, text=0) - col.set_expand(False) - - self.treeview.append_column(col) - self.treeview.set_headers_visible(False) - self.treeview.set_rules_hint(True) - self.treeview.set_hover_selection(True) - self.treeview.set_model(self.model) - - def treeview_row_activated_cb(treeview, path, column): - """Handles "row-activated" in the treeview. - """ - self.insert_word_completion(path) - self.hide_completion_window() - return True - self.treeview.connect("row-activated", treeview_row_activated_cb) - - style = self.textview.get_style() - color = style.base[gtk.STATE_SELECTED] - self.treeview.modify_base(gtk.STATE_ACTIVE, color) - - scroll=gtk.ScrolledWindow() - scroll.add(self.treeview) - scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - scroll.set_border_width(2) - w.add(scroll) - - return w - - - diff --git a/pgworksheet_yvesf/pgw/__init__.py b/pgworksheet_yvesf/pgw/__init__.py deleted file mode 100644 index eba0aad..0000000 --- a/pgworksheet_yvesf/pgw/__init__.py +++ /dev/null @@ -1,105 +0,0 @@ -# -*- coding: latin-1; -*- -# -# PgWorksheet - PostgreSQL Front End -# http://pgworksheet.projects.postgresql.org/ -# -# Copyright © 2004-2005 Henri Michelon & CML http://www.e-cml.org/ -# -# 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 (read LICENSE.txt). -# -# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# $Id: __init__.py,v 1.8 2005/06/10 15:14:34 hmichelon Exp $ -# -import sys -import os -import string -import gettext - -def mswindows(): - """Return TRUE is we run under Microsoft Windows""" - return sys.platform == "win32" - - -def get_user_encoding(): - if (mswindows()): - return "ISO-8859-1" #"UTF-8" - try: - enc = os.environ['MM_CHARSET'] - return enc - except KeyError: - try: - enc = os.environ['LANG'] - except KeyError: - try: - enc = os.environ['LC_LANG'] - except KeyError: - try: - enc = os.environ['LC_ALL'] - except KeyError: - return "ISO8859-1" - parts = string.split(enc, '.') - if (len(parts) > 1) : - return parts[1] - return "ISO8859-1" - - -def set_proportional(buffer): - """Change the font of a widget to proportional""" - tagname = 'font-' + str(buffer) - try: - font = buffer.create_tag(tagname) - if (mswindows()): - font.set_property('font', 'Courier New 10') - else: - font.set_property('family', 'monospace') - buffer.apply_tag(font, buffer.get_start_iter(), buffer.get_end_iter()) - except TypeError: # tag already exists - buffer.apply_tag_by_name(tagname, buffer.get_start_iter(), buffer.get_end_iter()) - - -def get_user_configdir(): - """Return the directory where the configuration file is stored""" - if (mswindows()): - try: - return os.environ['USERPROFILE'] - except KeyError: - try: - return os.environ['ALLUSERSPROFILE'] - except KeyError: - return os.environ['SYSTEMROOT'] - else: - return os.environ['HOME'] - - -def get_config_path(): - return os.path.join(get_user_configdir(), '.pgworksheet') - - - - -#Utils -import gobject -class GObjectContainer(gobject.GObject): - def __init__(self, data): - gobject.GObject.__init__(self) - self.set_data("key", data) - - def get(self): - return self.get_data("key") - - def set(self, data): - self.set_data("key", data) - return data - - diff --git a/pgworksheet_yvesf/pgworksheet.py b/pgworksheet_yvesf/pgworksheet.py deleted file mode 100755 index 6f01ec7..0000000 --- a/pgworksheet_yvesf/pgworksheet.py +++ /dev/null @@ -1,7 +0,0 @@ -#!/usr/bin/env python -import pgw.UI; -import pygtk; import gtk - -ui = pgw.UI.UI(None, "pixmaps/pgworksheet/") -ui.show_all() -gtk.main() diff --git a/pgworksheet_yvesf/pixmaps/pgworksheet.png b/pgworksheet_yvesf/pixmaps/pgworksheet.png deleted file mode 100644 index 24e6d3362ea3386b50d16ec5c0f8cbdcfeced9a9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcwPel00001 literal 1291 zcwPYu1@!ufP)Fv^1QZ-7h|~gu1qKHK76cp!SP&R!P+(OH0uC4& z9C%>C11Gt_cI;;-(N=EtziY~` zD*!~qlHDp$8Dl6*&GPfMJ_R7Qwpkhh;7932^BEu??rZoNsn^n{9r33CU}7oIF*c3# z_6g;yp?He%qohA=Z>_HgK)CRT7Jj`SIqfqB@=erQVsZmiT5H@O>D@yHPbi*ZreVWO zq*?2|OEVfpHeYiNdBHlGb;>oT+#n%;$pNaH)-R4~4)->GQub=_pbr&?>UXm}ydv9VX08MyU7U)i^e)2iTx#t3*2CFx9M&Q(1k6b|VSZ6`kIg@D4 z`U8sZnzGc^Tt5+Ic|jU4Pf5s7gVS*w=oP^mfcPPvC`Z+P8%jE9ue-Sh>E1(X%?*vS zJ>lSREK9a+Sx1-jG| z5vhzZthX7?ose&0LCb)CPhgJ*h$siQ2D_h_0M&1#s#1Z&u(VNH8_#YW^TV5O{tsqVRd{43_74C6002ovPDHLkV1i6q BM)Cjv diff --git a/pgworksheet_yvesf/pixmaps/pgworksheet/about.png b/pgworksheet_yvesf/pixmaps/pgworksheet/about.png deleted file mode 100644 index d66bfd7b02604ccf5ec74d9d284fa45498541868..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcwPel00001 literal 320 zcwPZO0l)r2cp?*Tb%RNC9{As}zd zO9A9JlV2=!ZLivoTMs#~e4St5`yNlv=PvKbZMS}xd+En5ykfx7ah2)B$;@7DoaSss zq=&$YE4^SkaTudIS|w}n`{I*G4+#SAXRF4jasa@1Y+nGZ%}V{p(L4o6Q*j0Fdce1o z^7%*wtrA3_-3fy~msr$jFk2k#4`?V_sG)}c4k5G#A+&>l1z198EsOH~LTJr@E4&(L2c`h4J9^0qcZ4j! zdNI&n&VlDZyAax1J00f|J&yT(+oF9B@3jmLJmt{gBjrNt=B)tS>blC4$GvUa{l2J_ zD!A+hLTC+As%TG7oE-){Iy)~Tgm%HsF6S>l7l)K8AMOaP z$kH>XP9UX9Rcg6DW%NHja=TYioG&svJ&AMgzA|4bSpej78Rm;7n_9hiJR1p~JYA*X zx^X>HMVjV!00Myn7~c$(QWynQ=JnJE0196vqa&}GnVMi?^1bbluJFYxRiwk=;A|*J zGC53BV-tp9kk4ky^|7~a0LbQYjE|2pH#(=yO;5!n}PMf@K4GIB&1Xbp&bRD g*-c(U4gU^504g%qVhqttJOBUy07*qoM6N<$f+`6L*#H0l diff --git a/pgworksheet_yvesf/pixmaps/pgworksheet/disconnect.png b/pgworksheet_yvesf/pixmaps/pgworksheet/disconnect.png deleted file mode 100644 index 0769aadcbba4111e2f998feb8a0bfa964a98ffdd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcwPel00001 literal 581 zcwPZT0=oT)P)+-Rc9(enTd4IS#?;ozPeM-p5^Cnm*nJ@sOQLh>|u3xpb8a02Qc6)bL&BON=?{sx+wSECG zJ$)AUr;C&lw<-O&_EvGVCue{D|c<541}0El@WfbAb!Jv`K>@w2z@HsjaQx5+<#%9m<|R;vZT+-%$c z3?WQI2-C`CGtAA#0cbX*UqEx?FJHw8;25ysg-!vb{WOjv0ir^fMUM|Kz(3*-w2J&- TB{7ON00000NkvXXu0mjfAfpTP diff --git a/pgworksheet_yvesf/pixmaps/pgworksheet/pgworksheet-32.png b/pgworksheet_yvesf/pixmaps/pgworksheet/pgworksheet-32.png deleted file mode 100644 index 24e6d3362ea3386b50d16ec5c0f8cbdcfeced9a9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcwPel00001 literal 1291 zcwPYu1@!ufP)Fv^1QZ-7h|~gu1qKHK76cp!SP&R!P+(OH0uC4& z9C%>C11Gt_cI;;-(N=EtziY~` zD*!~qlHDp$8Dl6*&GPfMJ_R7Qwpkhh;7932^BEu??rZoNsn^n{9r33CU}7oIF*c3# z_6g;yp?He%qohA=Z>_HgK)CRT7Jj`SIqfqB@=erQVsZmiT5H@O>D@yHPbi*ZreVWO zq*?2|OEVfpHeYiNdBHlGb;>oT+#n%;$pNaH)-R4~4)->GQub=_pbr&?>UXm}ydv9VX08MyU7U)i^e)2iTx#t3*2CFx9M&Q(1k6b|VSZ6`kIg@D4 z`U8sZnzGc^Tt5+Ic|jU4Pf5s7gVS*w=oP^mfcPPvC`Z+P8%jE9ue-Sh>E1(X%?*vS zJ>lSREK9a+Sx1-jG| z5vhzZthX7?ose&0LCb)CPhgJ*h$siQ2D_h_0M&1#s#1Z&u(VNH8_#YW^TV5O{tsqVRd{43_74C6002ovPDHLkV1i6q BM)Cjv diff --git a/pgworksheet_yvesf/pixmaps/pgworksheet/pgworksheet.ico b/pgworksheet_yvesf/pixmaps/pgworksheet/pgworksheet.ico deleted file mode 100644 index bda11bdd3363bd23134688bd42dee1e2ae50085d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcwPel00001 literal 16958 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 X;M&zIJdT>Sze0bP|Nr-Y`rrQmS`QGj diff --git a/pgworksheet_yvesf/pixmaps/pgworksheet/pgworksheet.png b/pgworksheet_yvesf/pixmaps/pgworksheet/pgworksheet.png deleted file mode 100644 index 8672762e613f43c81996154341d4a4b82e82e05c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcwPel00001 literal 14247 zcwPagH(1DtP)_} zhGt2ljbv$-G@2nRoj3PDtJQh(=S0Mb z6X!2ZJj3tsn}GZ#|G8x4JH|*Oo)88~=m+oI`{R$MRflIknt*>zkl*A#$KT?2S(c$F z3KX{min{_uQJ^eKu##SpF~u%5Un>J~-jmGFI+PI$k zB=kM>hfuPiF5S4EYy41`Zs0upy?)?t=8O5}DaQLKoSEO`KQC9ycaskj6nXI!bnXTR zh@uFcP6z&r4!WIAt!?wgd^4F$kfqrVA<;Yc;QPLktU(aKKlkCDxqH8(EK8($j_g~) zC3~JL3BL=dOEG>w#_;X%XcFnsFB-fZZ04WlI~72?A+GDfr7p-xWp%K7hLV*^!F;g3 z-~hpk0G$^d3zC?P%nQFCKVfAIT^?uiLF?u&T3L`!E1=C-qo8fS{b&y@ph41<3 zgdK#P5S>ov;0|PrA;~gi-x4HAg6t-HJcC&@hA%@zuerYP&;c%P3&h`ItiG(^oqHHu z4fd8SY|TKN<1rRv4D-(`%s)<$CTZ(^K_|duI%|~H`@+Ewrq}6a_;!dmjvMjRrHEcf z=)UScYCv{DoTkXGb7X0Z_-lOdveX~+(d+im?RFdSj4=QNK$B$U*Y{}~WBfk(d!PIH zkLXWIc0MN=u<09d5@Y#!iPjw!vOC;?aN14`(AGjGeRj^h~1FH0=HEK%eIx|dx{ zCKLGQ{?6yKqC`=Y07_)Hl?0M)Ap~$Kg-Zd?b!+d?B?7;ns6I)u9HWmbq}K&-LO=<} zOC|vn-|%fMwQ1m`YisB?Uq^-NragG5u-Ws3#Fhuv{$B?e1^(?{(v7 zJlaggliKyc+W{s&O|}j+V?cJ3BhGRpS-})2V?0_mL>Ar62XPne$Rc0)wdjRnxiO66!#3}JzqxHS~&j%O_Di?7(}f0Q7|5kj0*9|0x**TQkrTE}g;)4^cOO@3u>(*{3CjgQ#&e znSNYg_$JzmH+J6CD0v)U{%Nk3E5`V&)CX;q@&Sp{9Ob=`L`oEk-)#fB=J&|i22|o* zc9NQP9&MHad*~c-nqrw0SS6X#IXI(m+M1rP29Bw}<+GBxyfcbk$3t-LAq>2&bj?>O zW?vE%cT7nm=;{|S{%CB6x`Xk_i8ZGs3_J`jJ2e_4WH%Z5Z~Bdj_P%=2)*I%F`KBNB zjce4USS(ivgP=a}_a)}56w9wUvfDyP5mK$?tzX*RNni|&5Wwmr_k_Z8iIM=_zyqaJ zd#tX+#%Ye(mjrQ|D@g~kuLQ7Zto|;wZ&T#blA7ELl5k_V;vJC3ESd2}Xhg^j`Xy^qVc?*~b}% zZ-=$(yO^jE(X?#M7xS8hRTL$n4@+cu0r!NO4Q?9uZGvXoc`8xHJ1jnvCVJpe45P4dd0~uUG>kbB& z9e!Q&L(M)dF?>_+!&QJD`g7JU*3gVUta8mT%>k`{?`Se=eGTAOfMTOBxH>orasAirZ+e$7zc zGX&=p=ynjcvF>wUfI~Cn<_>Uv6In}j&a838fej%I|_D{g4zq!QuzjqalfRH@@ z^()99#4MJC3dU>vu4A|109tpog8_uB;Wz{*#DRk~;_DpWu5S@scyQ^7F%~cW%E!rH zIEerLR=mQ2gFR{0X<-nI?0|@N6ReSBx48K~cew2M=6C<&3*41=`1W_-)U`ERqxiqY zUtj;j^?%XteQrx1TbUaFG^_b?hO?DgwhUmbQtF6OQ0h2!ZBLwWPxXH$bc}vCPQ-8} zwL_ytTA1z$!SZW{=%+>PyVDO-bT3UW{o>OCt9WHZ^$iKc{+azr=Q=;|@$qk`>cx)Z zU=gR7EmNHSg#$wD87&+pSi@A5Eu5o?UDd!HIQhJsaRBbv8tz{beEgeBB^k*d2#TV_ zo9Pne|6AkqM7~>No+f&Y?*bqK=iqQ!ci}`kq!4t71GZ*Zeak`q0KE7QXG)3!{BMBa z>pv9S&7hWDi`H%J&~f6oLkP%og6scXC`qJ$H~i}m^Z!0q33UK)cXx-I|8=9JkRgGV zUzP^P4c-j2$->v@>F0z`V4|^glewTetqn&^X|NZrdYzn+lQ&&uRmk7tMU3K(35A*L zey@SINPaM_JHAJlCJ}_y^IXJ5cx@S8YY2s$SdqS{E^4fRZ zGZ*9cW8>OtwL8de!f$MjtldHKI;-Q=GKa%) zoO8I4-vyU_5Tm7rP_5n`me3gnA zmELGE%k^0yuh~D3#_`rNaIf|-GJQSeeTmsJ<@A#3{>FE2qjy(Z9@`H69!+PVggai{ z6N1^71k=xTCYlbq=$yOUzoh2o1KXkDxRC*j=czH~?wO0ui;h7t@DhbJ2-o1_9U2S=6JM?>q z{T#oWo)Anwr;3TBaX<*cWDtT35*diLpa09bySn-9DUwG;#( z%XuVS*PE5>)t7PI~zdEuPA}yt`tE&%evC6 z2}3PncBdQx2kwgRcer#^30RC_ndE%d+7Bq2SoOP!-ZtD*w1Z(gPDlmsss0w@MN@I?bw$l2Zq_+2IXB2#X$LOZXkWBGzpi05^4HJnMR>LqZCoZG#ej{ z6A^WXAbcsLk63n>NrwEk1l1j$wLZ|4$tHT++H&-E=mWM5$JA>mB}i@xj4aEHo={BQ zbhY;GXyYC<5r?PKFbhwu0B}(j0D$MKB-!LbJjxq8zA3U+*ClEZT=gfbxL1dx`%icp zhs^)s{lW24>8n;R)0=3{Y{}lmOs+V!5+A5`Q7W_!yl0?ivVu&uC0h zG9+nk_J?{_dpFrZZyWBI?XbVG4F~NWRH-N9d5rSDG?eOLFMxZhONa-I$&OX4ZP&K_JNvMVyZHU?}I6M%iiF39Fyfa#BOscyVjCa~JVSjpC z&Fx3F5pDEr!)f$rw~s%rjKOs&!SIz9D{GQK`_K!h4Fo!rrL|3pa6Wl%BYdGi%NN+n zdb_#04aXjcgIbChV>RiMUgtdT*PxGCzx9D=!EI~HQQE=G_togxhBNOWgy(Q4*G1(q z7CLPBDipeqRF)4M6Y(zU)Rks?>$-Q!@ihi=scZaQ-j}LPH8?2pdnnH8&@~WVn9?!H ziz+g$h_sb&ogo@UB)H&?Y{u5LRG`KH>60zos8JFFbU~2{jd$!6YL2Hv9m1hmp zp{*@X=?7|>mO9R+RT~>hxcefrcHs6@cA>T`ZllTm#+thf3?3-!yL??rJ^)re5PxCw zjsenU`Wdsf4Mz^gp~5jR_%7eAs%Qa_=YO-$T$lT&q?J$!EstqOBTl=AG~uA6YIzSH zG}Uzw(dP1wVexBv)(f5|C4ox3wotOpLYZQ$lUyA)!Rk<504FV?Gs} zP7JBg0K3fBUH5Fku{Be(LMqTD;|wIFl6;;qRJk&8mnk8jvg6lcpA>|(vaXz@s*Sta z^1ya%HLE54ko1Xt@06f>K|#+v_@~q`ui3q@lEoNG`nxYY?kn15#!Jv7IB~eMR)^Gz z&ilTvn5yOnf~{0L;%{34vz1PQcAT^-4#mmuYMoP6xd3Fr0=cD^72KTdT)0LB3w!Hx zQ8HwCf$TcP>bgX7Q;0w@0kLUOgZqef?1KYAA&PJYUh{6&CeU*dWZzIi;kgt=Sqg!= z{kz6R2k@-DbJ^3gd6z^VRSHDTSb@j-Ioft=D2=0KsWFZeOU6SK9xD& zQN)4>FP1%Bl!Ar3)$o%3pN8n|BN z>Zvi1?V0vm$~#-cV(OqtAmg&l?QB1sj@PbBuf1f5Fz^tCfss@%<7LDlS}h;(Tl1_c zoN|^jxGu%wT@TS@iTtjt_Vz!t9lP2nq-+T;d35HnB??dID>-9mZWY%l!3afgF4B8- zg`}>Ww9}-i0)b=>u^TA6Nz4*34&dq%$hT5A?Bp_Eahqi->&lrmqgt=+gR3ciRoxq% zA#^cc)$GyqoT5Zllss1`FSvdop7+nV!>#wyH=c7{is_pW(T8Q#$=hgqWE*8N;V9}D zl1DB}vo8teUox&J-!tHZsNa58_^?^0gxrnoEX5@?6f)o3>E!dcfDcvjxFGH&^8f$1_uk`+92z~Rq;@C-)JrHDdb zF=3XMSgca?$4ht~MLg-NiW$L$hvlS??r;t&$#_UR_Gn|t7)Dne^t-0c6TX`x$qG#R z9VD}UBV%+1GbPhH7oMSJ6?Y}dJ1qrAS1(#D0KdciA(_t{YuNSW zU5V@_gMaR;neCrZh%p;hCHj1qqI2OQxh|?|9>;1Us^tO>5WX-c@a#*1BrD*bQVd^*#$c*; z=Q0M!^*H~88TYXJN-3|D$#$Bg|0ncp>#L~6zo~R_&alF?-_Udzv9>Sb6w!ErWz07by0Y}0o|*uj0%9{ym6+~f6m>BF zHB%u08E5PGTAwhTrbo6>1L}}k8M@Wi4DJcnIrW{QI`fQXF)zL$mN9bb8SjuOspcmM z+JnhlXY{RlP)V|?(QKD^c@ET*$n0wKzFpCjiLXCNFjc<0Y9aT83mrz*v00`((SJ+L zL_!GCoL5aVKvOXDI|ke{6h&^lUwLCy+Zw)cXdCr50idU(_DFHhgbGD4`NAcnEEPEW zk|3I_kmg*;=Mo3-tl`NFt4VW5G=)yUz1}V*wOzh*Yqw6&sk;{(0JW00wkhvY?iE#i zVJKrQO!O!dSHl5dYfU_hrA$>f)kj%(j)`{=0!$V$04QBUG2xd4t0V(X2;#Iv7*yX0 zJZgEl8)nI&Z8VlLo;JbT$J;8i&_QOAZU?5;fwGCfOqm@ z{53{dma14KJ)v+<3Gza4@IC>^CT;(LK}ZIG-SJ}5x-!Z26-`mBImbAT$HEx0qEuyd zi6bNc0Vo6Vf~j}PPNW1V)I`x~dssW{C9SjuNJiMJj7!t&Y%7~gmLIm5GB*_8?Glnf zRK69unC#!=Yht|9_1wn#(Od_z&)!-C#a*)=#2Pu;`hVNcwtHG}^-k71Ta8lF^V&Ku z(>`3vix;Tv!{QC)nlqU0aP&Oa(t#e+4pRaUa2JEoHd!%N@=IenfY~Q@%}1#(67118 zgl|d=&RwOXC=G!@`04UdsE@$nkbvs_JvK(yD=-dQslV z`ayQzSTqsS8rAzYz0PZAkF=dBq8O-m*)tIGFcry>fu|SJ1a@u}K4KoRaSVV|Ku=Jw zvff4$v)5jeI6xXrN(T4=JZ zMmd6NdE=MzJChblsM+4y=MHS6HUWw7y(Fn=)pP?-NF+;Q=yYfj#j{)iMXBqC+xmzv z+n!5m0o>`#^gjE6-`eBa5@z0{M_{Fh^;}x@lbTuV$bKN*Eg%NisLb0e%D2*FNFd!} z(`K_%Ng&nLC)xnAw(mWpjnyT)5{Bzi_-8J61_GwUVCK8q_G)p7*3wU!w(Z6|{l-$Ftv+HRNZots8PCpU zv)cRY`aq2g1k^QcS&2$1TNgZ}!6X;i+lO@tpzz}NLvd;*QG*tlD{OpUf5ujJo4%*x znyOM5A%P>b!`i+~z!^v>?*bQ`d&+;snrM|d-)p9pT`7%R3YC7-+&BCkCF24?=6gx7 zt*`E7ck2=21_OE4S}3b_7!E}hyRl4Dd$!p>55=Kbi3U(fpr+@y(PTT-wDni-Oz!!H zcF$wlQNKsJBC6^lm81_mijryVHKc3hny^DWRPF0)cutI$tny}W)QppOZ|kd(fow%O zy-wAhAbuVdg?~m>(swnhP?tcq?(k5Y06n1$5GT>7bOp=Ok-y0vI1RxV18dv|#~$Af zW=RC)j(|F+%owT5efmEv<1OTC@D{pdEX@dd{bqrG;++wkJ9vDlFp)Bi5)}A<+QqF+2xbaxgc=fxI zg5^EK$|`Kxe-)Uzw~{2)yKI_eCZ=)gp?bG}AT}4Z6tQ11CPf8hk1MOhw&>hqh7S`CEDMC~NN( z;dLO(nsl?w_In1~GIgotZjqfJEH5}f&pO7SvAFrW`teUT)ELO-IvHfG_Fs!2qwf7} zENXqAkHp4R%~pH6bdaYS8vUftP+LN^;b7k@B;0z-J&$dp)lLGQ9A_8#jzSNF@a0-9 zR80NDo3aLSv1>vp($d|c-7C4ZWPIP4OHDVx{NuzRkGd4yaQE4%H3sUvHa*g|L(z4q z_&Azpc7w@i#LM=@>EApdHIub6b7farwAkiz8%_)+aiC&k0JOw=eZY^@MmesUq-6|P z#JTuWOjgfBx8n;wwAvvW%ou}IgCxztsbD5cVo5%>Bkyq%*U~fwgTXG|X=Wh*%>Q6q zSXUd%B*%6yc)UiL^MFPHHEQ}mMu8>9R`pS^OQg{t8WYa zhqe(g+Q}F{FLm`Tua)!dzw|{$s?`pS?m`+mQlg!DT9~7{w_NiCd?VWu&B}AwH3iAu z4CI}Af3zJ(i_c;ilMcm~y1&RWQ}r45D4clr8Y+iJLS9P7((Y?|cas#TeXn|tU6rEI zA$N?71H;s>3X5Y6%vOA|su<*jXO(QJ-c=bCFxug{w5Gc;(U-l@+`UnjCFURJM!Un8 zVdLq9dod6I_!p*mm&A$5WUedvL7(|(m?hTF!8jQE;w2PCDQ4J??~*-msAjIcd9k?H zEaqKpJEV=aB#}ai0INjH&lYqIdvd}u7`(!G|CsqhHdJkNPYI$|=Ge~X^IA~0c1ri5 z3}pL*vOF_t#K?_(st+`4srqftz=z;C*peZ)d?tpA-+q1^w2`T2ZrENi=!Jy>_iE8Q*Jf>5_Kfv@LP04H_A!AN8LR zEm5h+3nU3|l$;eE-!mwx7&3oN+w{~4nm+tgD+tA8Db_l=b z5Ar;C(wtYbK~oTq6^(c5sh`z0BW)?sW~A}|Z8*)V-RpS9H)H{;n&<=6?$PV$5Z>9&K)r6yFz54|dX z)fDCS0vZ_eE=;wYnfba2yvs(2y!)eHbY73a|m1OT(? z%=mlseq>lCMwTKgnQ|)DGx}jFzDKlN%6o?NCg+!>H(XXDWxR5c z`Amai-}2rj({{enj!&@L^N4m-xGnG0@B{!HzKvVPLN(JJ&#JZAFopZB>eg-g&aeG?3S};WRuU zT=Gn;qS~%YF^W1$VPr%TJB{bRLs?!_JNZX03vrqwxh}-+P}^F1U_07yZGB_(0YJd5 zue>NZb7=HNAwRK4&j*^XQgi}OooFp#I-MdHYJh~n+d+L-@`13EfdHOZZ4mQ|>HZD_ z5ALa!#I!Adxh)9UdW}2Tnw04%3=q8vcnP~kOV0XD2+DPJt^_BSe`A^G(q{|3hqj}M z9zwR$s{NmUTcdIrvn7jua$}m8823X1<maGB&PJmp)i=KA3^*Wo)%t)s(s@^ffQ3 z?$^-$FAdkW;q;UTfgXQ~Yu}#qLxcf8_EGw!)bWqTZ^7bgAQXNd3FUo>RgxJY07Du+ zDkyB>w)KsU)7nn}5blxYL&)D!-p%*2QyGV>OV6MU0qlE zhg5a+mqC^E)Huro5THIgcjG7_pp+oLEiwPRGQLd+!Ten$n23p(l4eC|w5X)2R~@5` z%dfc@KU*g`oYsSasXK8TFE8uW)O1Otq)!wY)Th_EQIZbe0n^cF^l0e=?8!g?(0yet zW3{c%E>Bb{rH53hBW_lr3Du6Ba9->7-cCXkv1^kI}$ne<}@NCJlWX5505?q&JKI+wsg3-IWgV6Tx>9C4do8@x3nJ?z* zXBDqDZTCCa6Qb9VQG_avW2DzPf(uX8)akzPkz5y*5W%^}i&b71B40+-0%8EWXXpyYo2-SCUgyXQo)uWLkRC$oPTaP>(Qrx{ zneCV5?gp0~)ehgKHGj}zxlp@{C4^y!Fbt7irnfcfsC!k~uU^)vo8t8A7eFpwMD}m)I(|AirdyV8qQ!qjw`{X>wFZ} ztSx;k=qYVXhmnWQJOsLzU97&W6yNNCXnHa2bO1s~<=lhbLAB;tX6~LiR{d_v zl~zA%2H*2A9dxnyDZ*mh#o~Pzi}#T_cV6DRh%=NWfZ&VA8 z)Nus7zEAoBpg>dOk<%dT3|4w69Wb-J-V)APj~QLnPnijtx8 zb_Oa6LYm5){0)&LYmS`j(-%W9qE-x>NFz?P$7ZADn1A zV-Pz_Jq#|xnlCa=Q*>W;4rdexpr;gpAHeguYLI+Oc(G0EUDJ;X4Btf04%WoGm)*_k zOQpmGoj~PGOI>I$X)%Fyr%VakhX0sXk{UL%2 zuXzmR&IM9G#r)S4?uq!eD$>m!*N#JXuK(u2J-50p~=b4t+(I_Pvdu+L7B@9JK5jqFA5+(UkoAI?DY#eCC``o^_Y zyh7Ni8Wg8F2GgaADx010(CNp(7|+%lMIEC9CHNOU_qIBGXF-3^N3Yv!WD?^Ga!f6l zeMvC;oI-}yn)Q~$+i@5UA~M4#&giP6l;=Z0U*2~0M-wcT3mD_h^{8hD=|BMY3E6o< zwQV6mwH3w4yi-fr;ij*24vu@iVjkV0*aPLN0O5yn)darxvzv&}R;##M+ z_2=NS!)Ly1M{V36YTlzA*YqqAJ4!oVEAwPUX)uZHWR&S4P0Z6&w99tZx}I;^>}ziF zAIv~NJ@I<+X;C}XPHsi1PE^)9?tmz^+z(ZhjCbHwPrH?OMs!s#fUQH37g&8+VfE_@ zzBsO0e}48Q!C<;nTZ@g3JJq&vV>_+;<6tgnHdxPADI8(#*7+($Z!||VS|A!PRKWQV zDPyL>wlH;BHq@k~hbhtKv!+QOT}3rXG?*^2O7bc(OAbP#K0r*I)*zWRxOgAc=;*)c z8~&*_pe{xHYYh8zqUq-tlSQJ=$BJGBm=3xIe)>68)!{4HvmK4NCVi^G{Fh@V{5;D^ zzfSw7L`atEG53@!*rD%%oKlgws4>P`NObXMn&rsy67hA8;M~Qe->peyyPw4YJ%{T+ ziaFj6HinDb0g@!+jzy`|<~e%fDh-ylDUX~a3rCc%r*rONKI(x|v(Wf>GR9;)*^A!g za#_p7o3B!g=P{4=i|-dD!(v?dma?McM?VoUQ@1I>jqPZ{>As-`oOVwMp7=KI`50XF z8v9o6=jRS=rs9UusBtN&xs1zu-nS)#I)iNVx`W~CfLATk`gyflq1Q9BHp4JP9LI<2 zKoUm7(FZ#|Hl2=nS7ItzFz2K zKI&odKH_;rYqQqSV!7aw$I^YGt4Qsg-#Zr81hZde&){IAe_%8k8GGpoA(-|<^nO}a z=b>|i_NKb-gEcUH*Hiu+mGhFsjWdF}6x~-{M6V;bXMUp}NFG=>{J27K$IQT~97@J& zf!3;+r$%FAEQ{@jv)gJsr{B}m>w;FX^i;*s1=?W^l{uhJaSVJOKMb{R<~42eECbxR zIsO#$W4&dFLVR3#dDpDF8dHaRe*OVu~gUO_o)j4SC>nTN@t(S)OC^ z)40{5bv+lWFROnHE&{^|_-F|P0JC3arjoh_hHrEe==!m`o;HvloxXKmg!+ z?#3<`(k3yoJjWu=k=+(>PbmhyPAwq{;5wGv_-5xH0el9HKgGh8&#zU-Vv@Q#!FWDR zd0*|!7)N1s;9A4!(0+dk0)oB9tyTGj$sc=$!-{(b@022*_Kn*I!vTVe0AUz{5~_lv z>UBaN%5F1c*BO!|L6RgW?&>EoH-Vk^(*{Rb!X(V+^IArmRInuz$${}b597XPHd@m= z0PgG2cTMJ2&1$x0Ag8oC#xk$sL2NB5n+ku2lqztzZ>ihy(d*O`&{c6wvTKA}Vq6c6 z#@p7Jw)W5lhTOK~JO+YJfZ=dh-_F$nN0mSTF#Tn^Y4XuDNsq1X(Ik%!`AuFsBv?XL zlqiZ4*=>RB)(kEZLg1fKgcmL-p+@eo&bZl4hUqU;BX8L6Ppbs}>M86kMh?Ykw-omb z!I>GxV2m}UT|5SYPJr=fj9#yI5KkPPfh5#I9U6pTh~DcS{1+Ygu7~ozKpe+dtyWy| z-jN7JU5e>+S~K6JGEPW6N2dB+S1Plc45QHqGSA7>wSZu-g@GQG(uyrO=`gIPa5RM$ zb^&!MIxjj1Uxx5~AKtlFv#1^dPsTt1FdC0G`^Kuafe75yuDhO#(Yp~koo;IaSsRpP zi8M_y{bdS0K@Kn(2oOs2$#)8-S|)yeS7Q3MtE@wy9s`_yT);o4D2f799tlAS+*9`` zOtKA*ssq_D8Bd_ zf;zlI%ex%eO@=Jv1w&WAu4?aV0>-$BUn$k5^HYT(nsl0NIJO%nS76^d7ghJU5lS$8 z6FsRQ*alC^KtQ#(zRAqr27cgUI-Q~$cAw3DnIXT)f9_rN-nE&XS(?=lT-{!7~r3qLd33^%UazAPY(|crXC85Pm5>ib&A2;LF);4uID1U zim+TRk)_!){j3J>-1}piq|YXk38;Hq1#&MiwrR-UPY_J4J_s<@$cy%o>^~BoTmtE! z*P%(T(+y(;<(khX_kC~EjTx_P3QDe;J&>n~)u8eP$kd0F134*Dt zdY*y7rS)T(%Ddf5@Arc5%0N0irl=7BW8I(rGTkIeg5tJ7ew%ZDQOkxp_soUw`Ebu% zbiy8nZ=z?5PYX>vY4* zy_Ckl(-RM!7ydKpE!P=FKXAA0G-M9ifIa2bW=4QD53@*`h(l1^?&nGVUhrqZKsG!? zy4j%s1BWJs7f%;V6~EcNc20=!q8Fv9|FoUl{Jr42Dbc@qAY0rey18vIgJz1?#&H`C z*t)e@USHSG39yL!r8At#n)TozSvKD7u&6=`2%)4+p^Vnz6Tf0)+CXc)2 z-wG~*fBcdCw$~CiU(7e#@cSkoJ=J^L-g5|DqF(Yl0AM9gb(M>Q>rxw5I?NCD!{j9+w}fuc$6dY7)o=~JNi-o*)~b`R7$meQnej(s%0eVIn8#a z{!W~A4`4_j#(==eLQJo7(>LYPgLhCo1stRU$>)plpkVh9~pGBSvQ#} zp**0v<|cM!l^r1(uRPZTvQ7XYq?SmZWu^k%dC}RqE%|#us{}ffA&xDbegx1{Pfe*j z&y^H%T?)_TdJr|1vPYQlHcnf~yfdm2>E+UC@5=4>w-?y@Ua)lu>qq@(4`HMq-Kd8` z=Y{`F`c_!U>+Q(wME8_e@G5mv+x{`O>NJ`0E%#_8b*28Jd!dWl!l-mYC_(3i|C^Bb zd!HAk|NLm8pAvM-CcRFT1=Q>KyoMsSNT6Ny6Wi`F!WY1xYntcjwRzM)|Em9^yGg-= z9ErOa>7i2Sx3CQAb&h5qXX^i9;K4hkDA(F9tYbyv#eYg6ee6nN_HmWH-w*@Ul;}eO zle?7dU7(xf`g;yF`;Q4CL4N}P@z>b=b~nIiwgMcXv&fugQn#e)ro46?Fmj?9 z0t)i{3$|vMyy>FfH4l%8lh`Pi6LbQkN&1^%9^i>$VQtdtDc<{J^b6T6&qR|-Z5RX? zzUH+GmHtZ_EUd<`1qa4}V$D-VJeOkeK2pr1f6Fe+HQ91h<&T0!271guJ*9K-d+JAW zx9V^>L~&~-vJYQ}7+iKx+?V3~F5Bm0Em`88k}(t|ukq}iQjGf{R+Ff9emwy6UiXar z=fT^-Z))k1u$7=g2khASK>L2{*h?6|Poj~_NB6Re<>zJXo;Xc0`k0`&V^z$`I?+a6 zmlg2?-$fJ#==d($c9q)aQpmHp9@}S60Y@3|r_4y)$LswR3$O!_V~k;$WJt0C zd0s%J5jlWM3EWc(@01`o_iE+z?1GtDo?|!|7zgDNN|1a_p1jV_pFQZuP=Bv)Cf~9R zxJ9-Buo=7^Y#3v$KV?~Nio0S{6vd{vE1K`QFB`8gM38B zpms02o1!STGEy6J+1HAq*i1hzHm>Jx?C%gtHmfB0oq7JHgE*ns_@OS{On;dk%tZ2M zzL;;Kt7t=AT6;HujUV`%^g1mbO!V*Y+k&7IG!8TzY@(}Zvs$e-`AxnliegiirTQs~ zVv}B{n^nBpjK-r)&1B%EX&NwVWON~a1p@sJovs3|H6k}IP}i}{yz}xw`8nHQ(6E3002ov JPDHLkV1fu7;%%EgTw)5VLMO)0~X)_mf<*1fFPM{?CgbI&&JwV*+a*!jeef!F zzTfw%*d&`Rts(_Uv&mO{_0I1;Uh&Zrk3W?@`_Lol-?Xe{L4RMR_wUo&LvMxN|DE2S zt5&PG=x>wW)eGOaaOsUpFaPM}i!Z%);o`+hm##d2;o@WGU;MRy_WZq1J-2r9xwXfh zJO2kST)6n!mFri|{ksbfo_pcB7cahi>5A}S{Cn=X=iIq-SFT(+|L?z%xbIoaU&4K5*W8`26|bJAdKAg%@9Z@$9o_@4fHd zmtT7=`@p$SBJ|kF$1YvDm7Y##A3UG6vJd>j2h_A`tyvE~_Mk-_A3SG0aE@k7Vkg+j zFug;+a9#+!>2HMIKBvK$bB%VRR7_Kuc$9#%c;fM6j~-uq^wf!mg}kqXvZv2Hee!tv z#1m(ZpE`Z~p))6*eByL2oPFfchn_t7pUVrhIoyyPAdyd|I!1n$x+{X=_djTQgy-V+q*n|CmbB(`n$91IR zI@)m^>$n~idt*IL?_kG07uRti@jE44{GK^}_RQkRV^1GHg?7NNCyTnYPD|E-)+e8! zFP}ek;@HXbFPuE~&_8i27f+w~t>fv!+8&hJwGvQIoj7~^Bw+j)kqWT!G(-FteK~gW z#Ie)P_mjt-c=RhoWNG~uG4z*@oj$(!@QG8Bu+k^boTAEpl(lM=)>e-6x#%R1-}uVu zGbbK-I{nabP%DOi^6cW{Pd}BzxA)bf2~%(@mIfJArx+{{;R*d+NfW>_|tE89{lfveVF&&iwg1*_^9S^;e&bJn`@S*SOY1wh_v^H})&sbD*=c2` zKG+TJHedan1>CxdTZeF^;p!$gA|TBDm^R*QJs-!Ku*{YZjRLr8a-*1N`2Nw?n>3dF z(f|>rY!zy^s&T7?sK@{IZ~ccG*vmght7~*`#~`j-65x$z+A$o%$hY`66tzU32lqhJ2xAKh%) zcVGY0<1vyco0YHr)s1HT>UaOe%D>t5?6w}{cC(`Xk8kh3;uUM6IrV2>6wi2ATDTgJ z#l`1OojURD7fu~te2TafcmHn+F88mW;Bo~gZhy_Wa92w62VWt$H`poK5!cP#r87!?qAoEMe#WnqNYwD!h7%$C*APQzzRYkqAw?Nsnu&fTK&6(AS zC1t5GvA#C0M%CK*dLgi|s(RHJvER7rSL} z_YCCo$-I)c2NWWt7NlHlzObe)fu`xJ7aw%Bh@J(7gyL0ia5x%^8%15u>c!k(EIK_p zreFc7AobpM;6ihGX#QD2LnvY^6&}$wGn3JE%V*um=o!=0G(8>(=NOA`PnL{oEQPpZ5E~mc%uLbn8n-G& z86ELy;KE}l*}86O=`flNMNBhG0HRsfsq^&^RzEbNWs2Ns16@3omQnFl?iiJ_tjMOL zSamHqs98n@Fv4bAvsBj@h-+CxF?PyEndYRI$7q$YZ0DJeV_>ogC6%i!rciVXn5GN-}wNgV_1po*4KpxM8* zilv85%K?{!H+HenQP3hXIpAs_XEI=^EwT9;4bYmS>bpu#FB%d@*xeN_H;laku+x$d z$s;B;*yeRr6tO@<+*-yOCezspc2EJjTJ4W2Rx&4g(1>d+t&6vMV&CT#|+?F8w@DD9jEv}vDy{`5MZH|VoM(^8vZ&61E% zDh*>pgn+a)Km&Vm@U%B=jmad;I4$ZDnI5A-vjX0)l;}pD>dOpOfT4`*-a^mO#%>O4 zMZ>A2wqgRS2E3CRHByY95?J>^+9?bTw4uZ^H2GFVqM)Lz&y5R037$j16691 z)b2)5x1Hl&6B2Wm0YP=9o4uK zf#m%@fTsmmdJ+?kOhtgfO(+Tv%f&~+o&;pb3YMW;dkkfCF`u{6V1?nKDI598n3-16o+;(99iPYS zGt{{r*ZcCF*Rb_LGFAR_exzt-vc*h%I2@ji9S$t3>Ue-U5;GpabBsED5MUBxWE)sS zrq}~%?4*F``vG`vGJPsSV~MX5&~ui?8|M3=Z#LT zBPl7n)+46GE;A+V9k#-^0RFHmhx&0`8RA+I)0o(4#P=%FT49O(R$jLbAb1p#XKoLt z+iU?qD@KE?4Tj$u!Sd~#?kKc=@VD4zxXME~tt7q`R{q}{2Zcl(GVHSmFfK;m0XEue zDDN3fkUnoung{S6KBV39!LZhD;M`QC<#U_qh-@ZavC+eQn+_b)MhAl`l_r%SM26)O zNMOj-!rd&`lu)csYaKl5fo-EmD1LJ-C1Fsh9H9H8;E4cAhOCwaTnw0BHOCC`^c8-< z0@LtyqT#kxDhuXDu=6{hr;wh-xP8z-n#L*)QIikBN{-fZil}s#*hL)>Km}{@K!^UxXlhlC;yrI{B!6(gI$^r`TRa1m*UFqOPO{*oACL4P*NXSFsrLq5?MONK@#l}Tl^5l*r@c*nzDvp1PLOgc|jbdTlL zw=-rstw)DLEC(^``=KRO424HxIdbQ;v}S6iUW}7p$O}rw-~bL7O0k+X$<>@5BaN_= zi0Dw`7E!5ERIDBPrkU~Kq${E~M{^{#rNE#zJ4FM|W;6*zn-(0(7F@^{H0~y`wqDdV zJvNH2R|$Iq5mPTqjqEb5V$`#y9)#e-MAtjTp8I$a9i+oJW?x|8xc;zzb5yR33lcHBVIF1b*!=i4+ zlBC_L3az}0QMpOIn9(Qu>t|nO+t6wG(_jzc^MnSOx+f^MZ73vvhc?(EjC7z zHzo;jdozEH!EY3;k1&fdxKYfS*)VUP2C#Y?d5oVNprW0Ex1X7$1$I<(sZR`=$hKZP} zO3cib_b}!)e0_Y-25(k@FA7wkBl(Un3s8$TzREuT)4>DBFo;0F9QBZyEw+{M?;dFH zb{1s1W{QyDB*HDDvx^J8{*W!Z1#E6M`fm*7%wlIB10a0$qfjdg5Q!F{_5Y6~+YBAJ z{kc}47+)v2F$Bnz(L4I=p`-jU1?dod5KPj9(@tho`%YiJ@^?9)2>oPuWl z{YYdFfvjXnd9wX>MAu!We^&hAM==y@SEs;*Wkv<-*X)Md$oLqB!biKH0bl@(5g-42 z90gF_s&uH?q6ycx88H!@y67VQ=UV|rBoU$k2;WLdCmXFk4qIKQ1#XYLN4)7=Lpxp<8AVq0sL@<9cNTmK+DC4XLy^ zv)%#lHp=E;o-Boz6frcIaqhq%La^*0!AV*(FQdfG{OItsGJP{K3{!3>-kz4wj(7#! z+CG?qV1Pe!LmAFa9j2FNPUXA;1IR#G8O|;_5JhI9PP6uHUPXqZa$|#si;>aM$q~KC z(ZPWnfekG=R#6{g=zBVl)si8lNow1OPYokH-XOe17*|<|D_cXT;b&2^EcvNdYgrkf zwmCVKrQ&-~-Fj9-NIvL@xUw-kHAX`WBkCaG)eUqji}_=wj_}+Ed9qB|K}@o*fd-Mo zF#H=~=m*8P)`J0Bmma74*StABYetjF$)Z`5-Uj)#it%5VaP%nz&YUn~?;1!ZGQ5lo zZAXLIW$0{bM@$F9MmB>M?+xl5NZTvWpMWq#K2#9mk?p6L?y_K!w+Q#O>}V;M(dw8R ztH13T%((kCGRRrhiqPRQ-qUoT95K5Qh^4ZH}^3t1`-&g0}N+ z90ucZRdYZC^IqLg16dO!QytJ?tU?(!H+a@tNi8d30!Z@i-W@XA#z{Btvv|Ebn2~h1 zVQ6xMy?7#VH}Lc`k5Mf4U{Dr%4q(1ZUaC{ei+C@oxov2uOdKZapx&L+c$Gda4S_A1 zkEJus4_TX+vYJ+40i1~G9G=N18=-Dx30wh;vMyTaYCmu!4FHxe*m;8)`SwC$D zKOgu1W|C(FxJW8^Ji4=*Oq>jCX9Sn5yOBVIs)6%16@*q{Y%p6i42yACH4}!DvyoBD z{W%THEBj2t%SDtkC!?G?#~aF4=12k(UFk|EDq>LF*jEY1vomYTg;(5mWI7k?ArjW) zxg+$vwbvB^or#nnJwOiPJfBXIH;_|oCCCG`1M9e4bUj#cl)i2+iuTBe3UY%1=L!V6 z%}t485>!*=X4!>H2m(az>6*4-mWCSwGPp!P3+wR zSp^2>u;SLb;F+up&yB$P_E7>XL>7Y)3v3($s7Y?IT@*wV=FTjtHp*$R0s=c*;~|EA zQG$9=M$AaeZnzA^7};JI+{}cKvK8KIfvT`h#zzn<4>7j0F4jCM>2<|Ps_+_H>vU&} zda*>{v>dQcLmL`*LN>WIPxp2&R3k;0bDt)h06-xn0KZwfHOJ|f8WTcZ=hS#?0k}qCi7dfpt;dkQ0Nak)MuqrtU z_~m6a9S%#l9KmDYoI^VdcL~XjzUBf%Ob$Vl8*#_U-Dnrsi4Q}J)753@L}S0QW@2I~ zWgCcSZ+6}x{^dM!6>;^1nRPOuuD&LN7@|A_HBwbL>gpsx4aWfm?{hk3QNSJ~`Q2l2 zc^zd~8_RU2*+@sy^lca*q`j?>v%{jjJ-^My3jo>LOcFaIFx;dPZgv$m zb5D)aZM-V}+^I-pfPCLZItLk5CuNWpeHV694+dqyP-rIE@@R0C!oFhJT?3y8@MD|PWJk2swd;)%9cYXSM@h?i z#yDuWoy@Q0r5f%un`u5B%vNVz>3XUXhYcaQl22UK4ZU+_c)%6V@F0>%F~_9u2uE9z zL2wMfUQY4aP1eS}2y`OSjnOn2JYJ5)`HU^yQD7WZ{}!jlVK?{jU1Z#40Ou4oWF!E! zhUVx>d71#p`FDrndS5;)vh4V9TC=2)A`e37SscA#66B=HyJWRW6Qy&0>X2p2@$Nt| zv$p`CWZF5_M0(sK69XNT?#7<@$b*!3jj(1F>DIQC76407%48BHgn*nA3G59hAPmxs z@KKR%NmSr#k5Xd*VgsAwxN;ocZp-}xLpNEgDN)VJ>JloXqR6yJL6No~wCmt;R*GGi ztHGCNh5x=cs^OeS8PU-rqHTPLk`w~u5Jk1Fo>15hN4iD>Q7P+rXRCHKS3lOdd z(-Mbc2_N*bAiZ@9!P3oS)YLMT#Tsuws%cK8URH7k2w?<)G(?fN^O0Cq)8PMl+=E@V zU>&&(9mRPo4B!L|x7c9KP+zp%Lhd#nN-A>VfIN1DFi%E?x4KwP(OXFo7aa%47|D0n z0fh)5Y0n_{R&Ha9aDJ$5pnyz;!sqD1js``}p_yc#+%9+HrjjMj@QT`sIzBOrGh(;* z@IwDZOlj3%OOi`YpmR{55DIiH2F4^bg^;tS zwxc5I*rPmEV_3_!nWd>4M+DoZG|MiIJG6YyleTXhw%<%?0jT>>Aui}d0-FyE$wSom4vri! zomv)0Girfxb*3~+sC$o^4@I?XrQ6@2*9r?L0PR{NZNVQbTImQDm|9T_$mPl7gUL7v z{|b31t$EBhK>*(#fyA>UvYHd>9Lbw4&)8_pL{7!ngH6L-YKgkO4{K0(hRrm+riBFC zio>$o`O)c^p3Yd{t(HZuk4+Msttqdl=cl6)&MX{KRh;kI4#qgslP$6)(zOnJY`akM zk&n_~tIy|T+vi;Cs_q$!@Ck%%Gh=FL&4?t$kmKhRz==3n*~013##nMPGNO!Jj!fnU zTuZH|XdyRdlPl&Ic4&#{-d=N#Tat2BKIn1vKb$w3BzU~G^6^}+pDF*+(IZAoS!R{W>i95-Nm|{ zDyai%ZI!svzpf6cZGPElkLD%bX$A@tJZ%X_%xGrlgHCLKgf$#bK@wJIkqL&s$_eD>oUu+KrLcV#QFPIXa-(&H&x(4Z6c$5}7 zsGQndbb-+Jr+uGbARh*DK9)Y!NFL?&-s+ErV!OE9uMvNI?h^uK|LN-g*CSm1xuI~S zUn6|HVr*n`5Y(}Z)DS%?+t_fe-ptQFyK3bdOybr|3!97 z8xfpzL2QssP@4}e?7*uvD(wGOm7?^G+`Pi8SX0H&tqlB6#KJeEdL|Ep&!ymOq~rG2 zhGdjA(2-J*UK1-pHpR_R;;Wihq7sd=m4S!+JwDvgKaqnaa8Q~3p)x1I z@_MnN8wepZWzd&>)?P!sB6CS^VIYnv3K*>hyDoV>D?>*@hC7?^n-$}o{tlB-b`xoY zAhJ6-FhSl8U1Je9=j91kvKTAf;Z5l;y^qycgd>`7ShIAVF=-b0U~O}ijq&yg;JqxK z$EbpGoMT8xYM97UC)0WnChv#yDhK=rEURMdpVnJJpryj`qHAGIM#VxNc4wjB;2A>Ujaa$}2s9#74Ee^qs=^Wa!65jiKky|#l@WjgyM+#8G0nllNZK@3 zRTbm>udov|@0(X@vmo0iLpq4HF*IdhIQEsi;+3drv?uGo0{C1`L^UkaE{Bn5;`rMR z;{u55OwczB*BGmC5L!lfIm{z+90ofigHZBxT4##h2}^9b+^@$;6*ZGn^57)Q(ybXX zu5_8E@OF7eZal&*tF-Z9DXr`nBnZcnwhjq_yg@&tH5{s!r56Vbibx}oyU!sv#I!gJ zCxhm1ln(-Z#c&FCE+vhQ@d23$8se=5A%aV$HK7E= zWV%>n3VW^maVtQu)x;BKHix3`kPRF^teHATKsvlzpFBO`af{n1vQtx>XB0Tqv?<00 z^3ypf4VC?9bBZ0dsN=(4Y&!%?%O|#mrZX9bsM?29H}<|M;5a^AK_Y?GOJK1yvAVLl zir^iYzmqUL%l)v%g_lfH&^d`JWkCES!tsZLNm@pGedH{&A`6NiPL6PBJ(bht5ut;a zX~Qx>67|toHWnn$yFN^|ECgh8n6t!}51iAD0B#PaP2JSv!@;p5L(0%jYQQ9cng)s2 z#$-^ahmkJJ5p))vc_MxYHZsMHoF}K~9*4q|>_?!)k$yOR^*(tWSzXWQoctpdKz(yE z)X~dI??_NtEGxrP@`0WTb+`0Pnh%i|HB4PIEJV`wbJDengn`AnbM&yLnPmNY&CN_U zI+-^%_;ib0`jvg$8@GChi3RU()S#H%8%TAZKT&qjA06i729 zAsWSu9wx-U$?3|2*v2U1++;+wywtR+6_W%bmSCAq^fb}f!^d(fuxubB;$quZ7#R?} zDiRblO>jR#kb8h2Y#f~n_*0&g;;;JVN-N8%3W|~kYkRq*%8G)cUkMeDiHg8cfL(aV{sFK3iV zTf)F;EvR9&HnVhSA%NTy2UG0~7~{%8^C?bPn6n%^3E%9(f-it0?>>3J-OJLxmnU|( zv^bnsFRAJ>&R90RiUKc^XC+&s8}u@=P&65nOZ)^)geKwE4$ysl4x`}oKDyM_sf&Q+ zd|Nnn^?0cS;4l`9F7Ueyu*0Ry{xnuFKwLEDWT&@vsfG>^-JE&8g#-6%9Zs;19r88a zAfkvj4~Ye+L67!hLyo1#2J2cZyMCo7H(%h}NBuz3RmSxWK4zbR90gy$-Lo z>H>-kj|Hc*jEwqvF~bju?IpXGFyB1jCA+j0g=?VUY^0UVlT<<2(mvWVT|LD3Ron+0 zI?s32kynHjD3ex)XsXu&OhK+AgH^SQy+d8hOEQRL&-P6CmY+rli1s5{eLxC9%_&C2 zm^T9*NTr$OGc;HEoOK_RR@o4fjL9KO)uO^%P{(YG;{CFi@kds#$A)? zeUDn7bEi-cyTueKchL$bB5DP>4!`iK%@n4`w&Y!om-Dm5pq@s6`zc%QZM8($B6%8c z_u}CY3RQc>-MtN}ei0KKcvrd}3Qr*#NM+D{?itFnner{nDzhAP#Y4jji>0MC#NJjV zw$z9W^~KcY5ZPv%JHAqp+6k_=KkV%$6 zLkM&yG&UBVjz?fpa;E*xve2duPw~lVPCL{lMB0oZU}-O4zRi#rk!qU+m=_`Dpc6D) z1H^3K3LfsB@jDJezSNE(5;lTIRX?`kLw-DS#@}Yw3XK}0{NkIIc->;wIpj_9S6F0 zrZwk~tzz8Xuyiv$=sd>-9-bPzn!2xA5aJ_8elG z_Bbr6TfO|`g(<>UFDW{iUbCJ&Sj2l!R9Rgo=tT% zAiQ#kj-Y76X8@#!U%V;J`%?tHS}NdMT*q(fkf}RCTW`-(BBQ9jytcA7u7=b`DagQX z_8&FEn@p(9WipB;u}h4?Pf3VWVNDH_Z!&Ro!Lby2#bh`2^9x2-Jv4W89iXd@uPqhk ze14k$-A)+n7hrGhtK9o=i~lnV=O^u(9m9XtgLe%5*$r;VHf?ioY(oyaFees*3 z>u0dO_@)r|FVlO&Y2e(uKSpn|@$V;jbN>XrHF{_0P3yluNAE>6ekLJy`R%)Bx9i&P Nyp`kl*{{AZ_}@tkFsJ|k diff --git a/pgworksheet_yvesf/plugins/README_PLUGINS b/pgworksheet_yvesf/plugins/README_PLUGINS deleted file mode 100644 index 2df2b53..0000000 --- a/pgworksheet_yvesf/plugins/README_PLUGINS +++ /dev/null @@ -1,40 +0,0 @@ -=== General - * You can put the plugin wherever you want under plugins/ - -=== SidebarPlugin - -<<<<<< - -#Your imports -from pgw.Plugin import SidebarPlugin; - -class (SidebarPlugin): - name = "PLugin Title" - def __init__(self): - SidebarPlugin.__init__(self) - self.my_box = gtk.HBox() - - - - self.add(self.my_box) - - def on_init(self): - #called after setting self.app - def on_connection(self): - #called everytime a new connection is established - - ... - - -EXPORTS=[] - -<<<< -# -# -# -# -# -# VALUE -# -# -# FOO -# -# -# - -class ResultViewSaveXML(pgw.Plugin.ResultViewPlugin): - name = _('Als XML Speichern') - def __init__(self, app, result): - pgw.Plugin.ResultViewPlugin.__init__(self, app) - - self.add(gtk.Button(result.sql)) - self.show_all() - - -EXPORTS=[ResultViewSaveXML] diff --git a/pgworksheet_yvesf/plugins/sidebar/FunctionBrowser.py b/pgworksheet_yvesf/plugins/sidebar/FunctionBrowser.py deleted file mode 100644 index 7a8e16b..0000000 --- a/pgworksheet_yvesf/plugins/sidebar/FunctionBrowser.py +++ /dev/null @@ -1,165 +0,0 @@ -# (c) Yves Fischer yvesf - xapek org, 2007, License: GPL-2 - -import pygtk; -import gtk; -from pgw.Plugin import SidebarPlugin; -import pgw.Syntax; - -class ListBox(gtk.ScrolledWindow): - def __init__(self,ui): - gtk.ScrolledWindow.__init__(self,ui) - self.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS) - self.set_shadow_type(gtk.SHADOW_NONE) - - self.store = gtk.ListStore(str) - self.view = gtk.TreeView(self.store) - - cell = gtk.CellRendererText() - column = gtk.TreeViewColumn("Functions") - column.pack_start(cell, True) - column.add_attribute(cell, 'text', 0) - column.set_sort_column_id(0) - self.view.append_column(column) - - self.add(self.view) - - def set_array(self, array): - self.store.clear() - for item in array: - self.store.append(item) - - def get(self): - tuple, treeview = self.view.get_cursor() - if tuple == None: - return None - return self.store[tuple[0]] - -class TextWidget(gtk.ScrolledWindow): - def __init__(self): - gtk.ScrolledWindow.__init__(self) - self.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - self.set_shadow_type(gtk.SHADOW_NONE) - - self.buffer = gtk.TextBuffer() - self.syntax = pgw.Syntax.Syntax(self.buffer) - - self.buffer.connect('delete-range', self.syntax.text_deleted) - self.buffer.connect('insert-text', self.syntax.text_inserted) - self.buffer.connect('changed', self.syntax.text_changed) - - self.view = gtk.TextView(self.buffer) - - self.add(self.view) - - - def set_text(self, text): - self.buffer.set_text(text) - def get_text(self): - return self.buffer.get_text( \ - self.buffer.get_start_iter(), self.buffer.get_end_iter() ) - -class FunctionBrowserPlugin(SidebarPlugin): - name = "Function Browser" - def __init__(self): - SidebarPlugin.__init__(self) - self.vpaned = gtk.VPaned() - - self.hcontainer = gtk.HBox() - - self.button = gtk.Button("Reload") - self.button.set_property("height-request", 30) - self.button.set_property("width-request", 50) - self.button.connect("clicked", self.refresh) - self.hcontainer.add(self.button) - - self.liststore = gtk.ListStore(str); - self.combobox = gtk.ComboBox(self.liststore) - cell = gtk.CellRendererText() - self.combobox.pack_start(cell, True) - self.combobox.add_attribute(cell, 'text', 0) - - self.hcontainer.add(self.combobox) - self.liststore.append(["asdf"]); - self.liststore.append(["asdf"]); - self.liststore.append(["asdf"]); - self.liststore.append(["asdf"]); - - - - self.pack_start(self.hcontainer, False, True) - self.listbox = ListBox() - self.listbox.view.set_property("height-request", 200) - self.vpaned.pack1(self.listbox) - - self.text = TextWidget() - self.vpaned.pack2(self.text) - - self.add(self.vpaned) - - self.listbox.view.connect("cursor-changed", self.cursor) - - def on_init(self): - pass - - def on_connection(self): - self.refresh() - - def cursor(self, widget, data=None): - name = self.listbox.get()[0] - if not vars(self.app).has_key("db") or not self.app.db.is_connected: - print "FunctionBrowser: No Connection!" - return - query = self.app.db.query("SELECT prosrc AS sprache FROM pg_catalog.pg_proc WHERE proname = '%s'" %(name)) - result = query['cursor'].fetchall() - self.text.set_text(result[0][0]) - - def refresh(self, widget=None): - if not vars(self.app).has_key("db") or not self.app.db.is_connected: - return - self.button.set_relief( gtk.RELIEF_NONE ) - - #dropdown - sql = """SELECT DISTINCT(lanname) - FROM pg_catalog.pg_language AS L, pg_catalog.pg_proc AS P - WHERE int4(L.lanplcallfoid)+1 = int4(P.prolang);""" - query = self.app.db.query(sql); - - results = query['cursor'].fetchall() - active = self.combobox.get_active_text() - self.liststore.clear() - self.liststore.append([_("All")]) - n=0 - j=0 - for result in results: - if len(result) == 1: - self.liststore.append([result[0]]) - if result[0] == active: #take-over old selection - j = n - n+=1 - else: - print "FunctionBrowser: Error, unexpected result" + str(result) - self.combobox.set_active(j) - #list - - filter = self.combobox.get_active_text() - if filter == _("All") or filter == None: - filter = '%'; - sql = """SELECT proname - FROM pg_catalog.pg_language AS L, pg_catalog.pg_proc AS P - WHERE - int4(L.lanplcallfoid)+1 = int4(P.prolang) - AND L.lanname LIKE '%s';""" % filter - got = self.app.db.query(sql) - cursor = got['cursor'] - results = cursor.fetchall() - - store = [] - for line in results: - store.append([line[0]]) - - self.listbox.set_array(store) - - self.button.set_relief( gtk.RELIEF_NORMAL ) - return - -EXPORTS=[FunctionBrowserPlugin] diff --git a/pgworksheet_yvesf/plugins/sidebar/PgStats.py b/pgworksheet_yvesf/plugins/sidebar/PgStats.py deleted file mode 100644 index 4bd55e5..0000000 --- a/pgworksheet_yvesf/plugins/sidebar/PgStats.py +++ /dev/null @@ -1,241 +0,0 @@ -# (c) Yves Fischer yvesf - xapek org, 2007, License: GPL-2 - -import pygtk; -import gtk; -from pgw.Plugin import SidebarPlugin; -import pgw.Syntax; - -class RowedListBox(gtk.ScrolledWindow): - def __init__(self): - gtk.ScrolledWindow.__init__(self) - self.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS) - self.set_shadow_type(gtk.SHADOW_NONE) - self.view = gtk.TreeView() - self.add(self.view) - - # [[CAPTION1, CAPTION2, ...] [DATA1, DATA2, ...] ] - def set_array(self, array): - if len(array) == 0 or len(array[0]) == 0: - return - #XXX !!!1!!11!!!11111111 dont look at this, it works but... - function = gtk.ListStore - self.store = apply(function, (str,) * len(array[0]) ) - #XXX its done - self.store.clear() - self.view.set_model() - self.view.set_model(self.store) - - caption = array[0] - array.remove(array[0]) - col = caption[0]; caption.remove(caption[0]) - cell = gtk.CellRendererText() - column = gtk.TreeViewColumn(str(col).replace("_", " ")) - column.pack_start(cell, True) - column.add_attribute(cell, 'text', 0) - column.set_sort_column_id(0) - self.view.append_column(column) - - for col in caption: #pop caption - cell = gtk.CellRendererText() - column = gtk.TreeViewColumn(str(col).replace("_", " ")) - column.pack_start(cell, True) - column.add_attribute(cell, 'text', 0) - self.view.append_column(column) - - data = [] - for row in array: - x = [] - for col in row: - x.append(str(col)) - data.append(x) - - for row in data: - self.store.append(row) - - def get(self): - tuple, treeview = self.view.get_cursor() - if tuple == None: - return None - return self.store[tuple[0]] - -class TextWidget(gtk.ScrolledWindow): - def __init__(self): - gtk.ScrolledWindow.__init__(self) - self.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) - self.set_shadow_type(gtk.SHADOW_NONE) - - self.buffer = gtk.TextBuffer() - self.syntax = pgw.Syntax.Syntax(self.buffer) - - self.buffer.connect('delete-range', self.syntax.text_deleted) - self.buffer.connect('insert-text', self.syntax.text_inserted) - self.buffer.connect('changed', self.syntax.text_changed) - - self.view = gtk.TextView(self.buffer) - - self.add(self.view) - - - def set_text(self, text): - self.buffer.set_text(text) - def get_text(self): - return self.buffer.get_text( \ - self.buffer.get_start_iter(), self.buffer.get_end_iter() ) - - -class Dropdown(gtk.ComboBox): - def __init__(self): - self.store = gtk.ListStore( str ) - gtk.ComboBox.__init__(self, self.store) - - cell = gtk.CellRendererText() - self.pack_start(cell, True) - self.add_attribute(cell, 'text', 0) - - def refresh(self, array): - active_text = self.get_active_text() - self.store.clear() - n=0 - j=0 - for line in array: - self.store.append([ line ]) - if line == active_text: - j = n - n += 1 - self.set_active(j) - - - -class PgStats(SidebarPlugin): - name = "PgStats" - def __init__(self): - SidebarPlugin.__init__(self) - self.vpaned = gtk.VPaned() - - self.vcontainer = gtk.VBox() - - #Filter - self.combobox_table = Dropdown() - self.combobox_table.set_property("height-request", 30) - self.combobox_table.connect("changed", self.refresh_data) - - self.button_refresh = gtk.Button("Refresh") - self.button_refresh.set_property("width-request", 60) - self.button_refresh.set_property("height-request", 30) - self.button_refresh.connect("clicked", self.refresh) - - self.filterbox1 = gtk.HBox() - self.filterbox1.pack_start(self.combobox_table, True, True) - self.pack_start(self.filterbox1, False, True) - - self.filterbox2 = gtk.HBox() - self.filterbox2.add(self.button_refresh) - self.pack_start(self.filterbox2, False, True) - #Ergebnisse - self.listbox = RowedListBox() - self.vcontainer.add(self.listbox) - - self.add(self.vcontainer) - - def on_init(self): - pass - - def on_connection(self): - self.refresh() - - def refresh(self,widget=None): - self.refresh_table() #=> Calls refresh_data via event from table-column ding - - def refresh_table(self): - tables = [_("All")] - for row in self.query("SELECT DISTINCT(tablename) FROM pg_stats;"): - tables.append(row[0]) - self.combobox_table.refresh(tables) - - - def refresh_data(self, widget=None): - if self.combobox_table.get_active_text() == _("All"): - filter_table = '%' - else: - filter_table = self.combobox_table.get_active_text() - - data = [ ["tablename", "attname", "null_frac", "avg_width", "n_distinct", "most_common_vals", "most_common_freqs", "histogram_bounds", "correlation"] ] - columns = ", ".join(data[0]) - - sql = "SELECT %s FROM pg_stats WHERE tablename LIKE '%s';"%(columns, filter_table) - print sql - - for row in self.query(sql): - data.append(row) - self.listbox.set_array(data) - - def query(self, sql): - if not vars(self.app).has_key("db") or not self.app.db.is_connected: - return - q = self.app.db.query(sql) - if not q.has_key("error") and q.has_key("cursor"): - return q['cursor'].fetchall() - else: - print q['error'] - -""" - def cursor(self, widget, data=None): - name = self.listbox.get()[0] - if not vars(self.app).has_key("db") or not self.app.db.is_connected: - print "FunctionBrowser: No Connection!" - return - query = self.app.db.query("SELECT prosrc AS sprache FROM pg_catalog.pg_proc WHERE proname = '%s'" %(name)) - result = query['cursor'].fetchall() - self.text.set_text(result[0][0]) - - def refresh(self, widget=None): - if not vars(self.app).has_key("db") or not self.app.db.is_connected: - return - self.button.set_relief( gtk.RELIEF_NONE ) -""" - #dropdown - # sql = """SELECT DISTINCT(lanname) - # FROM pg_catalog.pg_language AS L, pg_catalog.pg_proc AS P - # WHERE int4(L.lanplcallfoid)+1 = int4(P.prolang);""" -""" query = self.app.db.query(sql); - - results = query['cursor'].fetchall() - active = self.combobox.get_active_text() - self.liststore.clear() - self.liststore.append([_("All")]) - n=0 - j=0 - for result in results: - if len(result) == 1: - self.liststore.append([result[0]]) - if result[0] == active: #take-over old selection - j = n - n+=1 - else: - print "FunctionBrowser: Error, unexpected result" + str(result) - self.combobox.set_active(j) - #list - - filter = self.combobox.get_active_text() - if filter == _("All") or filter == None: - filter = '%'; -"""# sql = """SELECT proname - # FROM pg_catalog.pg_language AS L, pg_catalog.pg_proc AS P - # WHERE - # int4(L.lanplcallfoid)+1 = int4(P.prolang) - # AND L.lanname LIKE '%s';""" % filter -x= """ got = self.app.db.query(sql) - cursor = got['cursor'] - results = cursor.fetchall() - - store = [] - for line in results: - store.append([line[0]]) - - self.listbox.set_array(store) - - self.button.set_relief( gtk.RELIEF_NORMAL ) - return -""" - -#EXPORTS=[PgStats] diff --git a/pgworksheet_yvesf/plugins/sidebar/PgStatus.py b/pgworksheet_yvesf/plugins/sidebar/PgStatus.py deleted file mode 100644 index 4da422c..0000000 --- a/pgworksheet_yvesf/plugins/sidebar/PgStatus.py +++ /dev/null @@ -1,34 +0,0 @@ -# (c) Yves Fischer yvesf - xapek org, 2007, License: GPL-2 - -import pygtk; -import gtk; -from pgw.Plugin import SidebarPlugin; -import pgw.Syntax; -import thread -import time -import gobject - -class PgStatus(SidebarPlugin): - name = "PgStatus" - def __init__(self, ui): - SidebarPlugin.__init__(self, ui) - self.label = gtk.Label("STATUS") - - self.add(self.label) - - gobject.timeout_add(1000, self.thread) - print "Thread running" - - def thread(self,thrash=None): - if self.db.is_connected(): - self.label.set_text("ON"+str(self.db.db)) - else: - self.label.set_text("OFF"+str(self.db.db)) - return True - - def on_connection(self): - print str(self) + "got on_conn" - - - -EXPORTS=[PgStatus] diff --git a/pgworksheet_yvesf/plugins/sidebar/ShowConfig.py b/pgworksheet_yvesf/plugins/sidebar/ShowConfig.py deleted file mode 100644 index fc3bd60..0000000 --- a/pgworksheet_yvesf/plugins/sidebar/ShowConfig.py +++ /dev/null @@ -1,85 +0,0 @@ -# (c) Yves Fischer yvesf - xapek org, 2007, License: GPL-2 - - -import pygtk; -import gtk; -from pgw.Plugin import SidebarPlugin; - -class ShowConfigPlugin(SidebarPlugin): - name = "Configuration" - def __init__(self, ui): - SidebarPlugin.__init__(self, ui) - - self.vbox = gtk.VBox() - self.button = gtk.Button("Reload") - self.button.set_property("height-request", 30) - self.vbox.pack_start(self.button, expand=False, fill=True, padding=0) - - self.scroll = gtk.ScrolledWindow() - - self.table = gtk.Table(rows=1, columns=2, homogeneous=True) - - self.scroll.add_with_viewport(self.table) - - self.vbox.add(self.scroll) - - self.add(self.vbox) - - self.button.connect("clicked", self.button_pressed) - - def on_init(self): - pass - - def on_connection(self): - self.button_pressed(None) - - def clear_table(self, widget, data=None): - self.table.remove(widget) - - def button_pressed(self, button, Data=None): - #SHOW ALL - if self.db.is_connected(): - print "connected" - cursor = self.db.query("SHOW ALL")['cursor'] - if not cursor: - print "cursor == None" - return - ret = cursor.fetchall() - - #tabelle loeschen - self.table.foreach(self.clear_table) - - print len(ret) - self.table.resize(rows=len(ret), columns=2) - - n=0 - for line in ret: - self.table.attach(self.get_cell(line[0]), \ - left_attach=0, right_attach=1, \ - top_attach=n, bottom_attach=n+1, \ - ) #xoptions=gtk.EXPAND, yoptions=gtk.EXPAND) - - self.table.attach(self.get_cell(line[1]), \ - left_attach=1, right_attach=2, \ - top_attach=n, bottom_attach=n+1, \ - ) #xoptions=gtk.EXPAND, yoptions=gtk.EXPAND) - n += 1 - self.table.show_all() - else: - self.table.foreach(self.clear_table) - self.table.resize(1,2) - self.table.attach(self.get_cell("Not Connected"), \ - left_attach=0, right_attach=2, \ - top_attach=0, bottom_attach=1,) - self.table.show_all() - - def get_cell(self, caption): - hbox = gtk.HBox() - label = gtk.Label(caption) - label.set_property("justify", gtk.JUSTIFY_LEFT) - hbox.pack_start(label, expand=False) - return hbox - - - -EXPORTS=[ShowConfigPlugin] diff --git a/pgworksheet_yvesf/trash/pgworksheet b/pgworksheet_yvesf/trash/pgworksheet deleted file mode 100755 index 858c286..0000000 --- a/pgworksheet_yvesf/trash/pgworksheet +++ /dev/null @@ -1,578 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8; -*- -# -# PgWorksheet - PostgreSQL Front End -# http://pgworksheet.projects.postgresql.org/ -# -# Copyright © 2004-2005 Henri Michelon & CML http://www.e-cml.org/ -# -# 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 (read LICENSE.txt). -# -# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# $Id: pgworksheet,v 1.88 2006/01/10 21:31:35 hmichelon Exp $ -# -import os -import sys -import string -import gettext -import locale -import ConfigParser -#this is needed for py2exe -if sys.platform == 'win32': - #win32 platform, add the "lib" folder to the system path - os.environ['PATH'] += ";gtk/bin;gtk/lib;postgresql;" - import pygtk -else: - import pygtk - #not win32, ensure version 2.0 of pygtk is imported - pygtk.require('2.0') -import gtk - -import pgw -import pgw.UI -import pgw.RunSQL -import pgw.Execute -import pgw.DBConnection - -# maximum entries in the SQL queries history -PGW_MAX_HISTORY = 100 -# maximum entries in the connection parameters history -PGW_MAX_CONNECTION_HISTORY = 5 - - -class PgWorksheet: - - def __init__(self, app_name, app_version, pixmap_path, locale_path): - # Initialize I18N - if (pgw.mswindows()): - try: - # try to get the default language - lang = gettext.translation(app_name, locale_path, - [ locale.getdefaultlocale()[0] ]) - lang.install() - except IOError: - # fallback to the default method - gettext.bindtextdomain(app_name, locale_path) - gettext.textdomain(app_name) - gettext.install(app_name, locale_path, unicode=1) - else: - gettext.bindtextdomain(app_name, locale_path) - gettext.textdomain(app_name) - gettext.install(app_name, locale_path, unicode=1) - # Build UI - self.ui = pgw.UI.UI(self, app_name, app_version, pixmap_path) - # Default connection state : not connected - self.db = None - self.disconnect() - # Initialize prev/next query lifos - self.prev_statements = [] - self.next_statements = [] - self.load_history() - self.prev_saved = 1 - # Display connection dialog on startup - self.on_menu_connect(None) - # Start application - gtk.main() - - - def add_prevstatement(self, sql): - """Add a query to the previous queries lifo""" - # do not add the same query two times - if (len(self.prev_statements) > 0): - prev = self.prev_statements[len(self.prev_statements)-1] - if (prev == sql): return - # add the query to the lifo - self.prev_statements.append(sql) - self.ui.enable_prevsql(len(self.prev_statements) > 0) - - - def get_history_path(self): - """Returns the path to the configuration file""" - return os.path.join(pgw.get_user_configdir(), '.pgworksheet_history'); - - - def save_history(self): - """Save the history in a text file""" - try: - fd = open(self.get_history_path(), 'w') - self.add_prevstatement(self.ui.get_sqlbuffer_text()) - for sql in self.prev_statements: - fd.write("\n#$#\n") - fd.write(string.rstrip(sql)) - for sql in self.next_statements: - fd.write("\n#$#\n") - fd.write(string.rstrip(sql)) - fd.write("\n#$#\n") - fd.close() - except IOError: - pass - - - def load_history(self): - """Load the history from a text file""" - try: - fd = open(self.get_history_path(), 'r') - sql = '' - count = 0 - for line in fd: - line = string.rstrip(line) - if (line == '') : - continue - try: - line = unicode(line, 'UTF-8') - except UnicodeDecodeError: - try: - line = unicode(line, pgw.get_user_encoding()) - except UnicodeDecodeError: - pass - if (line == '#$#'): - if (len(sql) > 0): - self.prev_statements.append(sql) - count = count + 1 - sql = '' - continue - sql += line - sql += '\n' - if (len(sql) > 0): - self.prev_statements.append(sql) - fd.close() - if (count > PGW_MAX_HISTORY): - self.prev_statements = self.prev_statements[count - PGW_MAX_HISTORY : count] - self.ui.enable_prevsql(len(self.prev_statements) > 0) - except IOError: - pass - - - def is_connected(self): - """Return TRUE if connected to a database""" - if (self.db is None): - return None - else: - return self.db.is_connected() - - - def connect(self, host = None, port = None, db = None, - user = None, password = None): - """Connect to a database""" - self.ui.wndmain.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH)) - self.ui.status(_('Trying to connect as %(user)s to %(db)s on %(host)s') % - {'user':user, 'db':db, 'host':host}, _('connecting...')) - while (gtk.events_pending() == True): - gtk.main_iteration_do(False) - # Disconnect the re-connect - self.disconnect() - self.db = pgw.DBConnection.DBConnection(host, port, db, user, password) - # we are connected - if (self.is_connected()): - # update the UI to reflect the connection state - self.ui.enable_disconnect() - self.ui.enable_runsql() - self.ui.status(_('connected as %(user)s to %(db)s on %(host)s') % - {'user':user, 'db':db, 'host':host}, self.db.pgversion()) - new_conn = "%s,%s,%s,%s" % (host, port, db, user) - # update the connection history - n = 0 - for conn in self.all_connections: - # remove the connection from the history if it already exists - if (conn == new_conn): - self.all_connections.pop(n) - break - n = n + 1 - # add the connection to the history, making it the first of the list - self.all_connections.insert(0, new_conn) - # save the connection history in the config file - cp = ConfigParser.ConfigParser() - try: - cp.readfp(open(pgw.get_config_path(), 'r')) - except IOError: - pass - if (not cp.has_section("connections")): - cp.add_section("connections") - n = 0 - while ((n <= PGW_MAX_CONNECTION_HISTORY) and - (n < len(self.all_connections))): - cp.set("connections", "conn%d" % (n + 1), self.all_connections[n]) - n = n + 1 - try: - cp.write(open(pgw.get_config_path(), 'w')) - except IOError: - pass - # ready to type queries, give the focus to the text field - self.ui.setfocus_sqlbuffer() - # initialize the objects used to execute the queries - self.execute = pgw.Execute.Execute(self.db) - self.run = pgw.RunSQL.RunSQL(self.execute, - self.ui.sqlview, - self.ui.resulttab) - self.ui.wndmain.window.set_cursor(None) - - - def disconnect(self): - """Disconnect from the current database""" - # disconnect from the database - if (self.is_connected()): self.db.disconnect() - # destroy the objects used for this connection - self.db = None - self.execute = None - self.run = None - # update the UI to reflect the connection state - self.ui.status(_('not connected'), 'PgWorksheet v' + app_version) - self.ui.enable_disconnect(False) - self.ui.enable_runsql(False) - - - def on_wndmain_destroy(self, widget): - """Called when the application quits""" - self.disconnect() - self.save_history() - gtk.main_quit() - sys.exit(0) - - - def on_wndmain_delete(self, widget, event): - """Called when the user wants to close the main window""" - return False - - - def on_menu_connect(self, widget): - """Called when the user want the connection dialog box""" - # fill the connection dialog box with default parameters - if os.environ.has_key('USERNAME'): - self.username = os.environ['USERNAME'] - elif os.environ.has_key('USER'): - self.username = os.environ['USER'] - else: - self.username = "" - host = 'localhost' - port = '5432' - database = 'template1' - username = 'pgsql' - self.display_connect_dialog(host, port, username, database, 0) - - - def display_connect_dialog(self, host, port, username, database, overwrite_entry): - # display and execute the connection dialog box - params = self.ui.connect_dialog(self, host, port, username, database, overwrite_entry) - # check if the user have clicked "Cancel" - if (params is not None): - # connect to the database - host, port, username, passwd, database = params; - self.connect(host, port, database, username, passwd) - # error connecting to the database, retry - if (not self.is_connected()): - self.ui.error_box(_('Error connecting to %s:%s@%s:%s') % - (username, database, host, port)) - self.display_connect_dialog(host, port, username, database, 1) - - - def on_dlgconnect_map(self, widget): - """Called when the connection dialog box is displayed""" - # clear the connections history - self.all_connections = [] - # load the connections history from the config file - cp = ConfigParser.ConfigParser() - try : - cp.readfp(open(pgw.get_config_path(), 'r')) - n = 1 - while n <= PGW_MAX_CONNECTION_HISTORY: - try: - line = cp.get("connections", "conn%d" % n) - # add the connection to the connections history - self.all_connections.append(line) - host, port, db, user = string.split(line, ',') - # add the connections to the connections history list of the dialog box - self.ui.storeconn.append(["%s:%s@%s" % (user, db, host), line]) - n = n + 1 - except: - break - # if we have at least one connection in the history, made it the default - if (n > 1) : - # select the last used connection - self.ui.viewconn.set_cursor(self.ui.storeconn.get_path( - self.ui.storeconn.get_iter_first())) - except IOError: - pass - - - def on_dlgconnect_change(self, treeview): - """Called when the user choose a connection in the connection history list""" - # fill the connection dialog with the selected connection parameters - model, iter = treeview.get_selection().get_selected() - host, port, db, user = string.split(model.get(iter, 1)[0], ',') - self.ui.entry_host.set_text(host) - self.ui.entry_port.set_text(port) - self.ui.entry_database.set_text(db) - self.ui.entry_user.set_text(user) - self.ui.entry_password.set_text('') - - - def on_menu_disconnect(self, widget): - """Called when the user wants to disconnect from the database""" - self.disconnect() - - - def on_menu_opensql(self, widget): - """The user wants to open a file with some queries""" - filename = self.ui.file_dialog(_('Select a SQL text file')); - if (filename is not None): - self.ui.undo.lock = True - for handler in self.ui.buffer_handlers: - self.ui.sqlbuffer.handler_block(handler) - self.ui.set_sqlbuffer_text('') - try: - input = open(filename, 'r') - for line in input: - try: - self.ui.sqlbuffer.insert_at_cursor(unicode(line, 'UTF-8')) - except UnicodeDecodeError: - try: - self.ui.sqlbuffer.insert_at_cursor(unicode(line, pgw.get_user_encoding())) - except UnicodeDecodeError: - self.ui.sqlbuffer.insert_at_cursor(line) - except IOError: - self.ui.error_box(_('Error while opening or reading from %s') %filename) - for handler in self.ui.buffer_handlers: - self.ui.sqlbuffer.handler_unblock(handler) - self.ui.undo.reset() - self.ui.undo.lock = False - self.ui.syntax.refresh() - pgw.set_proportional(self.ui.sqlbuffer) - - - def file_overwrite(self, title): - """Display a "Save As" dialopg box and prompt a confirmation if the selected file exists""" - filename = self.ui.file_dialog(title, gtk.FILE_CHOOSER_ACTION_SAVE, - gtk.STOCK_SAVE_AS); - if (filename is not None): - try: - os.stat(filename) - if (self.ui.yesno_box(_('%s already exists, overwrite ?') % filename) == - gtk.RESPONSE_YES): - return filename - return self.file_overwrite(title) - except OSError: # file does not exists - return filename - return None - - - def on_menu_savesql(self, widget): - """The user wants to save his queries""" - filename = self.file_overwrite(_('Save SQL queries')) - if (filename is not None): - try: - output = open(filename, 'w') - output.write(self.ui.get_sqlbuffer_text()) - except IOError: - self.ui.error_box(_('Error while creating or writing %s') % filename) - - - def save_list_row(self, model, path, iter, output): - """Save a row of a TreeView in a tabular form""" - col = 0 - while (col < model.get_n_columns()): - val = string.replace(model.get_value(iter, col), '"', '\"') - output.write('"' + val + '"') - col = col + 1 - if (col < model.get_n_columns()): - output.write('\t') - output.write('\n') - - - def saveresults(self, widget, output): - """Save the content of a TreeView to a tab separated file""" - widget = widget.get_child() - if (isinstance(widget, gtk.TextView)): - buffer = widget.get_buffer() - output.write(buffer.get_text(buffer.get_start_iter(), - buffer.get_end_iter())) - elif (isinstance(widget, gtk.TreeView)): - widget.get_model().foreach(self.save_list_row, output) - - - def on_menu_saveallresults(self, widget): - """The user wants to save ALL the results""" - if (self.ui.resulttab.get_n_pages() > 0): - filename = self.file_overwrite(_('Save all the results')) - if (filename is not None): - try: - output = open(filename, 'w') - page = 0 - while page < self.ui.resulttab.get_n_pages() : - self.saveresults(self.ui.resulttab.get_nth_page(page), output) - page = page + 1 - except IOError: - self.ui.error_box(_('Error while creating or writing %s') % filename) - - - def on_menu_saveresults(self, widget): - """The user wants to save the current result""" - if (self.ui.resulttab.get_n_pages() > 0): - filename = self.file_overwrite(_('Save the results')) - if (filename is not None): - try: - output = open(filename, 'w') - self.saveresults(self.ui.resulttab.get_nth_page( - self.ui.resulttab.get_current_page()), output) - except IOError: - self.ui.error_box(_('Error while creating or writing %s') % filename) - - - def on_menu_cut(self, widget): - """Cut text to the clipboard""" - w = self.ui.wndmain.get_focus() - if (isinstance(w, gtk.TextView)): - w.emit('cut-clipboard') - - - def on_menu_copy(self, widget): - """Copy text to the clipboard""" - w = self.ui.wndmain.get_focus() - if (isinstance(w, gtk.TextView)): - w.emit('copy-clipboard') - elif (isinstance(w, gtk.TreeView)): - model, iter = w.get_selection().get_selected() - if (iter is not None): - col = 0 - result = '' - while (col < model.get_n_columns()): - val = string.replace(model.get_value(iter, col), '"', '\"') - result = result + val - col = col + 1 - if (col < model.get_n_columns()): - result = result + '\t' - clip = gtk.Clipboard() - clip.set_text(result) - - - def on_menu_paste(self, widget): - """Paste from the clipboard""" - w = self.ui.wndmain.get_focus() - if (isinstance(w, gtk.TextView)): - w.emit('paste-clipboard') - - - def on_menu_selectall(self, widget): - """Select the entire text""" - w = self.ui.wndmain.get_focus() - if (isinstance(w, gtk.TextView)): - buffer = w.get_buffer() - buffer.move_mark_by_name('selection_bound', buffer.get_start_iter()) - buffer.move_mark_by_name('insert', buffer.get_end_iter()) - - - def on_sqlview_focus_in(self, widget, event): - self.ui.enable_cut() - self.ui.enable_paste() - - - def on_sqlview_focus_out(self, widget, event): - self.ui.enable_cut(False) - self.ui.enable_paste(False) - - - def on_sqlview_keypress(self, widget, event): - """Save the last statement in the history - if needed (after an execution""" - if (event is None) : return - if (event.keyval != 65507): - if (self.prev_saved == 0): - self.add_prevstatement(self.ui.get_sqlbuffer_text()) - self.prev_saved = 1 - - - def on_menu_about(self, widget): - self.ui.about_dialog() - - - def on_menu_runsql(self, widget): - """Execute the SQL queries""" - if (not self.is_connected()): - if (self.ui.yesno_box(_('Not connected to a database.\nDo you want to connect now ?')) == - gtk.RESPONSE_NO): - return - self.on_menu_connect(widget) - if (not self.is_connected()): - return - self.on_text_change(widget) - self.prev_saved = 0 - self.ui.wndmain.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH)) - self.run.run() - self.ui.enable_saveresult(self.ui.resulttab.get_n_pages() > 0) - self.ui.wndmain.window.set_cursor(None) - - - def on_menu_prevsql(self, widget): - """Display the previous statement from the history""" - self.ui.undo.lock = True - if (len(self.prev_statements) > 0): - s = self.prev_statements.pop() - self.next_statements.append(self.ui.get_sqlbuffer_text()) - self.ui.set_sqlbuffer_text(s) - self.prev = s - self.ui.enable_prevsql(len(self.prev_statements) > 0) - self.ui.enable_nextsql(len(self.next_statements) > 0) - self.ui.undo.lock = False - - - def on_menu_nextsql(self, widget): - """Display the next statement from the history""" - self.ui.undo.lock = True - if (len(self.next_statements) > 0): - s = self.next_statements.pop() - self.prev_statements.append(self.ui.get_sqlbuffer_text()) - self.ui.set_sqlbuffer_text(s) - self.prev = s - self.ui.enable_prevsql(len(self.prev_statements) > 0) - self.ui.enable_nextsql(len(self.next_statements) > 0) - self.ui.undo.lock = False - - - def on_text_change(self, widget): - """The text have been changed after navigation the history""" - if (self.ui.undo.lock): - return - if (len(self.next_statements) > 0): - if (self.next_statements[0] == ''): - self.next_statements.pop(0) - self.prev_statements.append(self.prev) - for i in reversed(self.next_statements): - self.prev_statements.append(i) - self.next_statements = [] - self.ui.enable_prevsql(len(self.prev_statements) > 0) - self.ui.enable_nextsql(len(self.next_statements) > 0) - - -# Application parameters -app_name = 'pgworksheet' -app_version = '1.8.1' -# Default pixmap path -pixmap_path = '@PIXMAP_PATH@' -# Find current pixmap path -if (not os.access(os.path.join(pixmap_path, 'pgworksheet-32.png'), os.F_OK)): - pixmap_path = os.path.join(sys.prefix, 'share/pixmaps/pgworksheet') -if (not os.access(os.path.join(pixmap_path, 'pgworksheet-32.png'), os.F_OK)): - pixmap_path = os.path.join(os.path.dirname(sys.argv[0]), 'pixmaps/pgworksheet') -# Find current locale path -locale_path = '@LOCALE_PATH@' -if (not os.access(os.path.join(locale_path, 'fr/LC_MESSAGES/pgworksheet.mo'), os.F_OK)): - locale_path = os.path.join(sys.prefix, 'share/locale') -if (not os.access(os.path.join(locale_path, 'fr/LC_MESSAGES/pgworksheet.mo'), os.F_OK)): - locale_path = os.path.join(os.path.dirname(sys.argv[0]), 'locale') -# Start program -p = None -try: - p = PgWorksheet(app_name, app_version, pixmap_path, locale_path) -except KeyboardInterrupt: - if (p is not None): - p.on_wndmain_destroy(None) diff --git a/pgworksheet_yvesf/trash/setup.py b/pgworksheet_yvesf/trash/setup.py deleted file mode 100644 index be0b066..0000000 --- a/pgworksheet_yvesf/trash/setup.py +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env python -# -*- coding: latin-1; -*- -# -# Copyright (c) 2004-2005 -# Henri Michelon -# -# $Id: setup.py,v 1.12 2006/01/10 13:19:55 hmichelon Exp $ -# -from distutils.core import setup, Extension - -__version__ = "1.8" - -setup (name = 'pgworksheet', - version = __version__, - description = 'PgWorksheet - SQL Tool for PostgreSQL', - url = 'http://pgworksheet.projects.postgresql.org/', - license = 'GPL', - author = 'E-CML http://www.e-cml.org/', - scripts = [ 'pgworksheet' ], - packages = [ 'pgw' ], - data_files = [ - ('share/pixmaps', - [ 'pixmaps/pgworksheet.png' ]), - ('share/pixmaps/pgworksheet', - [ 'pixmaps/pgworksheet/connect.png', - 'pixmaps/pgworksheet/disconnect.png', - 'pixmaps/pgworksheet/about.png', - 'pixmaps/pgworksheet/pgworksheet-32.png', - 'pixmaps/pgworksheet/pgworksheet.png' ]), - ('share/locale/fr/LC_MESSAGES', - [ 'locale/fr/LC_MESSAGES/pgworksheet.mo' ]), - ('share/locale/ja/LC_MESSAGES', - [ 'locale/ja/LC_MESSAGES/pgworksheet.mo' ]), - ('share/applications', - [ 'applications/pgworksheet.desktop' ]), - ] - ) -- 2.11.4.GIT