pax_global_header00006660000000000000000000000064120447654250014523gustar00rootroot0000000000000052 comment=d88ba7c888a6f9a86aaff8f2262a6d72456cd773 labyrinth-0.6/000077500000000000000000000000001204476542500133645ustar00rootroot00000000000000labyrinth-0.6/.gitignore000066400000000000000000000000221204476542500153460ustar00rootroot00000000000000*.pyc build/ *.mo labyrinth-0.6/.tx/000077500000000000000000000000001204476542500140755ustar00rootroot00000000000000labyrinth-0.6/.tx/config000066400000000000000000000002211204476542500152600ustar00rootroot00000000000000[main] host = https://www.transifex.com [labyrinth.master] file_filter = po/.po source_file = po/labyrinth.pot source_lang = en type = PO labyrinth-0.6/AUTHORS000066400000000000000000000002411204476542500144310ustar00rootroot00000000000000This version is brought to you by the letter L and the number 24 It is also brought to you by: Don Scorgie Martin Schaaf Matthias Vogelgesang labyrinth-0.6/COPYING000066400000000000000000000431101204476542500144160ustar00rootroot00000000000000 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. labyrinth-0.6/ChangeLog000066400000000000000000001752271204476542500151540ustar00rootroot00000000000000Release 0.6 (November 2012): * Improved user experience when zooming in or out. * Dropped autotools build system. * Moved maps into XDG application data folder. * Various bug fixes. Release 0.5: * Removed tree view again, as it was causing too many bugs. * Remove build-dependency on gnome-desktop. 2011-04-25 Matthias Vogelgesang * src/TextThought.py * src/MainWindow.py: Clean-up TextThought code in order to find font issue 2011-04-24 Matthias Vogelgesang * src/labyrinth.py * src/MainWindow.py: Add text domain to action group 2011-04-24 Matthias Vogelgesang * src/MMapArea.py: Fix double-clicking on thought 2011-04-24 Matthias Vogelgesang * src/Links.py * src/MMapArea.py: Fix issue 124 and fix regression that links could not be deleted 2011-04-24 Matthias Vogelgesang * po/pt_BR.po: Really set to UTF-8 * configure.ac: Prepare release candidate 2011-04-24 Matthias Vogelgesang * data/labyrinth-ui.xml * src/MainWindow.py: Removing 'delete from menu which interfered with application key binding 2011-04-23 Matthias Vogelgesang * src/MainWindow.py * src/MMapArea.py * data/labyrinth-ui.xml: Add Zoom-to-Fit functionality fixing issue 150 2011-04-23 Matthias Vogelgesang * src/MainWindow.py * data/labyrinth-ui.xml: Temporarily disable ResourceThoughts for an earlier release of 0.5 2011-04-23 Matthias Vogelgesang * src/TextThought.py: Fix issue 136 with patch provided by Dennis Guse 2011-04-23 Matthias Vogelgesang * configure.ac: Fix issue 143 with patch provided by CaptainM... 2011-04-23 Matthias Vogelgesang * src/Makefile.in: Add ResourceThought 2011-04-23 Matthias Vogelgesang * src/MapList.py: Fix issue 148 with Patch from "perlhead" 2011-04-23 Matthias Vogelgesang * src/*.py: Respect PEP-8. 2011-04-23 Matthias Vogelgesang * src/MainWindow.py * src/utils.py: Replace deprecated libs 2009-03-08 Matthias Vogelgesang * data/labyrinth.glade Fix Gtk warning 2009-02-28 Martin Schaaf * src/MMapArea.py Used wrong variable name use height instead of heigth0. Thanks to Kunshan Wang for the pointer. 2009-02-27 Matthias Vogelgesang * data/Makefile.am Fix issue 132. Thanks again to Romain Tartiere. 2009-02-27 Matthias Vogelgesang * src/labyrinth.py Fix issue 133. Thanks to Romain Tartiere. 2009-02-26 Martin Schaaf * src/MMapArea.py Fix issue 135. Thanks to wks1985 for the patch. 2008-09-25 Matthias Vogelgesang * src/MMapArea.py Fix issue 126. 2008-08-10 Matthias Vogelgesang * src/MMapArea.py Fix issue 125. 2008-08-10 Matthias Vogelgesang * src/MainWindow.py Set default size something lower so it works with netbook dimensions. 2008-07-21 Martin Schaaf * src/utils.py * src/MainWindow.py * src/MMapArea.py o fix issue 86 by setting gnome theme default font 2008-07-21 Martin Schaaf * ChangeLog o add missing entries 2008-07-16 Martin Schaaf * src/MMapArea.py o fix background setting setted to foreground o set gdk color as default not the tuple 2008-07-16 Martin Schaaf * src/MMapArea.py o set "text" and "base" styles as foreground and backgroundcolor for widgets with text like it is described in the documentation 2008-07-16 Martin Schaaf * src/TextThought.py o fix if statement to use correct foreground var 2008-07-15 Martin Schaaf * src/TextThought.py o fix issue 96 exception if text foreground color isn't set 2008-07-14 Martin Schaaf * src/MMapArea.py * src/MainWindow.py * src/TextThought.py o fix AttributeErrors o remember last selected font, fixes issue 119 2008-05-15 Matthias Vogelgesang * help/C/figures/lab_alignment.png Add the alignment image. 2008-05-15 Matthias Vogelgesang * src/ResourceThought.py Fix webpage loading on Fedora distributions. A protocol must be given to load the page by the webbrowser module. * help/C/labyrinth.xml Add more help. 2008-05-13 Matthias Vogelgesang * src/ResourceThought.py Allow editing of URIs. * src/Links.py Deselect links with Escape. 2008-05-12 Matthias Vogelgesang * help/C/labyrinth.xml A paragraph about links. Remove top links for each section. 2008-05-12 Matthias Vogelgesang * help/C/figures * help/C/figures/lab_browser_start.png * help/C/figures/lab_map_start.png * help/C/labyrinth.xml More help. 2008-05-12 Matthias Vogelgesang * src/Browser.py * help/de * help/de/de.po * help/Makefile.am * Makefile.am * data/labyrinth.glade Make help visible to users. Start german translation of help. 2008-05-06 Matthias Vogelgesang * src/MainWindow.py Fix Issue 115. 2008-04-29 Matthias Vogelgesang * src/ResourceThought.py * src/MainWindow.py Fix severe bug on resource thought creation. 2008-04-29 Matthias Vogelgesang * src/ResourceThought.py Allow editing of a resource thought through right click. 2008-04-20 Matthias Vogelgesang * src/ResourceThought.py * src/TextThought.py * src/MainWindow.py * src/MMapArea.py * src/utils.py * data/labyrinth-ui.xml * data/labyrinth.glade Add resource thoughts, tackling issue 101. 2008-04-19 Matthias Vogelgesang * src/labyrinth.py Minor cleanups like indentation. 2008-04-19 Matthias Vogelgesang * src/MainWindow.py Small refactorizations. 2008-04-14 Matthias Vogelgesang * help/ Initial import of user manual. 2008-04-13 Matthias Vogelgesang * src/Browser.py * src/MainWindow.py Address some problems with the sidebar (Issue 94) such as auto-showing and expanding. 2008-04-13 Matthias Vogelgesang * src/MMapArea.py Implemented issue 100. However it feels rather strange, so it should be tested with users. 2008-04-11 Matthias Vogelgesang * src/DrawingThought.py * src/Links.py * src/TextBufferMarkup.py * src/UndoManager.py Refactorizations. 2008-04-11 Matthias Vogelgesang * src/Links.py Add link colors through context menu. 2008-04-11 Matthias Vogelgesang * src/MMapArea.py * src/MainWindow.py Fixed outline treeview bugs and simplified its code. 2008-04-11 Matthias Vogelgesang * src/MMapArea.py Use a 1-pixel-wide border line for selection box. 2008-04-11 Martin Schaaf * src/MainWindow.py Fix exception on maximizing loaded map by calling maximize on the gtk window not on the labyrinth window object. 2008-04-10 Matthias Vogelgesang * src/MMapArea.py Fix bug and issue 109. 2008-04-10 Matthias Vogelgesang * src/MainWindow.py * src/MMapArea.py * data/labyrinth-ui.xml * data/labyrinth.glade Use Glade for the MapWindow. Added general alignment widgets. 2008-04-09 Matthias Vogelgesang * src/MMapArea.py Move multiple thoughts (fix issue 93). Introduced escape key deselecting all thoughts. 2008-04-08 Matthias Vogelgesang * src/MainWindow.py * src/MMapArea.py * src/Browser.py Save line/bezier state. 2008-04-08 Matthias Vogelgesang * src/UndoManager.py * src/MainWindow.py * src/MMapArea.py * src/ImageThought.py Add undo/redo to context sensitive menu. Use an image item for change image. 2008-04-07 Matthias Vogelgesang * src/DrawingThought.py * src/BaseThought.py * src/MMapArea.py * src/ImageThought.py * src/TextThought.py Started working on popup menus. Added image changing through popup menu. 2008-04-06 Matthias Vogelgesang * src/MMapArea.py Fix bug and update model on thought deletion. 2008-04-06 Matthias Vogelgesang * src/MainWindow.py * src/BaseThought.py * src/MMapArea.py * data/labyrinth-ui.xml Add thought outline (activate throught view -> outline) for a11y. 2008-04-05 Matthias Vogelgesang * src/MMapArea.py Fix critical bug and use default system font. 2008-04-05 Matthias Vogelgesang * src/MainWindow.py * src/MMapArea.py * data/labyrinth-ui.xml * data/labyrinth.glade Restructured menu bar according to the GNOME HIG. 2008-04-05 Matthias Vogelgesang * src/MMapArea.py * src/TextThought.py Fix theme colors. Use theme colors for text selection. Reduce code. 2008-04-04 Matthias Vogelgesang * src/Links.py Use theme colors for links too. 2008-04-04 Matthias Vogelgesang * src/utils.py * src/MMapArea.py * src/TextThought.py Use Gtk theme colors and select according to GNOME's HIG. 2008-04-04 Matthias Vogelgesang * src/MainWindow.py * src/MMapArea.py Update link positions on bezier/line switch. * po/labyrinth.pot * po/de.po Updated german translation. 2008-04-03 Matthias Vogelgesang * src/utils.py * src/MainWindow.py * src/BaseThought.py * src/Links.py * src/MMapArea.py * data/labyrinth-ui.xml Add bezier curves as stated in the ideas. It can be activated in the edit menu. 2008-04-03 Matthias Vogelgesang * src/MMapArea.py Add alignment of thoughts, thus implementing Issue 87. 2008-04-03 Martin Schaaf * src/MapList.py Refactoring of method _at_col_set_value. 2008-04-03 Matthias Vogelgesang * po/labyrinth.po * po/de.po * src/Browser.py Translator credits. * src/utils.py * src/ImageThough.py * src/DrawingThought.py Simplifications. 2008-04-03 Matthias Vogelgesang * po/es.po * po/LINGUAS Added spanish translation by Peter Gordon. 2008-04-02 Matthias Vogelgesang * src/TextThought.py Fix issue 92. * po/de.po Updated german translation. 2008-04-02 Matthias Vogelgesang * src/TextThought.py Refactoring leads to -200 loc. 2008-04-02 Martin Schaaf * src/MapList.py * src/MainWindow.py Differentiate between index in MapList and index in browser (column id). Column id is used as map index. Do not give an untitled map a number. Calculate new column id from biggest existing column id. Remove map title to map relation because it isn't used. * src/Browser.py Remove space in string. 2008-04-01 Matthias Vogelgesang * src/MMapArea.py Critical bug fixed. Couldn't deselect after selecting with box. 2008-03-31 Martin Schaaf * debian/chnagelog Add all entries from the rc versions. * configure.ac Bump to 0.5.0dev version. 2008-03-31 Matthias Vogelgesang * data/labyrinth.glade * src/MainWindow.py Beautify drop dead ugly export dialog. * src/utils.py Simplification. 2008-03-29 Matthias Vogelgesang * src/MMapArea.py Inherit color from parent node. 2008-03-29 Martin Schaaf * src/TextThought.py o set attribute to none or normal on unsetting (there is more work todo) 2008-03-28 Matthias Vogelgesang * src/MMapArea.py Fix Issue 80 doing correct undo move. * po/de.po * po/labyrinth.pot Update german translation. 2008-03-28 Martin Schaaf * src/labyrinth.py o check for pygtk version before gtk is imported like it is said in the pygtk FAQ, fixes Issue 82 2008-03-28 Martin Schaaf * src/Makefile.am o add missing file for distribution creation 2008-03-27 Martin Schaaf * src/MapList.py o fix renaming of thought * src/Browser.py o raise a AttributeError instead of a deprecated String 2008-03-27 Matthias Vogelgesang * src/MMapArea.py Fix problem when selecting through an object thus creating a link. * ChangeLog Correct changelog date of Martin's last entry. 2008-03-27 Martin Schaaf * src/TextThought.py * src/MMapArea.py * src/BaseThought.py * src/MainWindow.py * src/TextBufferMarkup.py o add font selection support for thoughts, fixes issue 79 o change attributes instead of inserting, fixes hopefully issue 53 2008-03-26 Don Scorgie * src/Browser.py: Only remember browser window size using gconf when not running under Windows (gconf isn't available there. We need another solution) 2008-03-25 Matthias Vogelgesang * src/utils.py * src/MapList.py * src/MainWindow.py * src/Browser.py * src/ImageThought.py Export maps with images as tarball. 2008-03-25 Martin Schaaf * src/ImageThought.py * src/TextThought.py * src/DrawingThought.py * src/utils.py o show a bigger border if a thought has extended info, fixes issue 33 2008-03-24 Matthias Vogelgesang * src/Browser.py Allow resizing. 2008-03-24 Matthias Vogelgesang * src/MMapArea.py Add bounding box selection. 2008-03-24 Matthias Vogelgesang * src/MMapArea.py More optimizations for issue 55. Partial redraw is done on editing and selecting and off-screen clipping has been simplified. 2008-03-23 Matthias Vogelgesang * src/Links.py Fixes issue 62. Links are not selected if not clicked. 2008-03-23 Matthias Vogelgesang * src/MMapArea.py Off-screen clipping works for other scale factors too, but only in horizontal direction. 2008-03-23 Matthias Vogelgesang * src/MMapArea.py Fixed bug introduced with last revision. 2008-03-23 Matthias Vogelgesang * src/MMapArea.py Don't draw off-screen thoughts. It is still a bit whacky and not working for scales other than 1.0. 2008-03-23 Martin Schaaf * src/Browser.py o remember map sort order, fixes issue 75 o catch exception if map is empty on file_save_cb 2008-03-23 Martin Schaaf * src/PeriodicSaveThread.py * src/MainwindowThread.py o save open maps every 60 seconds, fixing issue 64 2008-03-23 Martin Schaaf * debian/changelog * configure.ac o pump to version 0.4.0rc4 * src/ImageThought.py * src/utils.py o convert pixel array from pixbuf rgb order to cairo rgb order on exporting 2008-03-22 Martin Schaaf * debian/changelog * configure.ac o pump to version 0.4.0rc3 * src/ImageThought.py o ignore if an image isn't exportable 2008-03-22 Matthias Vogelgesang * debian/control Add python-gconf dependency. 2008-03-22 Matthias Vogelgesang * src/MapList.py * src/Browser.py Save configuration via gconf. 2008-03-21 Martin Schaaf * src/ImageThought.py o export also bitmaps to cairo surface (pdf, svg), but there is a small color problem 2008-03-21 Martin Schaaf * debian/control o add newer standard version * src/ImageThought.py o fix exception by only replace whole text if a parent node exist 2008-03-21 Martin Schaaf * debian/* o add debian package management support * configure.ac o set version to 0.4.0rc2 2008-03-21 Matthias Vogelgesang * src/MainWindow.py Add export to pdf. 2008-03-21 Matthias Vogelgesang * src/MapList.py * src/Browser.py Save and load browser size, fixing issue 18 2008-03-21 Martin Schaaf * src/DrawingThought.py * src/MainWindow.py * src/utils.py * src/ImageThought.py * src/TextThought.py o add svg export (patch by Matthias Vogelgesang) 2008-03-21 Don Scorgie * src/TextThought.py: * src/BaseThought.py: * src/Links.py: * src/DrawingThought.py: Fix potential exception on map opening * src/DrawingThought.py: Give all points their own unique colour * src/MMapArea.py: Update the colour selectors when loading a map 2008-03-21 Martin Schaaf * src/DrawingThought.py * src/MainWindow.py * src/MMapArea.py * src/Browser.py * src/ImageThought.py * src/TextThought.py * data/labyrinth-ui.xml * data/labyrinth.glade o add import/export of maps (patch by Matthias Vogelgesang) * Authors o added Matthias Vogelgesang and me 2008-03-20 Martin Schaaf * src/MMapArea.py o check for attribute transform on coord transformation * src/MainWindow.py o fix color update if a thought is selected that doesn't have background or foreground colors 2008-03-18 Martin Schaaf * src/MMapArea.py * src/MainWindow.py o update color button when selecting thought (patch by Matthias Vogelgesang) 2008-03-03 Martin Schaaf * ChangeLog o add missing entries 2008-02-18 Don Scorgie * src/MMapArea.py: Fix backspace and delete when not editing 2008-02-14 Martin Schaaf * /svn_ignore add eclipse files to svn ignore 2008-02-14 Martin Schaaf * src/Links.py set line witdth after link drawing back to original size 2008-02-14 Martin Schaaf * src/MainWindow.py * src/MMapArea.py * src/*Thought.py * src/utils.py * src/Links.py add foreground and background color selection/setting support 2008-02-04 Martin Schaaf * src/MainWindow.py * src/MMapArea.py o allow deletion of links o add some checks before deletion o catch attribute error exceptions in some cases where not only thoughts are expected 2008-02-04 Martin Schaaf * src/MMapArea.py o test for link element in child nodes, fixes bug introduced with last commit for element checking in dom tree 2008-02-04 Martin Schaaf * src/MainWindow.py * src/MMapArea.py o catch AttributeError in get_selection_bounds when it is called with link object o fix todo to check if a link exists before its deletion o only delete thoughts by selcting Edit/DeleteThoughts (fixes issue 66) o revert the last fix for link edit and add a better one 2008-02-03 Martin Schaaf * src/MainWindow.py o set edit menu entries insensitive, when they cannot be used with the selected object 2008-01-31 Martin Schaaf * src/MapList.py: o fix for Issue 68 - delete map corrupts open list 2007-05-21 Don Scorgie * src/MapList.py: Oops. Broke creating new maps. Fixed. 2007-05-16 Don Scorgie * data/labyrinth.glade: * src/Browser.py: Remove Quit button from toolbar (as per HIG) Fixes issue #44 (patch from Jean-François Fortin Tam) 2007-05-15 Don Scorgie * src/MapList.py: * src/Browser.py: Add searching in Browser window (issue #58) Add "Last Modified" column and allow sorting by it and name (issue #59) * src/MainWindow.py: * data/labyrinth-ui.xml: Add undo / redo to toolbar as an experiment (issue #60) Increase size of initial window slightly to fit better * src/MainWindow.py: Use gtk+ built-in zooming actions (issue #63) * src/MainWindow.py: * src/Browser.py: Don't ellipsize text in Browser while still space available (issue #61) * src/MainWindow.py: Attempt to reduce "over" movement when scrolling (slightly but not a huge amount better) * src/Links.py: Fix disappearing thoughts when links selection code fails (It still fails, but less so now) Partial fix for issue #62 * src/MMapArea.py: Add initial thought navigation using arrow keys 2007-04-17 Don Scorgie * src/TextThought.py: Fix thought boundaries when using attributes Don't process (control) key presses when not editing -Later- Fix byte table rebuilding in the presence of "undecipherable" characters as Python puts it. Basically, add a try-except block to ensure the character is correctly tested 2007-04-06 Don Scorgie * src/MMapArea.py: * src/Links.py: Add key filtering for +/- keys to increase / decrease link strength (when selected) * src/MMapArea.py: * src/Links.py: * src/BaseThought.py: First pass at link selection Able to select links (with think rectangle drawn around them) BaseThought and MMapArea have minor modifications to support Link selection * src/TextThought.py: Update attributes properly when using the mouse to move the cursor 2007-04-06 Don Scorgie Merge of Windows-support branch: * Windows/COPYING.txt: * Windows/defs.py: * Windows/lab.iss: * Windows/labyrinth.lnk: * Windows/labyrinth.bat: * Windows/labyrinth.ico: * Windows/WinSetup.bat: * Windows/winsetup.py: Add files for Windows build * src/Browser.py: * src/labyrinth.py: * src/MainWindow.py: * src/TextThought.py: * src/utils.py: Various fixes required to build and run on Windows properly 2007-04-05 Don Scorgie * src/TextThought.py: Fix stupid bug to make text selection work 2007-04-05 Don Scorgie * src/MainWindow.py: * src/MMapArea.py: * src/TextThought.py: * src/TextBufferMarkup.py: Add support for italics and underline * doc/TheFuture: Rework goals for 0.4 release 2007-04-05 Don Scorgie * src/MMapArea.py: Only update cursor type when the type has changes (Patch from Kamila Chyla) 2007-04-05 Don Scorgie * AUTHORS: * doc/TheFuture: Minor updates (correct email, add tick) * src/TextBufferMarkup.py: Total rewrite from scratch. The old one wasn't as shiny and didn't really do what I wanted New one is smaller and does what is needed Add support for enboldening and framework for other text attributes * src/DrawingThought.py: * src/ImageThought.py: * src/BaseThought.py: Update to use new extended buffer properly * src/UndoManager.py: Handle text attributes properly Combine translation / rotations * src/MainWindow.py: Un-disable Bold button Add support for enabling and disabling Bold (along with other attributes) Add undo support for translations and scaling * src/MMapArea.py: New signal to tell the Bold widget to enable when we want it to Add undo transform (translate / scale) Allow bold to be set in thoughts * src/TextThought.py: Update to use new extended buffer Enable bold in text thoughts themselves Shift some stuff around to work with the attributes Add framework for further attribute work 2007-03-28 Don Scorgie * src/utils.py: Make intermediate dirs for savedir (should fix issue #50) 2007-03-11 Don Scorgie * src/Browser.py: * src/DrawingThought.py: * src/ImageThought.py: * src/TextThought.py: * src/MMapArea.py: * src/Links.py: * src/prefs.py: * src/MainWindow.py: * src/UndoManager.py: * src/labyrinth.py: * doc/FileFormat: * AUTHORS: Updated my email address to new address * src/MainWindow.py: * src/MMapArea.py: * src/UndoMAnager.py: Enable undo / redo of scaling and translation 2007-03-10 Don Scorgie * src/BaseThought.py: * src/ImageThought.py: * src/DrawingThought.py: * src/TextThought.py: * src/MMapArea.py: Various misc fixes to make all thoughts work with transforms properly * src/Mainindow.py: * src/MMapArea.py: Add arrows around main area for translation Fix scaling properly Translate using button 2 (middle button) instead of ctrl-button 1 * src/MainWindow.py: * src/MMapArea.py: * src/TextThought.py: * data/labyrinth-ui.xml: Add initial support for scaling canvas and translating on canvas (infinte-scroll canvas) 2006-11-25 Don Scorgie * src/Links.py: * src/MainWindow.py: Remove (incorrect) interpreter invocations These files shouldn't be called outside of labyrinth anyway (in normal circumstances) 2006-11-15 Don Scorgie * src/Links.py: Only try and calculate ends on loading if both parent and child exists (issue #34) * src/MapList.py: Don't calculate the number of nodes within a map It's not used and seems to cause problems with some maps ( issue #36) =========== V0.3 =========== 2006-11-13 Don Scorgie * configure.ac: * NEWS: Bump Version Prepare for 0.3 release * data/Makefile.am: Fix make distcheck (add uninstall rule) * doc/TheFuture: * README: Update for 0.3 release 2006-11-12 Don Scorgie * src/MMapArea.py: * src/labyrinth.py: * src/Browser.py: Fix thought numbers on loading. Again. Sigh (issue #32 and previously issue #6) Fix loading of maps from the command line * src/MainWindow.py: Make export dialog work again (issue #29) 2006-11-08 Don Scorgie * src/utils.py: * src/TextThought.py: Use Tango palette colours, which are slightly less jarring, though feel somewhat strange ;) Text selection is still bright red Primary thought is "Butter" Selected thoughts are "Sky Blue" * src/MMapArea.py: Add an implicit "current_root" which acts as the anchor for new thoughts without being selected * src/MainWindow.py: Only set / change the mode with pygtk versions > 2.8 as the function was apparently only introduced during 2.10 2006-11-07 Don Scorgie * data/labyrinth-ui.xml: * src/MainWindow.py: * src/MMapArea.py: Add "(Un)Link Thoughts" menu item which links or unlinks thoughts when 2 (and only 2) thoughts are selected shortcut: ctrl-L (for want of a better one) * data/labyrinth.glade: Follow global toolbar style prefs in browser window (Jean-François Fortin Tam) * src/DrawingThought.py: Add erase mode using shift key Add erase action to undo list 2006-11-06 Don Scorgie * src/Browser.py: * src/MainWindow.py: Fix a couple of typos and unclear messages Issue #28 - Josef Vybíral * src/MainWindow.py: * src/Browser.py: * src/utils.py: * data/labyrinth-ui.xml: * data/labyrinth.glade: New, improved Browser window Move "Help->About" to Browser window. Remove from map windows Based heavily on a patch from Jean-François Fortin Tam. Issue #15 * src/MainWindow.py: * data/labyrinth-ui.xml: Remove Quit and New actions. Remove their callbacks - New hasn't worked for a while anyway and Quit has been removed for a while Convert several menu items to use stock labels 2006-11-05 Don Scorgie * src/TextThought.py: Don't draw selected text when not editing * src/MMapArea.py: Implement ctrl-a when no thought is being edited * src/TextThought.py: implement ctrl-a in thoughts. Various improvments in handling arrow keys * src/TextThought.py: Make backspace work again at end of text * src/TextBufferMarkup.py: * src/DrawingThought.py: * src/UndoManager.py: * src/MainWindow.py: * src/BaseThought.py: * src/ImageThought.py: * src/TextThought.py: * src/MMapArea.py: * src/Makefile.am: * data/labyrinth-ui.xml: Add undo and redo capabilities Each action should be mirrored properly Thought selection across undo's may be somewhat shaky and inconsistant. There are probably also many bugs still in the implementation * src/Links.py: Clean up old Links class 2006-11-04 Don Scorgie * src/TextThought.py: Hook up remaining (interesting) signals from IMContext Insert preedit text where appropriate (including all the shiny pango attrs that go with it) * src/TextThought.py: Check the function return for get_direction, not just the function address. Oops. * src/MainWindow.py: * src/Browser.py: * data/labyrinth-ui.xml: * data/labyrinth.glade: New, improved Browser window Add "Convert" to export to image (currently) Move "Help->About" to Browser window. Remove from map windows Based hevily on a patch from "nekohayo". Issue #15 * src/MainWindow.py: * src/Browser.py: * data/labyrinth-ui.xml: * data/labyrinth.glade: New, improved Browser window Add "Convert" to export to image (currently) Move "Help->About" to Browser window. Remove from map windows Based hevily on a patch from "nekohayo". Issue #15 * src/BaseThought.py: Don't print events - just pass silently * src/TextThought.py: * src/BaseThought.py: * src/MMapArea.py: * src/prefs.py: * src/labyrinth.py: * src/Makefile.am: Catch (temporarily) im_context signals and dump to terminal Add prefs.py to calculate / store preferences Add RTL mode when in a RTL environment - right edge anchored and edit sign displayed in top right corner Mixing RTL and LTR doesn't work so well yet. * src/MainWindow.py: Fix creation of new maps - MapNumber wasn't referenced properly * src/DrawingThought.py: * src/utils.py: * src/MainWindow.py: * src/BaseThought.py: * src/Links.py: * src/Browser.py: * src/MMapArea.py: * src/ImageThought.py: * src/TextThought.py: * data/labyrinth-ui.xml: Merge of "Rework" branch. Architecture rework of MMapArea and Thoughts Fixes (hopefully) many problems encountered thus far In addition, new features that have fallen out: - Kill Move mode. - In edit mode, single click selects - Single click + drag moves - Double click edits - Single click with ctrl drags a link - Multiple selection of thoughts is now possible using shift and ctrl keys - When multiple thoughts selected, extended buffer clears and becomes insensitive - Don't recalculate every text thought's text every redraw. Reduces CPU load significantly - Cursor changes happen on mouse-over - More cursor changes than you can shake a stick at - Middle clicking pastes primary selection text when possible - Thought heirarchy goes by selection order. Thoughts selected more recently appear in front of thought that appear less recently - Framework in place for popup menus (though none appear yet) - Framework in place to select links (though not done yet) Bug fixes included are: - Don't "jerk" thoughts around when moving. Moving is much smoother now (#19) - Escape key finishes editing a thought (#23) - Backspace at the start of text kills things. Delete at end of text ditto (#25) - Fix a fairly strange bug in resizing images using the top-right corner 2006-10-23 Don Scorgie * src/TrayIcon.py: * src/labyrinth.py: * src/utils.py: * src/MapList.py: * src/MainWindow.py: * src/Makefile.am: * src/Browser.py: Massive update to Browser from Andreas Sliwka Split into MVC style: MapList contains the maps Browser only shows them Add debug_print function Move defs stuff into utils Add optional TrayIcon (disabled by default: --use-tray-icon) 2006-10-21 Don Scorgie * README: Added "License" section at the top of the file * data/labyrinth.svg: * data/labyrinth-24.png: * data/labyrinth-22.png: * data/labyrinth-16.png: Shiny new icon from Josef Vybíral (icon released under GNU GPL v2) * src/Makefile.am: Add TextBufferMarkup.py (Issue #16) Thanks to "jmalonzo" for spotting :) 2006-10-19 Don Scorgie * src/MainWindow.py: Don't complain if no selection is made in extended buffer and edit menu is opened with focus on extended buffer * src/BaseThought.py: * src/DrawingThought.py: * src/ImageThought.py: Adapt to fit new text entry stuff (pass im_context to begin_edit which isn't called for other thought types) * src/MMapArea.py: * src/TextThought.py: New text entry stuff. Pass all keystrokes through an IM Context. Picks up dead keys and unicode entry (though no cool underlines u atm). Update view entirely when > 1 key is pressed in quick succession Construct a byte table in text thoughts to handle proper deletion / selection / movement within multibyte characters 2006-10-18 Don Scorgie * src/BaseThought.py: Fix typo in docstring (Thanks to Rob Tirrell) 2006-10-17 Don Scorgie * src/MainWindow.py: * src/BaseThought.py: * src/TextBufferMarkup.py: * src/MMapArea.py: * data/labyrinth-ui.xml: Implement cut / copy / paste for thoughts and extended buffer New menu - "Edit" for copy etc., delete thought and View Extended Minor edit of TextBufferMarkup Clipboard works for both primary selection and main clipboard :) * doc/TheFuture: A few minor updates from the Export stuff below * src/MainWindow.py: * src/BaseThought.py: * src/DrawingThought.py: * src/Links.py: * src/utils.py: * src/Browser.py: * src/MMapArea.py: * src/ImageThought.py: * src/TextThought.py: * data/labyrinth-ui.xml: * data/labyrinth.glade: Implement "Export as Image" in File menu. Supports png and jpg. Whether supported is determined based on file extension. Initial file name comes from map title. Export dialog is in glade file (need to move glade stuff into utils!) Not fully finished - spin boxes need hooked up Several new methods in all thought classes (update_bbox, export, get_max_area) 2006-10-16 Don Scorgie * src/MMapArea.py: When loading, ensure nthoughts > actual thoughts on canvas Don't create duplicate thought numbers. Maybe fix issue #6 (possibly) * src/DrawingThought.py: Don't draw multiple copies of drawings when saved / loaded * src/MainWindow.py: Fix maximised restore across 2 saves Merge of "Further Info" personal branch. This is an experiment into adding a "More Info" text area to the bottom of Map windows (when the user requests it). It also includes several other minor features. These are outlined below (main stuff described below all entries). Sorry for the long entry * doc/TheFuture: Updated what's done. Added new "non-feature" section * src/MainWindow.py: Save and restore maximised state of windows Remove old "number_windows" function * src/BaseThought.py: * src/DrawingThought.py: * src/TextBufferMarkup.py: * src/Browser.py: Don't display window. Let window display itself * src/MMapArea.py: * src/ImageThought.py: * src/TextThought.py: * data/labyrinth-ui.xml: Add "Drawing Mode" and "Add Image" to Mode menu (All): Add "more info" option to Mode menu. When selected, add a text entry to bottom of window (resizeable) to add further info to a thought. Save and restore this option. Save and restore text buffer across instances. Add new toolbar to bottom of window that will (in future) allow text to be bold, italics etc. Allow saving of these text properties (in future) using TextBufferMarkup.py, borrowed from Gourmet Recipe Manager (http://grecipe-manager.sourceforge.net/) Note: This isn't final. There is still quite a bit of work to do in it It's in a workable state though, so I'm committing. 2006-10-13 Don Scorgie * src/MMapArea.py: Update view when thought deleted (got lost somewhere along the line) * doc/TheFuture: Update - Text selection now works (damned ugly thought) * src/TextThought.py: * src/MMapArea.py: Make text selection with cursor by dragging work properly * src/BaseThought.py: * src/DrawingThought.py: * src/ImageThought.py: Add "selected" callback to thoughts. Used for notification when the user selects the thought. Makes text selection much easier Make thought.handle_movement return a bool indicating whether movement was in fact handled * src/TextThought.py: Fix delete key with no selection enabled * src/TextThought.py: Allow index to go to end of text / line when user requests it with mouse selection of text * src/BaseThought.py: * src/MMapArea.py: * src/TextThought.py: Rework lots of stuff to allow beginning of text selection with mouse. Right now, only moves the "index". Pressing shift + clicking will select a range. Click-dragging will not. Yet. Doesn't obey current selected areas either yet. * src/TextThought.py: Handle text selection using keyboard navigation (Ignore the hideous colour for now ;) * src/BaseThought.py: * src/DrawingThought.py: * src/ImageThought.py: * src/MMapArea.py: Pass modifier mask when handling keystrokes 2006-10-12 Don Scorgie * src/labyrinth.py: Only import utils once labyrinth knows where to look 2006-10-11 Don Scorgie * src/BaseThought.py: * src/DrawingThought.py: * src/utils.py: * src/MMapArea.py: * src/ImageThought.py: * src/TextThought.py: Split out drawing of thought outlines (into utils.py) Standardise (somewhat more) on what ul and lr really mean Fix resizing of drawing thoughts in edit mode * src/labyrinth.py: Make current path clearer in terminal printing * src/Makefile.am: Really regenerate defs.py and labyrinth when configure is run Might (hopefully) fix issue #1 * src/labyrinth.py: * src/Browser.py: Add new command line options: -o / --open: open a map from the given (full) path and filename -m / --map: open a map with the filename from the internal "database" (Based on patch from Kevin Kubasik. Fixes issue #3) * src/MainWindow.py: Add (stupid) icons to toolbar entries. Temporarily improves issue #2 until gtk+ fixes it 2006-10-10 Don Scorgie * doc/TheFuture: * doc/FileFormat: Rejig to be more readable in 80-column format * doc/TheFuture: List of goals for 1.0 release 2006-10-08 Don Scorgie * src/MainWindow.py: * src/Browser.py: Add missing strings to translations ======= Version 0.2 ====================== 2006-10-06 Don Scorgie * configure.ac: Bump version * src/MainWindow.py: Actually set the window icon properly. No, really this time * src/Browser.py: Make 'Open' and 'Delete' buttons only sensitive when a map is selected * src/ImageThought.py: Gracefully handle case where image file isn't available (display empty thought) * src/MMapArea.py: When bad (unended) links are loaded, assume them to be broken and remove them properly * po/POTFILES.in: Add ImageThought as it now contains translatable strings * doc/TheFuture: Update for v0.2 * doc/FileFormat: Add new file (incomplete) describing the save format for Labyrinth maps * doc/Makefile.am: Add FileFormat to EXTRA_DIST * src/MainWindow.py: * src/Browser.py: * src/labyrinth.py: Fix uninstalled mode. Silence glade warning when not really a warning * src/labyrinth.py: fix i18n stuff. Hopefully. 2006-10-04 Don Scorgie * Browser.py: * MainWindow.py: Fix window icon * configure.ac: * src/MainWindow.py: * src/labyrinth.py: * src/DrawingThought.py: * src/Browser.py: * src/MMapArea.py: * src/ImageThought.py: * src/TextThought.py: * Makefile.am: * po/LINGUAS: * po/ChangeLog: * po/POTFILES.in: Add i18n framework. Maybe. * src/Browser.py: Only activate 'Open' and 'Delete' when an item is selected * src/MMapArea.py: * src/MainWindow.py: Set mode back properly when image is inserted * src/MMapArea.py: Only allow drawing in "Drawing" mode. In edit mode, allow linking thoughts instead * src/Browser.py: * src/MainWindow.py: Set icon for browser and windows to be Labyrinth icon 2006-10-03 Don Scorgie * src/MainWindow.py: * src/BaseThought.py: * src/DrawingThought.py: * src/Links.py: * src/Makefile.am: * src/MMapArea.py: * src/ImageThought.py: * src/TextThought.py: * data/labyrinth-ui.xml: Add DrawingThought. Add "Drawing Mode" to toolbar Attempt to fix various problems with XML loading in all thought types Various code cleanups Make removing links work properly again (I hope) 2006-09-25 Don Scorgie * src/TextThought.py: Fix corner rounding when a thought only contains an 'i' * src/MMapArea.py: Fix problem when loading a map stuck in "AddImage" mode 2006-09-13 Don Scorgie * src/MMapArea.py: Use the FileChooser instead of the old, nasty FileSelector * src/ImageThought.py: * src/TextThought.py: Curve the corners of thoughts slightly. Makes the entire thing slightly prettier and less intimidating * src/ImageThought.py: Clip title to only be actual filename (ignore path and suffix) * src/BaseThought.py: * src/MMapArea.py: * src/ImageThought.py: Add a cursor change when resizing images, reflecting direction of change * src/BaseThought.py: * src/MMapArea.py: * src/ImageThought.py: Make loading and saving of image thoughts work. Fingers crossed. Should work. Cleanup temp stuff from BaseThought * src/TextThought.py: * src/ImageThought.py: Make links originate and end in the center of thoughts which looks so much cooler :) * src/MainWindow.py: * src/BaseThought.py: * src/Makefile.am: * src/MMapArea.py: * src/ImageThought.py: Beginnings of an Image Thought. New mode: "Add Image". Dosn't drop out when image added though :( In edit mode, image can be resized In mode mode, image is moved Links are screwed up Doesn't save or load (hence still screws up any maps using them) Can't add text to images * src/MMapArea.py: Fix typo (Rogi Lemar) * src/BaseThought.py: * src/MainWindow.py: * src/MMapArea.py: * src/TextThought.py: New base thought type: resizable. Will be used to contain drawings and images Hook up "New Image" Button to (temporarily) draw a basic resizable thought Fit everything else in required - Click-dragging (in edit mode) near a resizable thoughts edge will allow it to be resized - Move mode works as expected WARNING: as the resizable thought isn't fully supported, its likely to corrupt maps if used WARNING: No, really, any use of resizable thoughts is likely to destroy maps, creating random links and screwing everything up (They also aren't saved) 2006-09-09 Don Scorgie * src/MainWindow.py: * data/labyrinth-ui.xml: Added "add image" button in preperation for future work * src/Makefile.am: * src/defs.py.in: Fix compilation once again. Sigh 2006-09-06 Don Scorgie * configure.ac: * src/Makefile.am: * src/defs.py.in: Make defs get generated properly. Hopefully (taken from Alacarte) * src/Links.py: Import TextThought instead of Thoughts * data/labyrinth-??.png: * data/labyrinth.svg: * data/labyrinth.desktop.in: Add these vital files. Labyrinth should now show up in the Applications->Office menu Complete with its own (very ugly) icon * data/Makefile.am: Update to install icons and desktop file * TextThought.py: * MMapArea.py: Move Thoughts.py to new file Update MMapArea to use the file * BaseThought.py: New file: Base class for thoughts * Thoughts.py: * MMapArea.py: Update to use BaseThought. Rename Thought to TextThought * MMapArea.py: * Thoughts.py: Draw links behind thoughts to make thoughts feel more solid * MMapArea.py: Don't redraw on mouse motion when not watching Only redraw every 1/40th second to stop from hammering X server 2006-08-29 Don Scorgie * Initial Import into new home on Google What follows is the svn log dumped from the repo on my machine. Don't judge it too harshly ;) ------------------------------------------------------------------------ r85 | don | 2006-08-28 16:16:00 +0100 (Mon, 28 Aug 2006) | 2 lines Oops forgot to add in md5sums. ------------------------------------------------------------------------ r84 | don | 2006-08-28 16:01:54 +0100 (Mon, 28 Aug 2006) | 2 lines Update web page a little. Bump version up to 0.1. ------------------------------------------------------------------------ r83 | don | 2006-08-28 14:03:40 +0100 (Mon, 28 Aug 2006) | 2 lines Add 2 new screenshots showing the browser and current map window ------------------------------------------------------------------------ r82 | don | 2006-08-28 12:47:41 +0100 (Mon, 28 Aug 2006) | 2 lines Fix spelling mistake ------------------------------------------------------------------------ r81 | don | 2006-08-28 12:46:40 +0100 (Mon, 28 Aug 2006) | 2 lines More README update ------------------------------------------------------------------------ r80 | don | 2006-08-28 12:37:17 +0100 (Mon, 28 Aug 2006) | 2 lines Make the about dialog go away when requested ------------------------------------------------------------------------ r79 | don | 2006-08-28 12:31:15 +0100 (Mon, 28 Aug 2006) | 2 lines Minor addition to configure.ac ------------------------------------------------------------------------ r78 | don | 2006-08-28 12:29:53 +0100 (Mon, 28 Aug 2006) | 2 lines Make installation actually work (hopefully) ------------------------------------------------------------------------ r77 | don | 2006-08-28 12:14:41 +0100 (Mon, 28 Aug 2006) | 3 lines Remove Quit from menu in map windows Try and fix installation again. Fail :( ------------------------------------------------------------------------ r76 | don | 2006-08-27 20:23:09 +0100 (Sun, 27 Aug 2006) | 2 lines Update README and TheFuture a little more in light of the new browser ------------------------------------------------------------------------ r75 | don | 2006-08-27 18:43:15 +0100 (Sun, 27 Aug 2006) | 2 lines Stupid work-around to make maps save when open and quit is selected ------------------------------------------------------------------------ r74 | don | 2006-08-27 15:48:36 +0100 (Sun, 27 Aug 2006) | 3 lines Update glade to make prettier. Slightly. Make rows respond to activation ------------------------------------------------------------------------ r73 | don | 2006-08-26 16:07:15 +0100 (Sat, 26 Aug 2006) | 2 lines More browser work. Hooked up most of the signals required. ------------------------------------------------------------------------ r72 | don | 2006-08-26 14:26:58 +0100 (Sat, 26 Aug 2006) | 5 lines Updated configure, README First pass at Browser. Not too shabby though. Doesn't work just yet, but give it time ------------------------------------------------------------------------ r71 | don | 2006-08-24 22:03:02 +0100 (Thu, 24 Aug 2006) | 4 lines Update a couple of comments Add new TheFuture entry for current (soon) release Update NEWS for new release ------------------------------------------------------------------------ r70 | don | 2006-08-24 21:36:37 +0100 (Thu, 24 Aug 2006) | 2 lines Remove old cruft ------------------------------------------------------------------------ r69 | don | 2006-08-24 21:30:12 +0100 (Thu, 24 Aug 2006) | 3 lines Move functions.py to utils.py Just seems nicer somehow ------------------------------------------------------------------------ r68 | don | 2006-08-23 22:44:06 +0100 (Wed, 23 Aug 2006) | 16 lines Many, many updates from the local "rework" branch. * Add new functions.py to store functions that can be used by anyone * Rework Thoughts, links so only MMapArea has a copy of all of them * Remove / kill parent child relationship for thoughts - These make loading / Saving much easier - They make updating links much easier - They make considering things much easier * Save window geometry All old classes are still there. Much needs cleaned up. TheFuture needs cleaning properly ------------------------------------------------------------------------ r67 | don | 2006-08-14 18:30:04 +0100 (Mon, 14 Aug 2006) | 5 lines Update save to use only 2 passes (although, very hackily) Make loading actually delete thoughts when requested Make save only save when area is closed Update TheFuture somewhat (maybe) ------------------------------------------------------------------------ r66 | don | 2006-08-01 21:34:16 +0100 (Tue, 01 Aug 2006) | 3 lines More loading work. Seems to be mostly done (first pass). Issue remains with saving a doc twice: The text is repeated!The text is repeated! ------------------------------------------------------------------------ r65 | don | 2006-08-01 20:54:49 +0100 (Tue, 01 Aug 2006) | 3 lines More loading work. Almost working (badly). Now links are drawn, but it doesn't update properly and moving nodes breaks things ------------------------------------------------------------------------ r64 | don | 2006-08-01 19:58:25 +0100 (Tue, 01 Aug 2006) | 3 lines More work on loading. Coords are parsed and small squares shown on screen ------------------------------------------------------------------------ r63 | don | 2006-08-01 18:42:07 +0100 (Tue, 01 Aug 2006) | 4 lines First attempt at a pass at loading of files: * Load all files in save directory * Only set title of window ------------------------------------------------------------------------ r62 | don | 2006-07-31 20:44:41 +0100 (Mon, 31 Jul 2006) | 2 lines Save to a real-life file! ------------------------------------------------------------------------ r61 | don | 2006-07-31 20:17:55 +0100 (Mon, 31 Jul 2006) | 3 lines Lots more saving stuff. Prints out the complete (for now) save file in a pretty format ------------------------------------------------------------------------ r60 | don | 2006-07-31 19:36:13 +0100 (Mon, 31 Jul 2006) | 3 lines First attempt at saving to XML. Dumps the content of each node and the cursor position to stdout when double-click happens ------------------------------------------------------------------------ r59 | don | 2006-07-23 13:31:15 +0100 (Sun, 23 Jul 2006) | 2 lines Remove note_number since its no longer used ------------------------------------------------------------------------ r58 | don | 2006-07-16 16:56:42 +0100 (Sun, 16 Jul 2006) | 2 lines Remove dead python setup files ------------------------------------------------------------------------ r57 | don | 2006-07-16 16:52:05 +0100 (Sun, 16 Jul 2006) | 2 lines Remove extra files. Most are auto-generated. src/Labyrinth has moved ------------------------------------------------------------------------ r56 | don | 2006-07-16 16:47:25 +0100 (Sun, 16 Jul 2006) | 2 lines ... and another forgotten file ------------------------------------------------------------------------ r55 | don | 2006-07-16 16:46:30 +0100 (Sun, 16 Jul 2006) | 2 lines Move UI description to lower-case ------------------------------------------------------------------------ r54 | don | 2006-07-16 16:44:52 +0100 (Sun, 16 Jul 2006) | 2 lines Sigh. One more file to add ------------------------------------------------------------------------ r53 | don | 2006-07-16 16:44:10 +0100 (Sun, 16 Jul 2006) | 2 lines Add m4 subdir, forgotten in last commit ------------------------------------------------------------------------ r52 | don | 2006-07-16 16:42:32 +0100 (Sun, 16 Jul 2006) | 7 lines Move to autotools style setup. Allows installing to happen. Takes care of removing .py from labyrinth in bindir. Adapt everything to cope. Adapt everything to allow to run from either uninstalled or from installed instance. Based on auto* stuff from deskbar-applet. Added (empty) changelogs. ------------------------------------------------------------------------ r51 | don | 2006-07-15 19:19:11 +0100 (Sat, 15 Jul 2006) | 2 lines Update md5 sums of packages on web-page ------------------------------------------------------------------------ r50 | don | 2006-07-15 19:15:01 +0100 (Sat, 15 Jul 2006) | 4 lines Bump version v0.0.5 Update README et. al. to reflect changes. Discover install is broken. Decided "What the fuck.". Moving to new system (hopefully) soon. ------------------------------------------------------------------------ r49 | don | 2006-07-15 18:49:51 +0100 (Sat, 15 Jul 2006) | 2 lines Continued work on index for web-page ------------------------------------------------------------------------ r48 | don | 2006-07-15 18:41:25 +0100 (Sat, 15 Jul 2006) | 5 lines Make the primary thought red when not selected (Making it easier, for non-colour-blind people, to pick out). Move screenshot to -002. Add in -005 screenshot. Start updating website ------------------------------------------------------------------------ r47 | don | 2006-07-15 18:11:50 +0100 (Sat, 15 Jul 2006) | 12 lines Fix stupid bugs. Find out Python is actually EVIL. When it doesn't feel like it, it won't alert you to exceptions, just silently fail. Anyway: Make deletion of parent nodes work properly. Make title change as requested Handle deletion of primary node gracefully If title text is "", revert to "Unknown Map %d" Ensure selection of primary and current root works when deleting thoughts Probably a load more. True feature parity with before rewrite. Woo-hoo ------------------------------------------------------------------------ r46 | don | 2006-07-14 18:18:31 +0100 (Fri, 14 Jul 2006) | 2 lines Make window title the primary thought content. If > 27 chars, truncate. ------------------------------------------------------------------------ r45 | don | 2006-07-13 20:41:55 +0100 (Thu, 13 Jul 2006) | 2 lines Bring up to feature-parity with before. Delete *Classic versions ------------------------------------------------------------------------ r44 | don | 2006-07-13 20:19:23 +0100 (Thu, 13 Jul 2006) | 4 lines Fix a few regressions about editing and selecting different nodes and ... Nothing terribly interesting :( ------------------------------------------------------------------------ r43 | don | 2006-07-13 19:35:21 +0100 (Thu, 13 Jul 2006) | 3 lines Rework links. THings are now around the same level as before the rewrite, but much clearer in the code :) ------------------------------------------------------------------------ r42 | don | 2006-07-13 19:15:31 +0100 (Thu, 13 Jul 2006) | 2 lines Start Link rework. Make Area and Thoughts work together. ------------------------------------------------------------------------ r41 | don | 2006-07-12 22:57:45 +0100 (Wed, 12 Jul 2006) | 3 lines Rework of Thoughts. More clean now. Seems to work for the most part. No colouring. No links as yet. Not tried things out properly. ------------------------------------------------------------------------ r40 | don | 2006-07-12 21:49:24 +0100 (Wed, 12 Jul 2006) | 3 lines Oops. Forgot the delete function. Fixed. Still nothing works though ;) ------------------------------------------------------------------------ r39 | don | 2006-07-12 21:01:10 +0100 (Wed, 12 Jul 2006) | 5 lines Great MMapArea rewrite. Breaks program badly until Links and Thoughts are rewritten to support it. New code is much cleaner and easier to follow though. ------------------------------------------------------------------------ r38 | don | 2006-07-10 21:20:53 +0100 (Mon, 10 Jul 2006) | 2 lines Make Node deletion work. (Added a list of children to current thought) ------------------------------------------------------------------------ r37 | don | 2006-07-10 21:01:15 +0100 (Mon, 10 Jul 2006) | 2 lines Add list of children. Save drawing links the wrong way around ------------------------------------------------------------------------ r36 | don | 2006-07-10 20:46:49 +0100 (Mon, 10 Jul 2006) | 3 lines Make dragging of links work in editing mode. Make links update when dragging thoughts around. ------------------------------------------------------------------------ r35 | don | 2006-07-10 20:16:02 +0100 (Mon, 10 Jul 2006) | 2 lines Links now work as before ------------------------------------------------------------------------ r34 | don | 2006-07-10 19:47:59 +0100 (Mon, 10 Jul 2006) | 2 lines First attempt at adding a link type. Very, very broken for now. ------------------------------------------------------------------------ r33 | don | 2006-07-10 17:47:44 +0100 (Mon, 10 Jul 2006) | 4 lines Implement Moving and Editing Modes. Now, to edit a thought, you have to be in editing mode (default). To move thoughts around, you must be in move mode. ------------------------------------------------------------------------ r32 | don | 2006-07-10 17:24:51 +0100 (Mon, 10 Jul 2006) | 2 lines Add a silly "About" dialog ------------------------------------------------------------------------ r31 | don | 2006-07-10 17:08:43 +0100 (Mon, 10 Jul 2006) | 3 lines Make NewWindow, CloseWindow and Quit work as expected. Allows > 1 window at a time to be worked on ------------------------------------------------------------------------ r30 | don | 2006-07-10 16:46:38 +0100 (Mon, 10 Jul 2006) | 2 lines Add menubar and titlebar to window. Nothing works yet thought. ------------------------------------------------------------------------ r29 | don | 2006-07-10 15:59:41 +0100 (Mon, 10 Jul 2006) | 2 lines Add UI description. Update setup and MANIFEST to ship them ------------------------------------------------------------------------ r28 | don | 2006-07-10 15:50:30 +0100 (Mon, 10 Jul 2006) | 3 lines Add new file describing MainWindow Update script to use LabyrinthWindow ------------------------------------------------------------------------ r27 | don | 2006-07-10 14:45:34 +0100 (Mon, 10 Jul 2006) | 3 lines NEW VERSION Bump version number to 0.0.3 ------------------------------------------------------------------------ r26 | don | 2006-07-10 14:45:02 +0100 (Mon, 10 Jul 2006) | 2 lines Put the correct filenames on the webpage ------------------------------------------------------------------------ r25 | don | 2006-07-10 14:40:47 +0100 (Mon, 10 Jul 2006) | 2 lines Add in md5 sums ------------------------------------------------------------------------ r24 | don | 2006-07-10 14:35:46 +0100 (Mon, 10 Jul 2006) | 2 lines Remove MANIFEST from repo. It's automatically generated. ------------------------------------------------------------------------ r23 | don | 2006-07-10 14:35:23 +0100 (Mon, 10 Jul 2006) | 2 lines Add in webpage to repo. Including screenshot. ------------------------------------------------------------------------ r22 | don | 2006-07-10 14:31:48 +0100 (Mon, 10 Jul 2006) | 2 lines Include MANIFEST.in in dist, adding in other various files ------------------------------------------------------------------------ r21 | don | 2006-07-10 14:27:26 +0100 (Mon, 10 Jul 2006) | 3 lines Make package installable. Update TheFuture to show some ideas. Add NEWS file. Update README to reflect changes ------------------------------------------------------------------------ r20 | don | 2006-07-10 13:07:07 +0100 (Mon, 10 Jul 2006) | 2 lines Add a missing * ------------------------------------------------------------------------ r19 | don | 2006-07-10 06:02:05 +0100 (Mon, 10 Jul 2006) | 2 lines Add some docstrings. Create README. Update TheFuture ------------------------------------------------------------------------ r18 | don | 2006-07-10 02:45:16 +0100 (Mon, 10 Jul 2006) | 3 lines Remove some surplus prints. A selected thought will now become the root node. Yay. Means that there can now be multiple root thoughts. ------------------------------------------------------------------------ r17 | don | 2006-07-10 02:40:46 +0100 (Mon, 10 Jul 2006) | 3 lines Rework signals. Make single click select node. Make double click edit node. Make dragging nodes actually work as expected. I hope. ------------------------------------------------------------------------ r16 | don | 2006-07-10 01:14:01 +0100 (Mon, 10 Jul 2006) | 2 lines Make draggin work properly. Pretty cool. ------------------------------------------------------------------------ r15 | don | 2006-07-10 00:59:07 +0100 (Mon, 10 Jul 2006) | 3 lines Cleanup some syntax First attempt at drag-moving boxes around. Doesn't work. Yet. ------------------------------------------------------------------------ r14 | don | 2006-07-09 23:54:57 +0100 (Sun, 09 Jul 2006) | 3 lines Make thoughts selectable. Clicking in them makes them change back to "editing" state ------------------------------------------------------------------------ r13 | don | 2006-07-09 23:44:40 +0100 (Sun, 09 Jul 2006) | 3 lines ... and then I go and spoil it all by doing something stupid like ... chaning my mind. Home / End go to start / End of line ------------------------------------------------------------------------ r12 | don | 2006-07-09 23:40:52 +0100 (Sun, 09 Jul 2006) | 2 lines Added Home and End buttons to go to start and end of buffer ------------------------------------------------------------------------ r11 | don | 2006-07-09 23:37:35 +0100 (Sun, 09 Jul 2006) | 2 lines Add a corner in the top-left of the currently-being-edited note ------------------------------------------------------------------------ r10 | don | 2006-07-09 23:34:43 +0100 (Sun, 09 Jul 2006) | 2 lines Shade current root thought a hideous bluey color ------------------------------------------------------------------------ r9 | don | 2006-07-09 22:38:52 +0100 (Sun, 09 Jul 2006) | 2 lines Don't fall over when ctrl-C'd to quit. Personal peeve ------------------------------------------------------------------------ r8 | don | 2006-07-09 22:37:38 +0100 (Sun, 09 Jul 2006) | 3 lines Option parsing. Only 1 option - -h (for help) At least shows something now ------------------------------------------------------------------------ r7 | don | 2006-07-09 22:09:59 +0100 (Sun, 09 Jul 2006) | 2 lines Update require to actually check version of Gtk available (maybe) ------------------------------------------------------------------------ r6 | don | 2006-07-09 22:04:51 +0100 (Sun, 09 Jul 2006) | 4 lines Make the background white If current_thought is empty when finishing editing, don't bother drawing it ------------------------------------------------------------------------ r5 | don | 2006-07-09 21:10:07 +0100 (Sun, 09 Jul 2006) | 5 lines Added a small overview of where this might be leading in the next version Bump version number ------------------------------------------------------------------------ r4 | don | 2006-07-09 21:04:16 +0100 (Sun, 09 Jul 2006) | 2 lines Make MoveUp and MoveDown work as expected ------------------------------------------------------------------------ r3 | don | 2006-07-09 19:58:18 +0100 (Sun, 09 Jul 2006) | 3 lines Make text insertion work First pass at Up navigation. Very broken ------------------------------------------------------------------------ r2 | don | 2006-07-09 19:18:25 +0100 (Sun, 09 Jul 2006) | 3 lines Moving back / forward while editing thought Backspace / delete actually work as expected ------------------------------------------------------------------------ r1 | don | 2006-07-09 18:59:02 +0100 (Sun, 09 Jul 2006) | 2 lines Initial Import of Labyrinth to new home ------------------------------------------------------------------------ labyrinth-0.6/NEWS000066400000000000000000000127421204476542500140710ustar00rootroot0000000000000012/11/06 v0.3 (Beautiful Insane) ------------- New Features: * Open maps from the command line (allowing Beagle to work with labyrinth properly) - Kevin Kubasik (Issue #3) * Add "Further Info" to all thoughts allowing further notes to be attached to any thought. Some work borrowed from Gourmet Recipe Manager (http://grecipe-manager.sourceforge.net/) * Store maximised state for maps across saves * Export as Image (png and jpeg) * Selecting text within thought now works * Cut / copy / paste using clipboard and primary selection * Much improved handling of multibyte characters and non-English keyboard layouts * Massively cool new tango-ified icon (Josef Vybíral) * Large Browser internal rework. Added optional trayicon (disabled by default) Can be enabled by passing --use-tray-icon to labyrinth - First step towards an applet (Andreas Sliwka) * Much improved Browser window layout, adding menus and moving the "Help->About" from Map windows to the Browser window, among other things (Jean-François Fortin Tam, issue #15) * Add debug printing framework (Andreas Sliwka) * Change cursor when moving mouse across thoughts to reflext currently available action * Merge "Move" and "Edit" mode into single "Edit" mode * Selection of multiple thoughts now possible * More performance work * Massively improved RTL support * Add (experimental) Undo / Redo framework * Add menu entry to link / unlink selected thoughts * Use tango-ified colours for text selection colour and to denote selected and root thought (until theme support is added) Fixes: * Regenerate defs.py when required (Issue #1) * Add icons to toolbar as temprary fix for issue #2 * Fix thought numbers across saves (issue #6 and #32) * Don't "jerk" thoughts around when moving (issue #19) * Escape should finish editing thoughts (issue # 23) * Backspace at start of thoughts breaks things royally (issue #25) * Problem resizing drawings / images using the top-right corner * ctrl-a selects either all thoughts or all text in (currently editing) thought * Improvements to handling of arrow keys within editing thoughts * Fix several unclear and confusing messages (Issue #28) * Change mode when inserting image. Remember current mode across saves properly (Requires PyGtk >= 2.10) * Fix export dialog to show up properly (Issue #29) Translations: * ru (Alexandre Prokoudine) * nl (Rigo Ketelings and Max Beauchez) * pl (Tomasz Dominikowski) * pt_BR (Leonardo Gregianin) * ca (Gil Forcada) * cs (Josef Vybíral) * fr (Mathieu Leduc-Hamel and Jean-François Fortin Tam) * pt_PT (Luis Gomes) * eu (Zunbeltz Izaola) * sv (Robin Sonefors) * de (Raphael Schmid and Florian Ludwig) Infrastructure Changes: * Add list of 1.0 targets to doc/TheFuture * Fantastic new website design by Florian Ludwig v0.2 ---- New Features: * Base thought class for future thought types to derive from * Add new document to docs describing (current) file format * Add i18n framework. No translations yet thought * Add Image Thought for adding images from external files * Add image mode for adding an image * Add Drawing Thought for simple drawings * Add drawing mode for drawing in drawing thoughts * Both Image and Drawing Thoughts are resizable by dragging corners / edges * New (crappy) Labyrinth icon * Add menu entry (shows up in Applications->Office) * Set window icon to new Labyrinth icon in Browser and map windows * All thought types now have slightly rounded corners * When resizing thoughts, change the cursor to reflect this * Links now originate at the centre of thoughts, making them look prettier Fixes: * Fix uninstalled mode * Only allow 'Open' and 'Delete' to be used when a map is selected in Browser window * Make removal of links work properly * Various code cleanups (Thanks to Rogi Lemar) * Make defs get generated properly (From Alacarte) * Only redraw every 1/40th second when required to stop hammering X server * Draw links behind thoughts for added solidity v0.1 ---- New features: * Tomboy style loading and saving of maps * Saves all thoughts and links * Saves window title, current mode, geometry and placement of window * Link strengthening and weakening * Drag a link from a current parent to a current child to strengthen the link by 1 * Drag from child to parent to weaken the link by 1 * If strength reaches 0, link is deleted * Massive internal rework (Yes, again) * No more parent-child relationship in code * Makes it much easier to maintain and write save files for * Make install work again v0.0.5 ------ New features: * Menubar and toolbar added. Beginnings of a user-interface. Yay! * Allow multiple Labyrinth windows to open at the same time * Added an About dialog * Allow windows to be closed (ctrl-W) or quit the app (ctrl-Q). Also from the menu. * Different modes: * Move Mode allows you to drag thoughts around and delete them with the delete / backspace key. * Edit Mode allows you to enter new thoughts, edit old thoughts and link up thoughts. * Deletion of nodes. Either through delete / backspace key in Move Mode or by menu item in any mode. Note, when no node is selected, this silently fails. The menu item is always sensitive. * Massive code rework. Code is now cleaner than before and easier to work with. (Of course, it will likely be screwed with again before becoming serious) * Window title becomes Primary Thought content. If no primary thought, default to "Untitled Map %d" * Break Install v0.0.2 ------ Initial release labyrinth-0.6/README.rst000066400000000000000000000107761204476542500150660ustar00rootroot00000000000000Labyrinth ========= Labyrinth is a lightweight mind-mapping tool, written in Python using Gtk and Cairo to do the drawing. It is intended to be as light and intuitive as possible, but still provide a wide range of powerful features. A mind-map is a diagram used to represent words, ideas, tasks or other items linked to and arranged radially around a central key word or idea. It is used to generate, visualise, structure and classify ideas, and as an aid in study, organisation, problem solving, and decision making. (From wikipedia) Currently, Labyrinth provides 3 different types of thoughts, or nodes - Text, Image and Drawing. Text is the basic standard text node. Images allow you to insert and scale any supported image file (png, jpeg, svg). Drawings are for those times when you want to illustrate something, but don't want to fire up a separate drawing program. It allows you to quickly and easily sketch very simple line diagrams. License ------- This software is released under the GNU GPL v2 (or later) license. All source files are included in this, unless explicitly stated in the source file itself. For copyright owners, please refer to the source files individually. The "labyrinth" icon (``data/labyrinth.svg`` and ``data/labyrinth-*.png``) is copyright Josef Vybíral and is released under the GNU GPL v2 license. Please refer to the "COPYING" file for a complete copy of the GNU GPL v2 license. All documentation (This file, anything in the docs directory) released with this package is released as public domain. The documentation, you can do with as you please. Requirements ------------ * Python >= 2.6 * gtk+ * pygtk * pygobject * pycairo * PyXDG The minimum required versions are unknown, but any reasonably recent packages should work. How to use it ------------- From the top directory of the package, run the command:: ./labyrinth You can also install Labyrinth with ``python setup.py install``, and ``./install_data_files.sh`` for icons and translations. It can then be run as ``labyrinth``. This will open a browser window, showing you all the maps currently available and allow you to modify / delete them and create new maps. The title is (currently) the primary thought text(truncated to 27 characters long). This is usually the first thought created in a new map. In a new map, single click somewhere to create a new "thought". This is your root. Add your main thought to this. Click somewhere else will create a new thought, linked to the first. To move thoughts around, single-click and drag. To edit a current thought, double click on it (text thoughts only). Drawing and Image thoughts can be resized using their corners / sides. Links between thoughts can be created, strengthened and weakened. To create a new link, in edit mode, click and drag from the "parent" thought to the "child" thought while holding down the ctrl key. Doing this with a link already in place will strengthen the link by 1 and dragging from child to parent will weaken the link by 1. If the link goes to 0 strength (it starts at 2), the link is deleted. Links can also be created / deleted by selecting both thoughts (hold down the shift key to select > 1 thought) and choosing "Edit->(Un)Link Thoughts" from the menu (shortcut: Ctrl-L). Loading and saving of maps is in the tomboy style - they are automatically saved, you shouldn't have to worry about them. For reference anyway, the maps are saved in ``~/.gnome2/labyrinth/.map``. Future Plans ------------ In ``doc/TheFuture``, there are a list of goals for a 1.0 release and for the next release. Releases are feature-based at this stage. Once all the required features are in place, a release is made. However a release may also be made without all the changes if it is deemed that this is in the best interest. Getting the Latest Development Code ----------------------------------- Development happens on Github. See https://github.com/labyrinth-team/labyrinth Helping Out and Questions ------------------------- If you have any questions about Labyrinth or just want to be part of our gang, the mailing list address is labyrinth-devel@googlegroups.com If you want to help out with developing labyrinth, please let us know on the mailing list. We aren't just looking for coders. We're looking for packagers, artists, doc writers, interface designers, web developers, and just about anyone else. Translations now take place `on Transifex `_. If you want to use Transifex in your language, it's very easy to get started. labyrinth-0.6/Windows/000077500000000000000000000000001204476542500150165ustar00rootroot00000000000000labyrinth-0.6/Windows/COPYING.txt000066400000000000000000000431101204476542500166660ustar00rootroot00000000000000 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. labyrinth-0.6/Windows/WinSetup.bat000066400000000000000000000131261204476542500172670ustar00rootroot00000000000000@ECHO OFF rem This is a script to automate generating Windows packages rem It is fairly basic and still requires quite a bit of rem user-interaction. I'll try and include what needs doing rem In addition, the script makes various assumptions about locations rem and such. rem if you really want to help, you'd write me a nice long rem set of instructions on how to generate all this stuff under rem cygwin and how to make most of this obsolete (if possible) rmdir /S /Q dist mkdir dist del src\defs.py copy Windows\defs.py src\defs.py rem Assumes python is at this location. Change to proper location c:\Python24\python.exe Windows\winsetup.py py2exe copy Windows\labyrinth.lnk dist\ copy Windows\labyrinth.bat dist\ mkdir dist\data_files\share\locale\ca\LC_MESSAGES mkdir dist\data_files\share\locale\cs\LC_MESSAGES mkdir dist\data_files\share\locale\de\LC_MESSAGES mkdir dist\data_files\share\locale\eu\LC_MESSAGES mkdir dist\data_files\share\locale\fr\LC_MESSAGES mkdir dist\data_files\share\locale\it\LC_MESSAGES mkdir dist\data_files\share\locale\nl\LC_MESSAGES mkdir dist\data_files\share\locale\pl\LC_MESSAGES mkdir dist\data_files\share\locale\pt_BR\LC_MESSAGES mkdir dist\data_files\share\locale\pt\LC_MESSAGES mkdir dist\data_files\share\locale\ru\LC_MESSAGES mkdir dist\data_files\share\locale\sv\LC_MESSAGES rem Assumes GetText-Tools is installed in c: rem change as appropriate. rem Also, a nice loop would be great here... cd po c:\GetText-Tools\bin\msgfmt.exe -o ..\dist\data_files\share\locale\ca\LC_MESSAGES\labyrinth.mo ca.po c:\GetText-Tools\bin\msgfmt.exe -o ..\dist\data_files\share\locale\cs\LC_MESSAGES\labyrinth.mo cs.po c:\GetText-Tools\bin\msgfmt.exe -o ..\dist\data_files\share\locale\de\LC_MESSAGES\labyrinth.mo de.po c:\GetText-Tools\bin\msgfmt.exe -o ..\dist\data_files\share\locale\eu\LC_MESSAGES\labyrinth.mo eu.po c:\GetText-Tools\bin\msgfmt.exe -o ..\dist\data_files\share\locale\fr\LC_MESSAGES\labyrinth.mo fr.po c:\GetText-Tools\bin\msgfmt.exe -o ..\dist\data_files\share\locale\it\LC_MESSAGES\labyrinth.mo it.po c:\GetText-Tools\bin\msgfmt.exe -o ..\dist\data_files\share\locale\nl\LC_MESSAGES\labyrinth.mo nl.po c:\GetText-Tools\bin\msgfmt.exe -o ..\dist\data_files\share\locale\pl\LC_MESSAGES\labyrinth.mo pl.po c:\GetText-Tools\bin\msgfmt.exe -o ..\dist\data_files\share\locale\pt_BR\LC_MESSAGES\labyrinth.mo pt_BR.po c:\GetText-Tools\bin\msgfmt.exe -o ..\dist\data_files\share\locale\pt\LC_MESSAGES\labyrinth.mo pt_PT.po c:\GetText-Tools\bin\msgfmt.exe -o ..\dist\data_files\share\locale\ru\LC_MESSAGES\labyrinth.mo ru.po c:\GetText-Tools\bin\msgfmt.exe -o ..\dist\data_files\share\locale\sv\LC_MESSAGES\labyrinth.mo sv.po cd .. rem and that's it folks. From here on out, you need user-interaction rem (sorry). Copy relevant files from the GTK install (Need a list of rem what can be deleted etc. and then run innosetup using the given iss rem This is specific to my install. Copying files from GTK install rem in c:. Edit as needed ;) mkdir dist\data_files\lib copy c:\GTK\lib dist\data_files\lib mkdir dist\data_files\lib\gtk-2.0 mkdir dist\data_files\lib\gtk-2.0\2.4.0\engines mkdir dist\data_files\lib\gtk-2.0\2.4.0\immodules mkdir dist\data_files\lib\gtk-2.0\2.4.0\loaders mkdir dist\data_files\lib\libglade mkdir dist\data_files\lib\pango mkdir dist\data_files\lib\pango\1.4.0\modules copy c:\GTK\lib\gtk-2.0\2.4.0\engines dist\data_files\lib\gtk-2.0\2.4.0\engines copy c:\GTK\lib\gtk-2.0\2.4.0\immodules dist\data_files\lib\gtk-2.0\2.4.0\immodules copy c:\GTK\lib\gtk-2.0\2.4.0\loaders dist\data_files\lib\gtk-2.0\2.4.0\loaders copy c:\GTK\lib\libglade dist\data_files\lib\libglade copy c:\GTK\lib\pango\1.4.0\modules dist\data_files\lib\pango\1.4.0\modules mkdir dist\data_files\etc mkdir dist\data_files\etc\fonts mkdir dist\data_files\etc\gtk-2.0 mkdir dist\data_files\etc\pango copy c:\GTK\etc\fonts dist\data_files\etc\fonts copy c:\GTK\etc\gtk-2.0 dist\data_files\etc\gtk-2.0 copy c:\GTK\etc\pango dist\data_files\etc\pango mkdir dist\data_files\share\themes\MS-Windows\gtk-2.0 mkdir dist\data_files\share\themes\Default\gtk-2.0-key mkdir dist\data_files\share\themes\Metal\gtk-2.0 mkdir dist\data_files\share\themes\Raleigh\gtk-2.0 mkdir dist\data_files\share\themes\Redmond95\gtk-2.0 copy c:\GTK\share\themes\MS-Windows\gtk-2.0 dist\data_files\share\themes\MS-Windows\gtk-2.0 copy c:\GTK\share\themes\Default\gtk-2.0-key dist\data_files\share\themes\Default\gtk-2.0-key copy c:\GTK\share\themes\Metal\gtk-2.0 dist\data_files\share\themes\Metal\gtk-2.0 copy c:\GTK\share\themes\Raleigh\gtk-2.0 dist\data_files\share\themes\Raleigh\gtk-2.0 copy c:\GTK\share\themes\Redmond95\gtk-2.0 dist\data_files\share\themes\Redmond95\gtk-2.0 copy c:\GTK\share\locale\ca\LC_MESSAGES dist\data_files\share\locale\ca\LC_MESSAGES copy c:\GTK\share\locale\cs\LC_MESSAGES dist\data_files\share\locale\cs\LC_MESSAGES copy c:\GTK\share\locale\de\LC_MESSAGES dist\data_files\share\locale\de\LC_MESSAGES copy c:\GTK\share\locale\eu\LC_MESSAGES dist\data_files\share\locale\eu\LC_MESSAGES copy c:\GTK\share\locale\fr\LC_MESSAGES dist\data_files\share\locale\fr\LC_MESSAGES copy c:\GTK\share\locale\it\LC_MESSAGES dist\data_files\share\locale\it\LC_MESSAGES copy c:\GTK\share\locale\nl\LC_MESSAGES dist\data_files\share\locale\nl\LC_MESSAGES copy c:\GTK\share\locale\pl\LC_MESSAGES dist\data_files\share\locale\pl\LC_MESSAGES copy c:\GTK\share\locale\pt\LC_MESSAGES dist\data_files\share\locale\pt\LC_MESSAGES copy c:\GTK\share\locale\pt_BR\LC_MESSAGES dist\data_files\share\locale\pt_BR\LC_MESSAGES copy c:\GTK\share\locale\ru\LC_MESSAGES dist\data_files\share\locale\ru\LC_MESSAGES copy c:\GTK\share\locale\sv\LC_MESSAGES dist\data_files\share\locale\sv\LC_MESSAGES labyrinth-0.6/Windows/defs.py000066400000000000000000000001041204476542500163040ustar00rootroot00000000000000prefix = "" DATA_DIR = "glade\\" VERSION="0.3" pkgdatadir="glade\\" labyrinth-0.6/Windows/lab.iss000066400000000000000000000014751204476542500163030ustar00rootroot00000000000000[Setup] AppName=Labyrinth AppVerName=Labyrinth 0.3 AppPublisher=Don Scorgie AppPublisherURL=http://www.gnome.org/~dscorgie/labyrinth.html DefaultDirName={pf}\labyrinth DefaultGroupName=Labyrinth DisableProgramGroupPage=true OutputBaseFilename=labyrinth-setup Compression=lzma SolidCompression=true AllowUNCPath=false VersionInfoVersion=0.3 VersionInfoCompany=None VersionInfoDescription=A Mind mapping tool PrivilegesRequired=admin LicenseFile=COPYING.txt [Dirs] Name: {app}; Flags: uninsalwaysuninstall; [Files] Source: ..\dist\*; DestDir: {app}; Flags: ignoreversion recursesubdirs createallsubdirs [Icons] Name: {group}\labyrinth; Filename: {app}\data_files\labyrinth.exe; WorkingDir: {app}\data_files [Run] Filename: {app}\labyrinth.bat; Description: {cm:LaunchProgram,labyrinth}; Flags: nowait postinstall skipifsilent labyrinth-0.6/Windows/labyrinth.bat000066400000000000000000000000551204476542500175020ustar00rootroot00000000000000@ECHO OFF cd data_files start labyrinth.exelabyrinth-0.6/Windows/labyrinth.ico000066400000000000000000000033361204476542500175130ustar00rootroot00000000000000(0u;ѣx^0_mA̘gvMȎVe4m8ɚrgʓ_b2YƖji6ΠtФ}k7ɐZ˖d`0d3o9ʗia1f4ɑ[^0l7t;ʔ_55&&'C 6&89:(+!-0123,A "D @./345&8'7#0034%% /$?BC>6&78'997*':;<)= 834%5%`labyrinth-0.6/Windows/labyrinth.lnk000066400000000000000000000034261204476542500175250ustar00rootroot00000000000000LF@ ,XaR cb-H E%6B1h5LABYRI~1*g5h5Labyrinth41h5dist h5h5distN2-h5 LABYRI~1.BAT2h5h5labyrinth.batv-uLC:\Documents and Settings\don\My Documents\Labyrinth\dist\labyrinth.bat.\labyrinth.bat9C:\Documents and Settings\don\My Documents\Labyrinth\distGC:\Documents and Settings\don\My Documents\Labyrinth\data\labyrinth.ico`Xdon-fhfosnvp6v3*MpAmM]hǻ%o )x*MpAmM]hǻ%o )x%USERPROFILE%\My Documents\Labyrinth\data\labyrinth.ico\My Documents\Labyrinth\dist\lab.bat"%USERPROFILE%\My Documents\Labyrinth\data\labyrinth.ico(3dl|q|3@d|3{t|{|304wPB @ ,{w4{w<c>wk>w0 47|7| 0p.|.|!.|;0@\`|.|P,PlorTable15|LB| |\X2labyrinth-0.6/Windows/winsetup.py000066400000000000000000000050631204476542500172520ustar00rootroot00000000000000#!/usr/bin/env python # -*- coding: ISO-8859-1 -*- __revision__ = '$Id: $' # Copyright (c) 2005 Vasco Nunes # 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 Library 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 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA # You may use and distribute this software under the terms of the # GNU General Public License, version 2 or later # for build this on a win32 environment and becames with a standalone distribution # a base python 2.4 for 2in32 instalation must be present # along with gtk+ development libraries # pywin32com extensions, reportlab module, pygtk for win32 and pysqlite-1.1.7.win32-py2.4 (current win32 distro install is using this pysqlite 3 version) import time import sys # ModuleFinder can't handle runtime changes to __path__, but win32com uses them try: import modulefinder import win32com for p in win32com.__path__[1:]: modulefinder.AddPackagePath("win32com", p) for extra in ["win32com.shell"]: #,"win32com.mapi" __import__(extra) m = sys.modules[extra] for p in m.__path__[1:]: modulefinder.AddPackagePath(extra, p) except ImportError: # no build path setup, no worries. pass from distutils.core import setup import glob import py2exe opts = { "py2exe": { "includes": "cairo,pangocairo,pango,atk,gobject,xml.dom,xml.dom.minidom,threading,shutil,pygtk,gtk,sys,gtk.glade", "optimize": 2, "dist_dir": "dist\\data_files", } } setup( name = "Labyrinth", description = "Labyrinth", version = "0.3", windows = [ { "script": "src\\labyrinth.py", "icon_resources": [(1, "Windows\labyrinth.ico")] }], options = opts, data_files=[ ("images", glob.glob("data\\*.png")), ("data", glob.glob("data\\*.glade")), ("data", glob.glob("data\\*.xml")), ("", glob.glob("src\\*.py"))], ) labyrinth-0.6/data/000077500000000000000000000000001204476542500142755ustar00rootroot00000000000000labyrinth-0.6/data/labyrinth-16.png000066400000000000000000000010661204476542500172260ustar00rootroot00000000000000PNG  IHDRasBIT|dtEXtSoftwarewww.inkscape.org<IDAT8S=hSQ=JCyfPCRJR`" ]`tCѡtPH Nb(.J\tP^yi}]|1cr?s fF/=m#\!AkjuT*}rB#!>?X) Dc qH)/-l'lZv ۃ/A|3̌ve fK<3~WV 7\T Dvqktj̻&!l쿭~zdԊzC"b`fqA>WJYg5Oq4ɂM/"hADhBkVʢc]na zcE f^d@":Rl;axKs$ aZ+>0 tS(. AP@ZB NA7YA(DЋ 'TfY ILڨ3p|﹌v`eccc-K-L͍8λlzTJDB@&"Ȳ(i5(rDnd)xtBd-jBSLQ.m{!_?5ӛ_y)OnզLZ׶vX}H>>j=D\V{eu1'c)FWGs===#" n{ASQl9QP"a龽s( 'U$ip8nq1#{ǠZ}`q8!~8 >DRg/sb 3TM9ߔVe-JӲx?]^Ƕd,W|> =Lyo"gcbgT*3iѶ;tIą,_Ĺ &;$%;='$I~TEk{>oZ+"H" t\7ڳ:Y0PC@h_X,>T*r2}MN$)WY#LK'ruDo }=<<.UkD"1 hJ3RIENDB`labyrinth-0.6/data/labyrinth-24.png000066400000000000000000000015131204476542500172220ustar00rootroot00000000000000PNG  IHDRw=sBIT|dtEXtSoftwarewww.inkscape.org<IDATHUMHTQ{͘3CRQbI+ i*6ZPh fd6Rf-*P7!n*!%tV!Ơ̄wO7ќР{2"^BS!)WlB"Pv(..WXXh3mz$ImʛpUTC&H9, ȅ}@D&g@Yc~PZd&xo(0v)p%IE 8nrSOc"_1Ɏ ɊMDp8ܤX\Z+LFlɒbv&-RI$fd-.lBII#X\;qr2bdF7N*4_S !s 8J$@6ʘ<ٕ 2hfnC=xpC>e`Vtcǥٸ-`ک;KR5])]]QhW emM}/+wnt"&3 SvF&[/\,wI4ϹyY,**qq155T^^nRM2S46Հ `?˳[|>aV`+ /V4NgF[ $ 8XT ")&t\IENDB`labyrinth-0.6/data/labyrinth-ui.xml000066400000000000000000000025241204476542500174310ustar00rootroot00000000000000 labyrinth-0.6/data/labyrinth.desktop000066400000000000000000000003251204476542500176640ustar00rootroot00000000000000[Desktop Entry] Name=Labyrinth Mind-mapping GenericName=Mind-mapping Comment=Map your mind Exec=labyrinth Icon=labyrinth StartupNotify=true Terminal=false Type=Application Categories=GNOME;GTK;Application;Office; labyrinth-0.6/data/labyrinth.glade000066400000000000000000001371251204476542500173000ustar00rootroot00000000000000 False Export Map as Image 591 419 gtk-save-as dialog True False True False end gtk-cancel -6 True True True False False True False False 0 gtk-ok -5 True True True False False True False False 1 False True end 0 True False 6 0 none True False 12 True False True False 2 3 Complete Map True True False False True True Visible Area True True False False True True rb_complete_map 1 2 True True False False True True 10 10 10000000000 1 10 0 1 2 3 1 2 True True False False True True 10 10 10000000000 1 10 0 1 2 3 True False 0 Width right 1 2 True False 0 Height right 1 2 1 2 4 False False 0 True False False False 5 1 True False True True 2 True False <b>Export Map</b> True label_item True True 2 False Labyrinth Maps True False True False True False False _File True False gtk-new True False False True True gtk-open True False False True True gtk-delete True False False True True True False False Import... True True False gtk-quit True False False True True True False False _Help True False gtk-help True False False True True gtk-about True False False True True False False 0 True False both True False False True gtk-new False True True False False True gtk-open False True True False False gtk-delete False True False True 1 True True automatic automatic in True True True True 2 False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 3 3 True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK down 3 2 3 GTK_FILL True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 2 3 1 2 GTK_FILL True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK up 3 GTK_FILL True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK left 1 2 GTK_FILL True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 1 2 1 2 True True True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK automatic automatic True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK word 1 True True True True 2 True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK False gtk-bold False True True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK False gtk-italic False True True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK False gtk-underline False True True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK False True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK False True True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK False False True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK False True True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK False #000000000000 False True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK False True True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_MOTION_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK False #000000000000 False False True 3 False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 5 center-on-parent dialog True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 2 True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK end False True end 0 True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK URL False True 0 True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK False False True True True True end 1 False True 1 True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK Align Left True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK False True False True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK stock_graphics-align-left Align Right True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK False True False True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK stock_graphics-align-right Align Vertical Center True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK False True False True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK stock_graphics-align-center Align Top True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK False True False True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK stock_graphics-align-top Align Bottom True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK False True False True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK stock_graphics-align-bottom Align Horizontal Center True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK False True False True False GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK stock_graphics-align-center labyrinth-0.6/data/labyrinth.svg000066400000000000000000000352171204476542500170220ustar00rootroot00000000000000 image/svg+xml Labyrinth mindmapping tool 20. 10. 2006 Josef 'cornelius' Vybíral Josef 'cornelius' Vybíral Josef 'cornelius' Vybíral http://cornelius.gimp.cz http://cornelius.gimp.cz labyrinth mindmapping mindmap map mind labyrinth-0.6/doc/000077500000000000000000000000001204476542500141315ustar00rootroot00000000000000labyrinth-0.6/doc/FileFormat000066400000000000000000000265471204476542500161220ustar00rootroot00000000000000LAST UPDATE: 6th October 2006 0. Preamble ----------- This describes the current save format for Labyrinth maps. It is intended to make life easier for anyone interested in accessing them or importing them. WARNING: At the time of writing, Labyrinth is at version 0.2. The file format is liable to change up to V1.0. The format described here isn't the final version. I'll keep this file up to date with any changes that happen to the format. The date at the top of the file states when this was last updated. 1. Location ----------- Currently, Labyrinth stores its files "internally". The files themselves can be found in the $HOME/.gnome2/labyrinth/ folder with a format like f59b62e734f3f65a1e34d7bf1fc33bb191c3777f.map. That is to say .map though labyrinth will attempt to read any .map file in that folder. The hexdigest is created using the sha of the generated XML the first time the file is saved. Currently, Labyrinth is unable to import / export in other formats (hey, its only at v0.2). This is (potentially) planned for V0.3. The maps are saved in standard (i.e. non-pretty) XML - all nodes on 1 line. This makes them difficult to read, but makes the formatting come out properly within text thoughts. Pretty formatting + python seems to screw up the text thought formatting in some cases. 2. Format --------- The basic format is a flat XML file. The file starts with the XML declaration: An example top-level node is: All other nodes are children of this. MMap is the name of the node (duh). All files must have this. In addition, each of the Attributes are required to form a valid file: Attribute Description ----------------------------------- mode The current "mode" Labyrinth is working in for that map 1: "Edit" mode - typing into thoughts, linking thoughts, resizing thoughts (if available) 2: "Move" mode - move thoughts around 3: "Image" mode - add an (external) image to the map. Clicking somewhere will pop up a dialog to select the image file 4: "Drawing" mode - With drawing thoughts (described below), draw within thoughts. Otherwise, add new drawing thought and begin drawing (in empty space) number Current map number. Used internally to set initial title. Can be set to any number. (Currently broken. I think) position Screen location (in pixels) of upper-left corner of map window size Size (in pixels) of map window title Map name. Generally same as primary root text 3. Children ----------- The children are the "meat" of the map. They come in several flavours, described in subsections here 3.1. Links ---------- Unlike other programs (I believe), Labyrinth stored links as top-level objects. That is to say, they don't actually belong to thoughts. An example link might look like: Again, all attributes must be specified (sorry!) Attribute Description --------------------------------------- child The thought number of the child thought connected by the link parent The thought number of the originating thought for the link start Canvas coordinates of the start location (parent location) for the link end Canvas coordinates of the end location (child location) for the link strength The "Strength" of the link. In Labyrinth, specifies the line width in pixels. Integer value always (for now). 3.2. Thoughts ------------- Thoughts, in Labyrinth-speak, are the text, images and drawing that appear on the canvas. There are 3 types currently and each have some attributes in common. The three types are: Text, Image and Drawing. Text is (surprisingly) text thoughts. Image thoughts are external images while drawings are "internal" images - simple lines that the user has drawn to make simple diagrams. 3.2.1. Common Attributes ------------------------ As stated above, thoughts have several attributes that may be set that are common across all thought types: Attribute Description --------------------------------------- current_root If set, the thoughts is "selected" - any new thoughts are automatically linked to this one (Currently, only 1 may be set. In Labyrinth, they show up as blue) primary_root The "Major thought" for the map. Generally, places at the centre of the map (Only 1 may be set. In Labyrinth, they show up as reddish-pink) ul-coords The upper-left canvas coords for the thought lr-coords The lower-right canvas coords for the thought identity The thought number (for link child / parent numbers and other things internally) Current_root and primary_root are only set when the thought is actually current root or primary root respectively. Otherwise, these are not set. Examples of these are given later. 3.2.2. Text Thoughts -------------------- Labyrinth 0.2 Text thoughts are denoted by "thought" XML elements. In addition to the common attributes, there are several more available Attribute Description --------------------------------------- cursor Cursor location in text. Specified in terms of characters. edit Whether the current node is being edited. Thoughts being edited don't get a full box drawn around then, instead only a small sector is drawn in the upper-left corner in Labyrinth The text within the XML node is as should be displayed onscreen (i.e. line-breaks mean the line breaks at that point within the thought). As before, "edit" is only set if the thought is currently being edited. 3.2.3. Image Thoughts --------------------- Attribute Description --------------------------------------- file The file path for the image to use within the thought image_height Labyrinth can resize images. This gives the current height the image should be image_width Ditto above for width 3.2.4. Drawing Thoughts ----------------------- \ The "big one". Children of the drawing thought are all the points that make up the image. Before that, the attributes for the drawing_thought itself. Attribute Description --------------------------------------- max_{x,y} The {x,y} location of the furthest {right,down} points of the drawing. Used to determine where the thought can be resized to (i.e. right edge cannot be dragged left of max_x and similar for max_y) min_{x,y} Same for {left, top} points 3.2.4.1. Children ----------------- Each child node is another point to draw. It is assumed (under normal circumstances) that each point is connected with a straight line. The coords give the canvas coordinates of the point. The "type" can be of (currently) 3 types: 0: Continue Draw a line from the previous point to this one 1: End End of a line segment 2: Begin Move from the previous point to this one without drawing 3.3 Examples ------------ An example file might look like: \ ijklm\ pij\ jjjj Or, in more human-readable format: i jkl m p i j jjjj Here, Thought 0 (first thought in list) is the "primary root" (i.e. main thought) with the contents "i" - same as the title of the map (as expected). Thought 4 (content "p") is the current root. All future thoughts will automagically link to that one until current_root is changed. Thought 8 (content 'jjjj') is currently being edited. All the links have a strength of 2. 4. Conclusion ------------- That's it. If there's anything unclear about this document, or something could be better explained, please let me know and I'll try and clarify. I normally respond to email quite quickly on Don@Scorgie.org. If you do implement importing of Labyrinth maps, please let me know and I'll add a nice link on the Labyrinth homepage. If you want Labyrinth to import maps from you're app, again let me know and I'll look into it. If you have a sample map, that'd be great. If you have the specs for the file format, even better :) Don labyrinth-0.6/doc/Makefile.am000066400000000000000000000000421204476542500161610ustar00rootroot00000000000000EXTRA_DIST = TheFuture FileFormat labyrinth-0.6/doc/TheFuture000066400000000000000000000153471204476542500160010ustar00rootroot00000000000000Labyrinth - Future Work --------- I'm following the "cairo" model here. Basically, the new version will be released when the "Required Features" are in place, in a usable form. Any "Desired Features" are a plus. New "Required" and "Desired" features are made very near release of previous version. Version 1.0 ----------- Due to popular demand and also to show where Labyrinth is heading, I will devote a few paragraphs to what is required for a 1.0 release to be made. The release series up to this point are part of the "Out of Nothing" series. These goals are (currently) in no particular order. Once I've got everything written down, I may rearrange them a little. The 3 main thought types are now available. Other thoughts are welcome, but only the 3 current ones are required for a 1.0 release. Those marked with a double star are planned for the next release (or at least started in the next release). Those with a tick (✓) have already been implemented. General: -------- ✓* New, better, shinier icon * Import from (at least) kdissert and freemind ** Export to (at least) png and XML format (include images in tarball style?) - Partly working (rudimentary png export) ** Printing support for maps - includes ps export * UI review. Better interface. HIG compliance * Documentation * Full i18n support * Theme support * "A11y" view - treeview of thoughts and links ✓* Selection of multiple thoughts * "Background"ing of areas. Add a coloured background around different areas of maps ✓* Extended text for all thoughts * Set icons on thoughts ** Hide / show thoughts ✓* Infinite canvas * Move and group multiple thoughts - Partly completed. Moving multiple thoughts works. Grouping is covered by "Background"ing option above * More clear primary thought / current root * Thought background colour changing * Popup menus everywhere * Keyboard navigation of thoughts * Autoadd new thoughts (Possibly) * Selection of links - allow intuitive deletion / editing of links - Link colours Text Thoughts: -------------- ✓** Selection of chunks of text * Different font sizes * Different font colours * Different fonts * Default to using current theme fonts ✓* Copy text to clipboard / paste text from clipboard Image Thoughts: --------------- * Ability to change images Drawing Thoughts: ----------------- ** Eraser mode - Partly. Using shift when drawing * Different pen widths * Different colours Possible goals. Not actually required, but if someone wants to do them... --------------- If these aren't done when the above are all implemented, they won't be in 1.0 release. * Different thought types. Draw outline of thoughts in different styles ✓- Abstract out drawing logic (hey, its pretty similar always anyway) * Export to kdissert / freemind / ... * Import from ... Current Goals (v0.4) ------------- Revised: Required Features: * Keyboard navigation of thoughts ✓* Populate and enable bold / italics / underline ✓* Infinite scroll canvas ✓* Cleanup TextBufferMarkup * Integrate Windows build * Integrate html export * Integrate ps export / printing support Possible: * Beginnings of N800 support Old requirements (probably obsolete): Required Features: * Printing support (ps export) * Integration of changes required for Windows build * Theme support ✓* Populate and enable bottom toolbar * Popup menus * a11y view ✓* Infinite scrollable canvas Desired Features: * Hiding / Showing Thoughts * Colourful thought Other (non-feature) Work: * Single instance support (find current running instances) ✓* Cleanup TextBufferMarkup.py * DTD for file format * Add proper declarations to save files * Add mime type handler V0.3 Goals ---------- Required Features: General ✓* Exporting of maps to png ✗* Exporting of maps to ps (printing) ✓* Select multiple thoughts ✗* Hiding / Showing of thoughts ✓* Extended info on all thoughts ✓ Text Thought ✓* Selection of chunks of text ✓ Drawing Thought ✓* Deletion of selected points Desired Features: ✓* New Toolbar (at bottom of window?) - In drawing mode - Allows selection of pen width, pen colour - In text edit mode - Allows selection of text size / colour - Probably other uses - Not necessarily all implemented though * Make window into infinite-scrollable if desired ✓* Remember maximised state * Import from kdissert (in first instance) * Popup menus in canvas Carried over from 0.2: * Alternate text sizes - Ideally, text should (in the first instance) follow the theme size - Additional text sizes available from a drop-down list * Follow theme - Should check which theme is running and follow the colours defined in it * Colourful thoughts - Should be able to select fg / bg colours for thoughts * Accessibility - Figure out a way to display all the thoughts in a completely accessible way - Use a tree-view? - Figure out how to make thoughts actually add (accessibly) to the map area Added non-feature stuff that needs doing before release: (** = Required in 0.3 / Regression needs fixing. Others *may be* longer term) * Reorganise MainWindow.py constructor. It's pretty messy atm. * Split out common thought creation stuff. Consolidate all thought creation stuff into 1 / 2 functions * Add (dbus?) interface for accessing existing instances * lazy find_thought_at for when mouse moves and we have focus to change the cursor as required ** When beginning editing a thought / creating a new thought the previous one should be deselected ** Cleanup TextBufferMarkup.py somewhat. Strip down to bare essentials * Create a DTD for the file format * Create and register a mime type * Add (proper) declaration to file format ** Split out glade stuff to only load the file once (in utils) ** convert XML save to UTF-8 format ** Make export work in non-native formats Older Versions (overview of pervious versions of this file): v0.1 (The Beginning Stages of...) ---- Version 0.1 of Labyrinth was all about getting a basic working thing. Loading and saving work and not a lot else. v0.2 (Get the Picture?) ---- Required Features: ✓* Beginnings of a "drawing" thought ✓* Icon and menu entry ✓* Beginning of i18n support In Addition: ✓* ImageThought. To add images from file. To infinity and beyond ---------------------- Some ideas for later versions. These are planned for some point, just not right now. * Export - Export maps as png / pdf / print / XML - Allow import as well (from XML) * Different thought types - "Elegant" (only 2 sides have thin border), "Jazzy" (huge great spikes out of it), cloud (fluffy) etc. > I know what they look like in my head and thats enough for me * Grouping of thoughts - Select multiple thoughts (Started in 0.3?) - Place a coloured background behind them * More intuitive controls * More crack!!!! labyrinth-0.6/help/000077500000000000000000000000001204476542500143145ustar00rootroot00000000000000labyrinth-0.6/help/C/000077500000000000000000000000001204476542500144765ustar00rootroot00000000000000labyrinth-0.6/help/C/figures/000077500000000000000000000000001204476542500161425ustar00rootroot00000000000000labyrinth-0.6/help/C/figures/lab_alignment.png000066400000000000000000000155071204476542500214540ustar00rootroot00000000000000PNG  IHDR.sRGBbKGD pHYs  tIME.kmIDATxy\T?0  0,FפrKͲ^0[55n%K˲LZyKp K" \ 30x<9{,g<$@0eV .a"d",//GFFYM1#R>| s'& "5LG:y.]1cưeWǸ}@~C/*є5`ɰw 6 Y$M WW1\\wہ:6p8L=|?@xx]/m[/XV[~F˺+ƦQnw_~ vZ̓d_‰˖-cQJ||.e=Nԩy%7^:il ^yrs2C?&>J{>.4q -OcO7܉=6`ЙmYe2tur\Q.cn`7:ɭw , PVk voz*nܸaS~opp#x>a=}baL|>>>rP(P*P*5Zw.F'@gXq%=.e.g rt}㊰d{v+w^KFoAUbvD"u~zM?\nvA]Vgmef Mh0pܘ Ce5p`"d02L &BD`02/^~Ga5p򐞞jalN.FNi}eff-Ԡnb:Si5Xyk? M#I-|o ~f"[$uv*mc LJT9G)<"m&_ '7A@2"cƶQHLJHB^""EGGS,A[Ε<;^m [\}4^v;Yj$}ݺu`T*䀣E5P.'W߆/|3eDDTsrN7=}Et0?zˊ뉈ԘV\}g*B>::lg[r]83h4&iŦ| ;(g@u8@G_]ZJ|N xNF/ 6wB^N<.\mCmB>aƉV}o$+yPGk(mvtmca;:=%( ?}֘fK?8 0,{ FTt4>cM~?/q2#4$/ho{`sw}B"`0_5 * k׮ENNN9lU|1 =t.RlJx7MV!7U%I:ӟ"СC+a}*Bs߿]f0&Bdtd5`"d02L &BD`XYųj1v𸻻32:.¨(<2jqD"D"9rJT*EDD<==ADtpqq˗Y2;1Ö=^`$''cǎXr%t:] dpp/[&cge&Bﬠu[2s+pVmRr+B[_DHw|\O,ؑ9q\&>=Aog??f_>Y.f_ľE.xLF̳qoLScEh8}Ԇq߻q~GU>0Njx.Ԋ_m+UX@OQyԗϞ <)aq>W~o? ipXK5+> /u`7qfH^n}и;;~Ax㧆7G\߷_cP!Dž Z”-ҥKQQqw?? п]t4I YwySGG dy>||K=1 )uNWQTo_ej3lzGDȕڕ#%żOO3+cBSj5JJJVQQQi/1 36E$gϞشi1GTXL@"`׮]]3;f0L !,8odSjߕ Bv34pޮSޯM\Dr6YF׈PU[~ӡj!˱g5iYF[Eؾ K?jط? lɰ{KXSU4Ny&:Θ|ِ􇳀J90ٗ{u7-@Y=wVލ '`ϩR]mU,Ҷz^1]1!/OBo>N]Y=Ǹmh fzN֚7/&_KpV "tټjN6?p,g9ǑR򃄫DZؙX/lJa3E~㱹\" +e8]#t}@G"JpzZך/nbz<,#X _/kc@! 0o\[|_omv ςZ.x;a0PSSVkd`dW#^[-&8+0=Pj$/#zdd?Y0dXz~= Zv-io\[|_orH<2j&ya.4MݥQt<''ypxAܻK0#P_ÿXo ]Էr;ܛ} 5wZq^wcS.!D ;6XKTPﶁ'u]b2&@n㬅btDȸo00]&“ǎ`8N3ybʔ)&!99xL FExu9&4 0//ۚQ.c„ j"--͘uVZet5 4|_[ 5@a9P RX2:;&U W1]8kj]{sl޾5eҥF2/E\ g^[եuiYW4YZ=uo˖-밍0zMl>z/dx>HRRBAAy?FOLF'LFQ#Qp4>233M#v5uMLgj5Cn+oQipD4=8E͢a/4[ls̥1PHX=3~י~S3$/09a$H&@"ɞ9LNH&QdX""EGGS,A[Ε[&"y=ij_͎p "*?Q i}πٷw/˖.,^`לtنömLӁez#qOa|QE__TL5'gFч>ʝ57 ,2r3X3f0lB)PB{vaJKZyj]e,^8hbM +:c½}TtwL3MC~~9lCrR2M+صsg\9߸ 6pC]QA)6 D}YCX9Eǖ۶n"CqQ199ضEZ y!.IfYT`bbUZ-C-/++g%8N : Wr)szoÇYa$Шh* D߰Yѭppfa69_;ZnG~Ǐk瓷C`{x;wcx!llX_aO#ydphq:ik"8\ue)ST_sF8)LC9}THh1 RJK{R`:Θ ^։"ӧ>z@m4oE脿Zoo\k߼~T4/]ş{֋{9E\䯚ynA*p3li&^xڳs)~͕_f_=0GPjg_k(G9eNV7p\21])0|r]ywN=J M8y;wa5W .yݠ5q*jٲe+dbL٫_O*2a쑚:Җ}K.8ŸC-n+mlL?Bf{-8cY,b'4>Cv\Wײ,'T#AjiÙ#ZbV3]ep=*ͷyӦD"4[y3ⶍΩ d E5p۞a%A_yqeTՇ;X\iB3/oڄvoӵܸ9'?/^ 瑗G@˩JB}8֭_?᝿wSXvMŨ0t%%Nk=Pd"eZEfjhF\F+4~{/}n-_sosKMݼ?~Ix<й,Yo gpc%˯T1;r{y֗f]o夵+?ۮ`~t`SOҙG)5W_yL&Қ5Ʋ"(4zf͚hw.w;D$/fߑ%4H |۹W =ڟ}$gɦ76axg1/ײ΋ģq׫2U%To{[+P_N0Wç?a}u+ >8ˋ>]W9 E{`ۛo=:rJp8< dJz}KISz7"N +{z}9)\LC>j.1 3Qh9S{_^$zA׽L ?=8 {ob?mqM}9̽?FDh,]V/,]q*.#hb8ɕQK֭?mJqDMouo0gĻJ}wkn NYX3G8‘gBGx  aD{f"7rD(¤zܭaEF&*A Sq׍w7S=&Nw}*RIc?Q/,D ;uKl{Y6IԸ 0(+CUhq 0>=p;;ulj[oT|ν|tA8knjwfǖsOS R:arK ~4b͑ަǞ n:'w/>t84facfz2+dד)a 45D~nevo6Lͧ-Efwg٤)87ޡ.LAZͥek4.ue1w!* \` \3vzvqft7 |;Θ?18WWh-!9G>$9=1RYye4<'~Ld9p+mOr뷪 fWi@]mA#|p-pWp̸\A`e?O޳ v1EW 3K怒L%\) ދ\AD dA8qERrGQ3gcUk?"&¨:MdZH 0jysƂ L*"2  "# "# '@@C5GijjNxpdl"-RäZdf0 DiXV>$9k'mm8ldeeJL@(DFM8)nSRRp:9J͑ÆNAA/DmTTV` q8*ZIMM"(..&sIKK)"3> `v%ZA6LՀ:H[5"0@VZwgbE1 EdjG)Px ;>Bd**()Y& bYazzzhmm?@ww>‚к:Hjj*n}Vf)R#Ed#2vDD}G$}L #TY%h߷w h{jeY&`0Իm\.'990M4iЀtEffPW]$"3A"cC"T;&z*Ž$4la_m0T+OLCZjۿ[h1Mt~Zkn7J)IJbYPۍa}>`Pj+uoQPDp{~8Ӝ mXMutȕtŴ!99F2IJJm;x^XR`0HWWe0MiJm> FDaS1E7́;V(euԗ(4#s\ݍDy-lmBZ[[˕("31%S@h֑+2@әm{vhvȤ^x5ǔ$;;Q{7 &xjTE$5s:޸ggS[[Çq\Ҏ ]mքB!^/PHjɘAd9@bhݍQ|-呂鞱 B iשԖ5p¸cq2'"P8&>˲zz@JJ Zk|REd&d(#fihafP[w᜾S0T.Om5,b׮Q[[W]ϛ5R tvArr2ᰅp81 #)s|QF")U&T44m#ƒ1̙TV̙`Jghmm=ZkJX^^^N^^ضeT-XmiXѣuS&~Jc57%%שFD r  CQA#eCo^bP(LPѴhZX@:Ze`:Q=3GGضqzn(  ͟/"=tX"ӉiЈȌO&^`z?1W(AEҫ+R+QcBtؠNį˲1H0l"N{`xq8&"2F9шȌOf(|8wX74tlޫyPlYLdJ}@zmpBb'pCa 4MLӁh̸ыyK[cciɘ ֽWXBbDa`Y6k:ڿT1u9}:.@$,ˊ))pm[1 چICC=۶' ˊtڶݻlHCPL݊gaդG]m{>,\.'eݍt80 $NfLA23ҩϼin8TQL .#STT@uu-혦oׄhh0MM}}=Rx<)[ CaN<ihh񐒒Gҩ ==2B[&`p(!#= ۅaJǯhnn ٸ}fwPaq䢹)9r9pqERRҔl*\R˅aIGG'.a8].2IH4L+"'#"337w6qw8dggNJ)RSSY(jJQʘWv"| Cp8xXoL SeD`Ddsuw1cmHߌT(a!Y0F&*=$K93ygSM~lR:Z 4&:+i;&*v!w<L ]y5\mqn',/>0[zoKEnV}_9LO9Yx)ZreL h>'1x/=OУ!B{¥cui+%@fڃ[UƛGf =Ktj4&JӏfHL-to~=>Fk+t|'C18{hj*s+9ZLKhRn\hƂs/a~r|^tӬ/JI=wNGn,ma 3Jq.6cl:~LReL\O{=U̪MXOrZ#|Wqm*92QGiL#g(YGxʽr1fu`9șM<< Y5km_[ȬSO!ꠁ2:!P4gFFrmd^@%;E/L|꫗n1m(4C&(3 \B[>|u#V#¸ۼL!- eVK{w=~NV*93H_K d4С6ښj kĕRHFz:N壧H$r ĦH-&JEgUSh/EdA\ LAADFADFADdAFː#~VI0*3r)<6/9'(9D`?)y'ˆlC>A&ADdAI`eEIFEDFq2 0VM5Lkp׮᪫1qSǽ_ӱfrMo+t›:`5/(o s-+81؜bSͧO!4sNoҟ<̳<̳c^?嘬:]wDgGh13?:sVLf'wlitxMV1|?8Wٕigyپܕ|櫗rFsc0yu껴9 YXY$.mF/ϯ`irE&Th?As%Bo#?m!HNm⛑p 0+أ<|ďYE6սC#]\6rwվ9wIDAT7Ek0NQȆpٍtRr:)?{~ʏOHuLuTe^wGbŌ5dWsw0RZǩ^z?v./OoV> Əw>q`&>?;.g~,.Õф? W෿G{GdfhOQ蟸grΙsIs+R:wQ<,Gjz3s?E(s t+(YE^# XLH9^ ʇu:q,u|PBG)k眯̋ (xc'u3(X̗[҆ٚfk/*A֒m[8S(Ks#΅5:#iF7 T:60 &4gR|i,ܿ~?vW? _YGDԁAуɘ&'"\uL[OLwa8=^ʟ_?^3E]JH!:mSqF4{r+5!-x?/0MIʇ5|*˨ICcGhě Cg!rJ%N*^H]޲H9w,/ʗىJ8oNaP[gV|a9֒efLo;qF-L+Lr@UC4V#{jLͺ.e38s[:~Gt9^z!}Ώx-r)&@&_=Ϳ>dƺU&̪ ryL?N[q`e)jkJfLCs·.$A8YK]w, dA8~NƲ,!aJ!e$P0 9$L r`vɈ +2AA&C"2 LȔ|CrH/MC #:Q¾ߖoo{$} t?aPrӿGu0}QdFkAx:q8A NFq2dA'#8AɈA dA'#NFq2 A'#8AɈA dA'#NFq2 A8A NFA dA'#NFq2 A8A NFq2dA'#8AɈA dA NFq2dA'#8AɈA dA'#NFq2 A'#8AɈA dA'#NFq2 A8A NFA dA'#9)8A NF dA'#8q2 A d NFq2 dA'#8q2 A d NFq2 '#8A A d NFq2 '#8A NF dA'#8q2 A 8A NF dA'#8q2 ' H[;{4NF]m6Fx|naDyVEh@(_iGAPJ6(9CI0j(遱m4PJHNI"ZP%A5JQâ$.dW.V:iBI pRC(СLñziz|~>j߾}PIJJJ7o.)c imoriMC߿_ayk9DgG;њNaA!JJ&…HKK4M?=IENDB`labyrinth-0.6/help/C/figures/lab_map_start.png000066400000000000000000000375421204476542500214730ustar00rootroot00000000000000PNG  IHDRnsRGBbKGD pHYs  tIME "(. IDATxy|uGݦ}rCT 偂*"x XV(B[Zhӻw&Msgٙ$MMghvwv糟yg>Yò,qJKK Xcpq0 RRR7n"230M#;7㙧% qƓF-"rtUWWvm6ˮfD(&MfTUS[[eYjqV妦+WpM5eػ aԙWLmm5mDDemtuq E0@YO>Y'BEE9`a®hldqǟpb\L"ҳ;lì[x}0ݘAJj*k֬]UYA>_cWk]H-k2q8f͚Q+V~ S=13٩wlDXPUrONV]BbR"I_;)Sʕ oN^x] CNN{oemk:nѩ0r(V#KEC{ C;0k mNj0nwj;w4N20y۱c3f~40uyJ#c_b?%Lf'̧/ͳŧoɸ92lyセ>ê㋽Yr 6>s?7wI{"G{) z=L88̚5ɱDY ;ҥ(Z ryZiZlpMٵsi/ҹ'2_BHL˩`)Ōc){?dÆLJգ9yةWːQ([&U˘28 Q,]UJ)@/V> '6_㉄ yr͈0'H%}v{?a+V| ̚9 ltRVӦv7es,-ù1ȍi{`" n8Q%,z~L?qPi~EnF-B&0ؔBHqp!>1?]_dM=`Ux h'ڟqmgci,n }qIC햁mbla }ܱi_:B!9Sg3:*-̤`*r~*?_MAr'uoy~eÀ'7,^8א8﹎;b|92U}0k0udf͚Y6iqfb0~B&;kF}v 零*ϫ1y˯8)}>erGcZ`t/?n-Ռh>\{9w;:AXw7ɸvlT̙3v$=K2{85J-yyp7M>T`7?8'p)>~'BOoĀd12|?ENwyc-߿رra՝xcߨ@'>ĥ0ݶD"6`+8(C[&Y|93g̨/FF^IWQEپ};uuuo#xC e谡8gpOaD&~nVcR8rtyk3Fqizox<05 ! lrV֟񢢵06[܍-&L8o..K /?zژgn%O4m<` >Ho;~kIw5AM,2e? $_oO76k9k찈v88hu4'LllQx'$|o Y N8 ]n/&NsǛv4mh{xcK@φ xݷM^k0tΛs9pllѯeia`&&%%yY""4DDW~]DD-n?*=,}SgCxgqk~ѳ~"dǧrTj>χ=u.Y2k.w%VDӷ~砮ӝ&qb_́s &v~w} 721Oɴop96԰@ۻndbᏤq?ӳ᪉mxӸ9׍X= Cve'Y>ńV1kf ù|6}/f1;;eϡVϿp-Kɢe+"]URzojbB|kH*,ln9^Jr8a&2w]-iL>{8 _1cYn ?{)f'!yIod7~P9Srv2#.$I?do(^֔p#H>ū:,کϮZ"M]%kȅw̩Yf'q]%: 3;,sC0ZY!3VDoUr[k5}oOSyU&P6;6?:<[԰wluDJ 98ܱ0HB .j&YS]lE=7oʹlvuP(9^_W<po^=Яٲt|="1Z4=="LpRDWA!"tepڢ9N\pOujMD(k:vѾn bY!nwtr{xEcF;&e붭X%vkhaڴ 67 " {:m?ZݦiRWS%=gٜ""e>DegKJOx7Pp*f߾}̜/!41//}{b#"r9KvۺGZc&!z=h2nU(ZS0~$7!غe5'zŻ{*_VNmDe2duk%ߕ$|8VpBa짼ٯGL>D_ILos|tp?ruhH$}<**hEEVv>c '3#p(t)+?[>mYTyVA*+闓sԷ=ՏTmG#RX8aCG2D"jjī׭ ٶb؜:2Q=^v{2l4ʡ" H%# ٴy3/\gvYkO1AuM aˢ_f6 :2,ql;k:mcn_ƍ(Z#vZWҿ^g·Iz3p{Cee%i~[>fqLs:8DlW|#W,zocO%9#-@/~1AuCvY29{v[=|hh*^ZmcXc:Hc1|ؠ4v*+1 ~150 Poo-ϜٶsiᅔWVq6Fo[lj~'9̳f!l^_4yc2M UI?Li@P+S Xb+7MGfĀ+eFdɒbv[E{artyyZ_m*+*ILJ&%5 ێ`nLӤq%a]ٶCuM5@n:Q]Uɮ=սc(ߒcsWn9qplߍߪS'O:RSCxHLJ"!! PP"lEpH^c!v׆"<fw3xQ'mپc7r SA,Ca2Umۀ=6 ؾcw܂D0b?Htyy PQQAFF$숅DmGD"uObbI]UVUQ^QAZjYnLE8±ZRRSq{SL^n. ^K;8 +jCé_{E//yjkj{ q )v`̘qX0۶o#  YCa9g }u_q d7wQ'?q$Bauo5m,khZoa[1*-YӚ,OSeQY^NfvPd52LSHJNUUUu;8p0a+ DT?D (.E^n Qp;Zo9 ]/B ʿ^716H4U1 gO 5ռ"OޒRB0pP( }z쫳zZ?ٙi0 >XiB࡛N|ѷ)Ɓ #54لH\0n~M7ub/W0!>:ɉ쯬&5Cem |7o66 a@ye ɉVf˲Ӛt('=#p8Ǔ@YY)axx$ A>:RpRLUU iXe [aD BYY)ЎGp;N톯tUwڮ/̷ p8i̚1/—D(Sa ul/vwISl޺Y'L"%%@OB`0כ@(d5mQ'2)-ǀTﮡ ;Ay)\.Ykg,XM$bS/}%;-q&i`FzӖԴ4jjk8PFzf!-#;` @rJ pˊ2e$'r@P 2QS())ӯR9n]%&we\qŕkfY@wڛG]j8a'9[Y]/nŽFjٿyu :k7d~x])\s͵O?EuMuÁXoENJJ&q{I(<[uxH U8y0MLe6dݴFwKyL zm]Y$7(/OfVv}? ۍ륢+|H|xÖ!  ?ÈdIIdef(⎞Hcܱ0h8Z];(Gt9K>v}?jb;?/ՑVm-ñ,\V-R6Eogx< à_o~ywԓh-oQ'am]m`Aoaƍ1EO*1 C3w0#-]#<47:Lӌ6v"vP0 JEjvDpDl;nc/a q߻tSӔqn[[6TH itl=l'*ɗ^.r%2Z*W >/ǃ;翼Cӵ6'>m/\ĤTf aj0`PnC Rq\88X400`>6o,✳gw[y b #zmtKy%aTUT4v0o4 "|~3p{ -,"m`۶1M'%˿7&Mļ/+_{g)OSrmdˮԴ4l_k@ ePBpèiwOuIp`k) -(1ӕ8l"-5@({'Dak_!  [v}߹4c]&ǂ5|P ˶8}@ wxiGTa2]xfu/,Ν yޢɡ=gι _8ǣHO2>.遡}$ϋ&("(EDz.989`xլ{EDu n(EDD-"(ED""[DD""Qp[DD"" nQp[DD-"" nQp(EDD-"" n(EDD-"(EDD-"(ED""[DD""Qp[DD"" nQp[DD-"" nQp(EDD-"" n(EDD-"(EDD-"(ED""[DD""Qp[DD"" nQp[DD-"" nQp(EDD-"" n(EDD-"(EDD-"(ED""[DD""Qp[DD"" nQp[DD-"" nQp(EDD-"" n(EDD-"(EDD-"!_ T""ݜњws˜9j tB,7c}89کg?Yw8lvxw$)))̝{j^D|sINN>n*9 9v8c}555̛j]D̛uS}M;nED Xpax9CHGE kwéG2cԨ^F-"(ED""[DD""Qp[DD"" nQp[DD-"" nQp(EDD-"" n(EDD-"(ED""(ED""[DD""Qp[DD"" nQp[DD-"" nQp(EDD-"" n(EDD-"(ED""(ED""[DD""Qp[DD"" nQp[DD-"" nQp(EDD-"" n(EDD-"(ED""(ED""[DD""Qp[DD"" nQp[DD-"" nQp(EDD-"" n(EDD-"(ED""(ED""Fx;רfED[DD"0_pϋ(EzPx+q /3܆-=y^c…̙sn4" nuu mQpWh[w˿E"$E*Qp[DD""U' P툈%~ U@n1qXVǶU!M ۃǓЫ/_ s-Dl ֱm6V}{U%LENN6ӦdaxIoъ1,gO1,y_r10mKy}+g1hp&u=Rá6RdY!-[eK8 U+,g|w}+zCRn[Z(mJKK4x` vR?Ғ}ѫ/[Vx;6n`Z ӈ JE-n(`G"7pԴnmZJE}Lںe5'zŻַQ±Mҝeul9V}SZ}}ܢXas+j%P8b(_=6H*9]g%vhJz^WI{O<ס^~`2ݲ *l#?Kr@ aP(OySNeXz <ԃ ]|6V$BفJ壕0~hN:~II h_{e˖b6a+ӂ;OW$;!-7t̥59q"7?hyv]\صO ( (Bp{l~?UU:2MԴT\.~x+G%-`՚ TTT [6, +V=xA xlݺ⽥<}F|c| ^2U\¤̈{Yx}rsjYTU D"+CݾrѪ$ɤ<}_Mytu\<55ǧr&\CϞu_n6)R[[KYYwb]ty@yEk7q 38p{K9}2y9ͦ{8 ۆ~뺤rl/G|0b1t /'Nۏ> Eyok—}lM[ˎI1̫lfwTOH_GE[>q\&efPӉ:d}urw~z/Snӌ1yw}I[<_ЎKp>{waZ,jsnӵ Wö#S]{777YeYdgecƍIzzלIVUUCn 1yX[8 -COcعٲe')zA,\:$#BǯKﳥ~#SG5`TrP SlPFM=.BA\3"Ğw僸I#u̮=eٴ!a?wI,_@8l1wy̛ .dΜs{Npoڲ_I~ʫkiN 88D8WZKRV^%xM1#1MҲr;]V@0iqƃBp̣FbN=xN=i>m_8sKo>?]Ҥ=e≵h_G3Әx(,LѪ5|YkǑgh3<^|1c*rpmvGG4 ںv\T\hŦOwpIOOe|֟rvn.M]ϋS^Qn9Abb"y9Y s'W^va|{FԔ$o؂kye+OAnv;|A }"he J=y$E6HL᎔ K`3zm/Oδ c7?}8SǖOIJ\v󗙚::M@ L?c5x5 xv\;*(HRZ^J_e9p0"m6m0 ;fD=/B_@6_}p@o\˛f^{};~-bWw3ǥjuZ+@}u;On;U= ji%7 xv\;--˲&&be1wx?x4fN>#NC8Sȯo8IMmN0W-d| ص{'{Ko{q?3N?o;韓d~U J&+][lFL:'%kM4D}4 ~0V޳]VM[a@@ I8LĊ#vxHHHK󑒒LRRR\=HKMK4I $ b-"vǁY3x<$%(%%%hX>/w 8C(jfcca'k󓔔Eug7W_(wgZ臺VI_FI\JbJZZjP^,/YYGMF_1fp~<_2*QJZLS TWUڲ$2c{?푸=n|DR,ۿCu0 ^|vBnh Az@ߜβ:j_q2TWG[EKػw!%%T_ah-oM*FLl!k#dڪN1uW4{\[ݠ#ukYm'Ư+rqplwGlLذR_}ܢm$+#[א iEuM5Y9؎ݫ/[w{9j),AJJjLD(sL7ob̞}6Ũr0%xغuU8G}ED{Arr* Labyrinth"> ]>
&app; Manual V&manrevision; 2008 Matthias Vogelgesang GNOME Documentation Project &legal; Documentation Writer 2 GNOME Documentation Project
doc-writer2@gnome.org
Documentation Writer 1 GNOME Documentation Project
doc-writer1@gnome.org
This manual describes version &appversion; of Labyrinth Feedback To report a bug or make a suggestion regarding the &app; application or this manual, follow the directions in the GNOME Feedback Page.
MY-GNOME-APP mygnomeapp Introduction &app; is a light-weight mind-mapping tool to structure one's thoughts. &app; provides the following features: Export maps as: PDF - Portable Document Format SVG - Scalable Vector Graphics JPEG - Joint Photographic Experts Group PNG - Portable Network Graphics Getting Started To Start &app; You can start &app; in the following ways: Applications menu Choose Office Labyrinth . Command line To start &app; from a command line, type the following command, then press Return: labyrinth When You Start &app; When you start &app;, the following window is displayed.
&app; Start Up Window Shows &app; browser window. Contains titlebar, menubar, toolbar and the map list area. Menubar contains File and Help menus.
The &app; browser window contains the following elements: Menubar. The menus on the menubar contain all of the commands you need to work with files in &app;. Toolbar. The toolbar contains a subset of the commands that you can access from the menubar.
Basic Usage You can use the &app; application to perform the following tasks: To Create a new Map To create a new map, choose File New or click on New from the toolbar. A new empty map window appears: Shows &app; map window. Contains titlebar, menubar, toolbar and the map canvas area. Menubar contains File, Edit, View and Mode menus. To Manipulate the View of the Map You can use the following methods to resize the view of the Map in the &app; window: To enlarge the view, choose View Zoom In . To shrink the view, choose View Zoom Out . To move the map around you have several options: Use the scroll arrows around the white canvas. Hold the middle button of your mouse and move the canvas while still holding the button. To Export a Map To export the map, you can use the following methods: To export the map for further loading, choose File Export Map... . To export the map as an image, choose File Export as Image and use the file dialog to choose the format you would like to save the map and an appropriate file name. At the time of writing you can export the map as PDF, SVG, PNG and JPG. Use a vector format like PDF or SVG for high quality printing purposes and a bitmap format like PNG or JPG for the web. Working with the Map The most common work you will do with &app; are: To Create a Thought In &app; a thought can be: Pure Text An Image A Drawing A Resource like an URL What you are going to create depends on the mode that is activated. The most common mode is the Edit Mode which can be activated by choosing ModeEdit Mode. By clicking anywhere on the white map you create a new thought. You then have to type some text which you can further format for your thought. An image thought is created in Image Mode which can be activated by choosing ModeAdd Image. After creating the thought a dialog pops up asking for the image to load. In Drawing Mode (choose Mode Drawing Mode.) you can freely make some sketches by dragging the mouse over the canvas. A resource thought can be added by choosing Mode Add Resource. If you click somewhere on the map you are asked to enter a URL and can then proceed to edit the thought's text. If you double-click on a created resource thought the URL is loaded in a webbrowser. To Manipulate Thoughts Selecting a thought for moving or alignment can be done by: Clicking on individual thoughts Shift-Clicking to select more than one thought Using a selection box by holding the left mouse button and dragging the mouse while holding that button. Selected thoughts can be moved around by left-dragging them with the mouse and formatted all at once.. Working with Links Links are created automatically between a selected parent thought and a newly created thought. If there is no thought selected, a connection is made between the last selected - as a last resort the root - and the new thought. You can create new links between existing thoughts by choosing EditLink Thoughts or pressing CtrlL. A link can be strengthened or weakened by selecting it with the left mouse button and using + respectively -. The strength of a link is visualised by the thickness of the line. A link with a strength of zero is automatically deleted. You can customize the look of the links by choosing either ViewUse Curves for curved links or ViewUse Lines for straight lined links. Format a Thought's Text A text and a resource thought can be formatted by using the tools of the lower format toolbar. For editing a thoughts text either: Double-Click on a text thought Use context menu Edit Text You can then mark text by: Double-Click on text to select all Press CtrlA to select all Drag the mouse to select parts of the text Now you are able to format the selected text just like in a word processor. You can use the tools in the lower toolbar to change: characters to bold letters characters to italized letters characters to underlined letter the font of the letters the letter's color the background's color Align Thoughts In order to organize your maps you can align the selected thoughts on your map by using the alignment tools in the lower toolbar: Shows &app; alignment window containing tools for aligning vertically, horizontally and all four edges. All thoughts are aligned to the first selected thought. About &app; &app; was written by Don Scorgio, Martin Schaaf and Matthias Vogelgesang. To find more information about &app;, please visit the Labyrinth Web page. To report a bug or make a suggestion regarding this application or this manual, follow the directions in this document. This program is distributed 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. A copy of this license can be found at this link, or in the file COPYING included with the source code of this program.
labyrinth-0.6/help/C/legal.xml000066400000000000000000000071301204476542500163050ustar00rootroot00000000000000 Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License (GFDL), Version 1.1 or any later version published by the Free Software Foundation with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. You can find a copy of the GFDL at this link or in the file COPYING-DOCS distributed with this manual. This manual is part of a collection of GNOME manuals distributed under the GFDL. If you want to distribute this manual separately from the collection, you can do so by adding a copy of the license to the manual, as described in section 6 of the license. Many of the names used by companies to distinguish their products and services are claimed as trademarks. Where those names appear in any GNOME documentation, and the members of the GNOME Documentation Project are made aware of those trademarks, then the names are in capital letters or initial capital letters. DOCUMENT AND MODIFIED VERSIONS OF THE DOCUMENT ARE PROVIDED UNDER THE TERMS OF THE GNU FREE DOCUMENTATION LICENSE WITH THE FURTHER UNDERSTANDING THAT: DOCUMENT IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES THAT THE DOCUMENT OR MODIFIED VERSION OF THE DOCUMENT IS FREE OF DEFECTS MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY, ACCURACY, AND PERFORMANCE OF THE DOCUMENT OR MODIFIED VERSION OF THE DOCUMENT IS WITH YOU. SHOULD ANY DOCUMENT OR MODIFIED VERSION PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE INITIAL WRITER, AUTHOR OR ANY CONTRIBUTOR) ASSUME THE COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY DOCUMENT OR MODIFIED VERSION OF THE DOCUMENT IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER; AND UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER IN TORT (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL THE AUTHOR, INITIAL WRITER, ANY CONTRIBUTOR, OR ANY DISTRIBUTOR OF THE DOCUMENT OR MODIFIED VERSION OF THE DOCUMENT, OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER DAMAGES OR LOSSES ARISING OUT OF OR RELATING TO USE OF THE DOCUMENT AND MODIFIED VERSIONS OF THE DOCUMENT, EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. labyrinth-0.6/help/ChangeLog000066400000000000000000000000001204476542500160540ustar00rootroot00000000000000labyrinth-0.6/help/Makefile.am000066400000000000000000000002151204476542500163460ustar00rootroot00000000000000include $(top_srcdir)/gnome-doc-utils.make DOC_LINGUAS = de DOC_MODULE = labyrinth DOC_ENTITIES = \ legal.xml dist-hook: doc-dist-hook labyrinth-0.6/help/de/000077500000000000000000000000001204476542500147045ustar00rootroot00000000000000labyrinth-0.6/help/de/de.po000066400000000000000000000275651204476542500156530ustar00rootroot00000000000000# msgid "" msgstr "" "Project-Id-Version: Labyrinth 0.5\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2008-05-12 00:12+0200\n" "PO-Revision-Date: 2008-05-12 00:17+0200\n" "Last-Translator: Matthias Vogelgesang \n" "Language-Team: Project-Id-Version: gtranslator 1.1.5" "Report-Msgid-Bugs-To: " "POT-Creation-Date: 2004-08-31 20:57+0200" "PO-Revision-Date: 2004-08-31 20:58+0200" "Last-Translator: Hendrik Brandt " "Language-Team: German " "MIME-Version: 1.0" "Content-Type: text/plain; charset=UTF-8" "Content-Transfer-Encoding: 8bit" "Plural-Forms: nplurals=2; plural=(n != 1); " "Language-Team: German " "MIME-Version: 1.0" "Content-Type: text/plain; charset=UTF-8" "Content-Transfer-Encoding: 8bit" "Plural-Forms: nplurals=2; plural=(n != 1);>\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit" #. When image changes, this message will be marked fuzzy or untranslated for you. #. It doesn't matter what you translate it to: it's not used at all. #: labyrinth.xml:206(None) msgid "@@image: 'figures/myapp_start_window.png'; md5=THIS FILE DOESN'T EXIST" msgstr "" #: labyrinth.xml:22(title) msgid "Labyrinth Manual V1.0" msgstr "Labyrinth Manual V1.0" #: labyrinth.xml:25(year) msgid "2008" msgstr "2008" #: labyrinth.xml:26(holder) msgid "Matthias Vogelgesang" msgstr "Matthias Vogelgesang" #: labyrinth.xml:40(publishername) labyrinth.xml:53(orgname) labyrinth.xml:61(orgname) labyrinth.xml:103(para) labyrinth.xml:113(para) msgid "GNOME Documentation Project" msgstr "" #: labyrinth.xml:50(firstname) labyrinth.xml:58(firstname) msgid "Documentation" msgstr "Dokumentation" #: labyrinth.xml:51(surname) msgid "Writer 2" msgstr "" #: labyrinth.xml:54(email) msgid "doc-writer2@gnome.org" msgstr "" #: labyrinth.xml:59(surname) msgid "Writer 1" msgstr "" #: labyrinth.xml:62(email) msgid "doc-writer1@gnome.org" msgstr "" #: labyrinth.xml:97(revnumber) msgid "Labyrinth Manual V1.0" msgstr "Labyrinth Manual V1.0" #: labyrinth.xml:100(para) msgid "Documentation Writer 2 docwriter2@gnome.org" msgstr "" #: labyrinth.xml:107(revnumber) msgid "Full title of previous manual." msgstr "" #: labyrinth.xml:108(date) msgid "Release date of previous manual." msgstr "" #: labyrinth.xml:110(para) msgid "Documentation Writer 1 docwriter1@gnome.org" msgstr "" #: labyrinth.xml:118(releaseinfo) msgid "This manual describes version 0.5.0 of Labyrinth" msgstr "Dieses Manual beschreibt Labyrinth Version 0.5.0" #: labyrinth.xml:121(title) msgid "Feedback" msgstr "" #: labyrinth.xml:122(para) msgid "To report a bug or make a suggestion regarding the Labyrinth application or this manual, follow the directions in the GNOME Feedback Page." msgstr "" #: labyrinth.xml:131(primary) msgid "MY-GNOME-APP" msgstr "" #: labyrinth.xml:134(primary) msgid "mygnomeapp" msgstr "" #: labyrinth.xml:140(title) msgid "Introduction" msgstr "" #: labyrinth.xml:141(para) msgid "Labyrinth is a light-weight mind-mapping tool to structure one's thoughts. Labyrinth provides the following features:" msgstr "" #: labyrinth.xml:145(para) msgid "Export maps as:" msgstr "Exportiert Maps als:" #: labyrinth.xml:148(para) msgid "PDF - Portable Document Format" msgstr "PDF - Portable Document Format" #: labyrinth.xml:151(para) msgid "SVG - Scalable Vector Graphics" msgstr "SVG - Scalable Vector Graphics" #: labyrinth.xml:154(para) msgid "JPEG - Joint Photographic Experts Group" msgstr "JPEG - Joint Photographic Experts Group" #: labyrinth.xml:157(para) msgid "PNG - Portable Network Graphics" msgstr "PNG - Portable Network Graphics" #: labyrinth.xml:166(title) msgid "Getting Started" msgstr "" #: labyrinth.xml:169(title) msgid "To Start Labyrinth" msgstr "Labyrinth starten" #: labyrinth.xml:170(para) msgid "You can start Labyrinth in the following ways:" msgstr "" #: labyrinth.xml:174(term) msgid "Applications menu" msgstr "" #: labyrinth.xml:176(para) msgid "Choose OfficeLabyrinth." msgstr "" #: labyrinth.xml:184(term) msgid "Command line" msgstr "" #: labyrinth.xml:186(para) msgid "To start Labyrinth from a command line, type the following command, then press Return:" msgstr "" #: labyrinth.xml:189(command) msgid "labyrinth" msgstr "" #: labyrinth.xml:197(title) msgid "When You Start Labyrinth" msgstr "" #: labyrinth.xml:198(para) msgid "When you start Labyrinth, the following window is displayed." msgstr "" #: labyrinth.xml:202(title) msgid "Labyrinth Start Up Window" msgstr "" #: labyrinth.xml:215(phrase) msgid "Shows Labyrinth main window. Contains titlebar, menubar, toolbar, display area, and scrollbars. Menubar contains File, View, Settings, and Help menus." msgstr "" #. for example, the items on the menubar and on the toolbar. This section is optional. #: labyrinth.xml:226(para) msgid "The Labyrinth browser window contains the following elements:" msgstr "" #: labyrinth.xml:230(term) msgid "Menubar." msgstr "" #: labyrinth.xml:232(para) msgid "The menus on the menubar contain all of the commands you need to work with files in Labyrinth." msgstr "" #: labyrinth.xml:237(term) msgid "Toolbar." msgstr "" #: labyrinth.xml:239(para) msgid "The toolbar contains a subset of the commands that you can access from the menubar." msgstr "" #: labyrinth.xml:249(title) msgid "Usage" msgstr "" #: labyrinth.xml:250(para) msgid "You can use the Labyrinth application to perform the following tasks: " msgstr "" #: labyrinth.xml:272(title) msgid "To Open an Image" msgstr "" #: labyrinth.xml:273(para) msgid "To open an image, choose FileOpen Image. The Open Image dialog is displayed. Select the file that you want to open, then click OK. To open another image in a new window, choose FileCreate New Window. Choose FileOpen Image to select the file that you want to open. You can also drag an image from another application such as a file manager to the Labyrinth window. If the Labyrinth window is empty, the application displays the image in the window. If the window is not empty, the application starts a new window to display the file. The application displays the name of the image file and the size of the image in pixels in the titlebar of the window." msgstr "" #: labyrinth.xml:297(para) msgid "If you try to open an image file format that Labyrinth does not recognize, the application displays an error message." msgstr "" #: labyrinth.xml:303(para) msgid "This is a caution." msgstr "" #: labyrinth.xml:308(title) msgid "To Manipulate the View of an Image" msgstr "" #: labyrinth.xml:309(para) msgid "You can use the following methods to resize the view of an image in the Labyrinth window:" msgstr "" #: labyrinth.xml:313(para) msgid "To enlarge the view of an image, choose ViewZoom In." msgstr "" #: labyrinth.xml:320(para) msgid "To shrink the view of an image, choose ViewZoom Out." msgstr "" #: labyrinth.xml:327(para) msgid "To view the image at its actual size, choose ViewZoom 1:1." msgstr "" #: labyrinth.xml:334(para) msgid "To enlarge or shrink the view of an image so that the image fits the Labyrinth window, choose ViewFit to Window." msgstr "" #: labyrinth.xml:342(para) msgid "To enlarge or shrink the image to a specific zoom factor, choose ViewZoom factor, then choose the appropriate zoom factor from the drop-down list." msgstr "" #: labyrinth.xml:351(para) msgid "To display the image in full screen mode, choose ViewFull Screen. Full screen mode displays the image in a window that fills the full screen. The window does not contain a window frame, titlebar, menubar, or toolbar. To exit from this mode, press the Esc key or CtrlW." msgstr "" #: labyrinth.xml:368(para) msgid "This is a tip." msgstr "" #: labyrinth.xml:373(title) msgid "To Scroll an Image" msgstr "" #: labyrinth.xml:374(para) msgid "To scroll around an image that is larger than the image window or full screen window, you can use the following methods:" msgstr "" #: labyrinth.xml:378(para) msgid "Use the arrow keys on the keyboard." msgstr "" #: labyrinth.xml:381(para) msgid "Drag the image in the opposite direction to the direction in which you want to scroll. For example, if you want to scroll down the image, drag the image upwards in the window." msgstr "" #: labyrinth.xml:387(para) msgid "Use the scrollbars on the window." msgstr "" #: labyrinth.xml:393(title) msgid "To Close an Image" msgstr "" #: labyrinth.xml:394(para) msgid "To close an image, choose FileClose This Window. If the window is the last Labyrinth window open, the application exits." msgstr "" #: labyrinth.xml:400(para) msgid "To quit Labyrinth and close all of the windows that you opened in the current session, choose FileExit." msgstr "" #: labyrinth.xml:407(para) msgid "This is a warning." msgstr "" #: labyrinth.xml:424(title) msgid "About Labyrinth" msgstr "" #: labyrinth.xml:425(para) msgid "Labyrinth was written by Don Scorgio, Martin Schaaf and Matthias Vogelgesang. (hacker@gnome.org). To find more information about Labyrinth, please visit the Labyrinth Web page." msgstr "" #: labyrinth.xml:430(para) msgid "To report a bug or make a suggestion regarding this application or this manual, follow the directions in this document." msgstr "" #: labyrinth.xml:436(para) msgid "This program is distributed 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. A copy of this license can be found at this link, or in the file COPYING included with the source code of this program." msgstr "" #. Put one translator per line, in the form of NAME , YEAR1, YEAR2. #: labyrinth.xml:0(None) msgid "translator-credits" msgstr "" labyrinth-0.6/install_data_files.sh000077500000000000000000000016171204476542500175510ustar00rootroot00000000000000# Run this to install Labyrinth's optional data files - language packs, icons, # and the .desktop file. # # Set the $DESTDIR environment variable to install somewhere other than root. set -e echo "Installing icons" for size in 16x16 22x22 24x24 scalable; do install -d $DESTDIR/usr/share/icons/hicolor/$size/apps; done install -m 644 data/labyrinth-16.png $DESTDIR/usr/share/icons/hicolor/16x16/apps/labyrinth.png install -m 644 data/labyrinth-22.png $DESTDIR/usr/share/icons/hicolor/22x22/apps/labyrinth.png install -m 644 data/labyrinth-24.png $DESTDIR/usr/share/icons/hicolor/24x24/apps/labyrinth.png install -m 644 data/labyrinth.svg $DESTDIR/usr/share/icons/hicolor/scalable/apps/labyrinth.svg echo "Installing .desktop file" install -D -m 755 data/labyrinth.desktop $DESTDIR/usr/share/applications/labyrinth.desktop echo "Installing translations" make -C po localedir=$DESTDIR/usr/share/locale install labyrinth-0.6/labyrinth000077500000000000000000000057221204476542500153140ustar00rootroot00000000000000#!/usr/bin/python # labyrinth # This file is part of Labyrinth # # Copyright (C) 2006 - Don Scorgie # Copyright (C) 2008 - Labyrinth-Dev-Team # # Labyrinth 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. # # Labyrinth 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 Labyrinth; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, # Boston, MA 02110-1301 USA # import pygtk import gettext, locale import optparse import sys, os import os.path as osp if os.name != 'nt': pygtk.require('2.0') import gtk from labyrinth_lib import utils from labyrinth_lib import Browser try: from labyrinth_lib import defs localedir = osp.abspath(osp.join(defs.DATA_DIR, "locale")) except: localedir = "/usr/share/locale" gettext.bindtextdomain('labyrinth', localedir) if hasattr(gettext, 'bind_textdomain_codeset'): gettext.bind_textdomain_codeset('labyrinth','UTF-8') gettext.textdomain('labyrinth') if hasattr(locale, 'bindtextdomain'): if not os.name == 'nt': locale.bindtextdomain('labyrinth', localedir) if hasattr(locale, 'bind_textdomain_codeset'): locale.bind_textdomain_codeset('labyrinth','UTF-8') locale.textdomain('labyrinth') gtk.glade.bindtextdomain('labyrinth') gtk.glade.textdomain('labyrinth') def main(): parser = optparse.OptionParser() parser.add_option("--use-tray-icon", dest="tray_icon", action="store_true", default=False) parser.add_option("--no-tray-icon", dest="tray_icon", action="store_false") parser.add_option("--hide-main-window", action="store_true", default=False) parser.add_option("-m", "--map", action="store", type="string", dest="filename", help="Open a map from a given filename (from internal database)") parser.add_option("-o", "--open", action="store", type="string", dest="filepath", help="Open a map from a given filename (including path)") (options, args) = parser.parse_args() if not options.tray_icon: options.hide_main_window=False MapBrowser = Browser.Browser ( start_hidden = options.hide_main_window, tray_icon = options.tray_icon ) if options.filename != None: MapBrowser.open_map_filename (os.path.join (utils.get_save_dir(), options.filename)) elif options.filepath != None: MapBrowser.open_map_filename (options.filepath) try: gtk.main() except: print "Exception caught while running. Dying a death." sys.exit(1) if __name__ == '__main__': main() labyrinth-0.6/labyrinth_lib/000077500000000000000000000000001204476542500162065ustar00rootroot00000000000000labyrinth-0.6/labyrinth_lib/BaseThought.py000066400000000000000000000356171204476542500210110ustar00rootroot00000000000000# BaseThought.py # This file is part of Labyrinth # # Copyright (C) 2006 - Don Scorgie # # Labyrinth 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. # # Labyrinth 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 Labyrinth; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, # Boston, MA 02110-1301 USA # import gobject import gtk import utils import pango import TextBufferMarkup MODE_EDITING = 0 MODE_IMAGE = 1 MODE_DRAW = 2 class BaseThought (gobject.GObject): ''' The basic class to derive other thoughts from. \ Instructions for creating derivative thought types are \ given as comments''' # These are general signals. They are available to all thoughts to # emit. If you emit other signals, the chances are they'll be ignored # by the MMapArea. It's you're responsiblity to catch and handle them. # All these signals are handled correctly by the MMapArea. __gsignals__ = dict (select_thought = (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,)), begin_editing = (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ()), popup_requested = (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT, gobject.TYPE_INT)), claim_unending_link = (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ()), update_view = (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()), create_link = (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,)), title_changed = (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_STRING,)), finish_editing = (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ()), delete_thought = (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()), text_selection_changed = (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_INT, gobject.TYPE_INT, gobject.TYPE_STRING)), change_mouse_cursor = (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_INT,)), update_links = (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()), grab_focus = (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_BOOLEAN,)), update_attrs = (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_BOOLEAN, gobject.TYPE_BOOLEAN, gobject.TYPE_BOOLEAN, pango.FontDescription))) # The first thing that should be called is this constructor # It sets some basic properties of all thoughts and should be called # before you start doing you're own thing with thoughts # save: the save document passed into the derived constructor # elem_type: a string representing the thought type (e.g. "image_thought") def __init__ (self, save, elem_type, undo, background_color, foreground_color): # Note: Once the thought has been successfully initialised (i.e. at the end # of the constructor) you MUST set all_okay to True # Otherwise, bad things will happen. self.all_okay = False super (BaseThought, self).__init__() self.ul = self.lr = None self.am_primary = False self.am_selected = False self.sensitive = 5 self.editing = False self.identity = -1 self.index = 0 self.end_index = 0 self.text = "" self.want_move = False self.undo = undo self.background_color = background_color self.foreground_color = foreground_color self.model_iter = None extended_elem = save.createElement ("Extended") self.extended_buffer = TextBufferMarkup.ExtendedBuffer (self.undo, extended_elem, save) self.extended_buffer.set_text("") self.extended_buffer.connect ("set_focus", self.focus_buffer) self.extended_buffer.connect ("set_attrs", self.set_extended_attrs) self.element = save.createElement (elem_type) self.element.appendChild (extended_elem) # These are self-explanitory. You probably don't want to # overwrite these methods, unless you have a very good reason def get_save_element (self): return self.element def make_primary (self): self.am_primary = True def select (self): self.am_selected = True def unselect (self): self.am_selected = False def get_max_area (self): if not self.ul or not self.lr: return 999,999,-999,-999 return self.ul[0], self.ul[1], self.lr[0], self.lr[1] def okay (self): return self.all_okay def move_by (self, x, y): self.ul = (self.ul[0]+x, self.ul[1]+y) self.recalc_position () self.emit ("update_links") self.emit ("update_view") def focus_buffer (self, buf): self.emit ("select_thought", None) self.emit ("grab_focus", True) def set_extended_attrs(self, buf, bold, underline, italics, pango_font): self.emit("update_attrs", bold, underline, italics, pango_font) def can_be_parent (self): return True # This, you may want to change. Though, doing so will only affect # thoughts that are "parents" def find_connection (self, other): if self.editing or other.editing: return None, None if not self.ul or not self.lr or not other.ul \ or not other.lr: return None, None if utils.use_bezier_curves: if other.ul[0] > self.lr[0]: xfrom = self.lr[0] xto = other.ul[0] else: xfrom = self.ul[0] xto = other.lr[0] else: xfrom = self.ul[0]-((self.ul[0]-self.lr[0]) / 2.) xto = other.ul[0]-((other.ul[0]-other.lr[0]) / 2.) yfrom = self.ul[1]-((self.ul[1]-self.lr[1]) / 2.) yto = other.ul[1]-((other.ul[1]-other.lr[1]) / 2.) return (xfrom, yfrom), (xto, yto) # All the rest of these should be handled within your thought # type, supposing you actually want to handle them. # You almost certianly do want to ;) def process_button_down (self, event, mode, transformed): return False def process_button_release (self, event, unending_link, mode, transformed): return False def process_key_press (self, event, mode): return False def handle_motion (self, event, mode, transformed): pass def includes (self, coords, mode): pass def begin_editing (self): return False def finish_editing (self): pass def draw (self, context): pass def load (self, node): pass def update_save (self): pass def copy_text (self, clip): pass def cut_text (self, clip): pass def paste_text (self, clip): pass def export (self, context, move_x, move_y): pass def commit_text (self, im_context, string, mode): pass def want_motion (self): return False def recalc_edges (self): pass def recalc_position (self): pass def delete_surroundings(self, imcontext, offset, n_chars, mode): pass def preedit_changed (self, imcontext, mode): pass def preedit_end (self, imcontext, mode): pass def preedit_start (self, imcontext, mode): pass def retrieve_surroundings (self, imcontext, mode): pass def set_bold (self, active): pass def get_popup_menu_items(self): pass class ResizableThought (BaseThought): ''' A resizable thought base class. This allows the sides and corners \ of the thought to be dragged around. It only provides the very basic \ functionality. Other stuff must be done within the derived classes''' # Possible types of resizing - where the user selected to resize RESIZE_NONE = 0 RESIZE_LEFT = 1 RESIZE_RIGHT = 2 RESIZE_TOP = 3 RESIZE_BOTTOM = 4 RESIZE_UL = 5 RESIZE_UR = 6 RESIZE_LL = 7 RESIZE_LR = 8 def __init__ (self, save, elem_type, undo, background_color, foreground_color): super (ResizableThought, self).__init__(save, elem_type, undo, background_color, foreground_color) self.resizing = False self.button_down = False def includes (self, coords, mode): if not self.ul or not self.lr or not coords: return False inside = (coords[0] < self.lr[0] + self.sensitive) and \ (coords[0] > self.ul[0] - self.sensitive) and \ (coords[1] < self.lr[1] + self.sensitive) and \ (coords[1] > self.ul[1] - self.sensitive) self.resizing = self.RESIZE_NONE self.motion_coords = coords if inside and (mode != MODE_EDITING or self.button_down): self.emit ("change_mouse_cursor", gtk.gdk.LEFT_PTR) return inside if inside: # 2 cases: 1. The click was within the main area # 2. The click was near the border # In the first case, we handle as normal # In the second case, we want to intercept all the fun thats # going to happen so we can resize the thought if abs (coords[0] - self.ul[0]) < self.sensitive: # its near the top edge somewhere if abs (coords[1] - self.ul[1]) < self.sensitive: # Its in the ul corner self.resizing = self.RESIZE_UL self.emit ("change_mouse_cursor", gtk.gdk.TOP_LEFT_CORNER) elif abs (coords[1] - self.lr[1]) < self.sensitive: # Its in the ll corner self.resizing = self.RESIZE_LL self.emit ("change_mouse_cursor", gtk.gdk.BOTTOM_LEFT_CORNER) elif coords[1] < self.lr[1] and coords[1] > self.ul[1]: #anywhere else along the left edge self.resizing = self.RESIZE_LEFT self.emit ("change_mouse_cursor", gtk.gdk.LEFT_SIDE) elif abs (coords[0] - self.lr[0]) < self.sensitive: if abs (coords[1] - self.ul[1]) < self.sensitive: # Its in the UR corner self.resizing = self.RESIZE_UR self.emit ("change_mouse_cursor", gtk.gdk.TOP_RIGHT_CORNER) elif abs (coords[1] - self.lr[1]) < self.sensitive: # Its in the lr corner self.resizing = self.RESIZE_LR self.emit ("change_mouse_cursor", gtk.gdk.BOTTOM_RIGHT_CORNER) elif coords[1] < self.lr[1] and coords[1] > self.ul[1]: #anywhere else along the right edge self.resizing = self.RESIZE_RIGHT self.emit ("change_mouse_cursor", gtk.gdk.RIGHT_SIDE) elif abs (coords[1] - self.ul[1]) < self.sensitive and \ (coords[0] < self.lr[0] and coords[0] > self.ul[0]): # Along the top edge somewhere self.resizing = self.RESIZE_TOP self.emit ("change_mouse_cursor", gtk.gdk.TOP_SIDE) elif abs (coords[1] - self.lr[1]) < self.sensitive and \ (coords[0] < self.lr[0] and coords[0] > self.ul[0]): # Along the bottom edge somewhere self.resizing = self.RESIZE_BOTTOM self.emit ("change_mouse_cursor", gtk.gdk.BOTTOM_SIDE) else: self.emit ("change_mouse_cursor", gtk.gdk.LEFT_PTR) self.want_move = (self.resizing != self.RESIZE_NONE) return inside labyrinth-0.6/labyrinth_lib/Browser.py000066400000000000000000000317551204476542500202160ustar00rootroot00000000000000# Browser.py # This file is part of Labyrinth # # Copyright (C) 2006 - Don Scorgie # - Andreas Sliwka # # Labyrinth 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. # # Labyrinth 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 Labyrinth; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, # Boston, MA 02110-1301 USA # # Standard library import tarfile import os import gettext _ = gettext.gettext # Gtk stuff import gtk if os.name != 'nt': import gconf import gtk.glade import pango import gobject # Local imports import utils import MainWindow from MapList import MapList import TrayIcon from . import __version__ AUTHORS = ['Don Scorgie ', 'Martin Schaaf ', 'Matthias Vogelgesang ', 'Andreas Sliwka '] class Browser (gtk.Window): COL_ID = 0 COL_TITLE = 1 COL_MODTIME = 2 def __init__(self, start_hidden, tray_icon): super(Browser, self).__init__() self.glade=gtk.glade.XML(utils.get_data_file_name('labyrinth.glade')) self.view = self.glade.get_widget ('MainView') self.populate_view () self.view.connect ('row-activated', self.open_row_cb) self.view.connect ('cursor-changed', self.cursor_change_cb) self.view_dependants = [] self.open_button = self.glade.get_widget('OpenButton') self.delete_button = self.glade.get_widget('DeleteButton') self.open_menu = self.glade.get_widget('open1') self.delete_menu = self.glade.get_widget('delete1') self.view_dependants.append (self.open_button) self.view_dependants.append (self.delete_button) self.view_dependants.append (self.open_menu) self.view_dependants.append (self.delete_menu) self.open_button.connect ('clicked', self.open_clicked) self.glade.get_widget('NewButton').connect ('clicked', self.new_clicked) self.delete_button.connect ('clicked', self.delete_clicked) self.open_menu.connect ('activate', self.open_clicked) self.glade.get_widget('new1').connect ('activate', self.new_clicked) self.delete_menu.connect ('activate', self.delete_clicked) self.glade.get_widget('import1').connect ('activate', self.import_clicked) self.glade.get_widget('quit1').connect ('activate', self.quit_clicked) self.glade.get_widget('about1').connect ('activate', self.about_clicked) self.glade.get_widget('showhelp').connect ('activate', self.show_help_clicked) for x in self.view_dependants: x.set_sensitive(False) self.main_window = self.glade.get_widget ('MapBrowser') # set remembered size if os.name != 'nt': self.config_client = gconf.client_get_default() self.config_client.add_dir ("/apps/labyrinth", gconf.CLIENT_PRELOAD_NONE) width = self.config_client.get_int ('/apps/labyrinth/width') height = self.config_client.get_int ('/apps/labyrinth/height') utils.use_bezier_curves = self.config_client.get_bool ('/apps/labyrinth/curves') if width == 0 or height == 0: width = 400 height = 300 else: width = 400 height = 300 view_sortable = self.view.get_model () view_sortable.connect ('sort-column-changed', self.sort_column_changed_cb) if os.name != 'nt': sort_order = self.config_client.get_int('/apps/labyrinth/map_sort_order') column_id = self.config_client.get_int('/apps/labyrinth/map_sort_order_column') view_sortable.set_sort_column_id (column_id, sort_order) self.main_window.resize (width, height) if os.name != 'nt': try: self.main_window.set_icon_name ('labyrinth') except: self.main_window.set_icon_from_file(utils.get_data_file_name('labyrinth.svg')) else: self.main_window.set_icon_from_file('images\\labyrinth-24.png') if tray_icon: self.main_window.connect ('delete_event', self.toggle_main_window, None) traymenu = gtk.Menu() quit_item = gtk.MenuItem("Quit") quit_item.connect("activate",self.quit_clicked) traymenu.add(quit_item) traymenu.show_all() self.traymenu = traymenu self.trayicon = TrayIcon.TrayIcon( icon_name="labyrinth", menu=traymenu, activate=self.toggle_main_window) else: self.main_window.connect('delete_event', self.quit_clicked, None) if start_hidden: self.main_window.hide () else: self.main_window.show_all () def toggle_main_window(self,*args): if self.main_window.get_property("visible"): self.main_window.hide() else: self.main_window.show() return True def map_title_cb (self, mobj, new_title, mobj1): map = MapList.get_by_window(mobj) if not map: raise AttributeError ("What a mess, can't find the map") map.title = new_title def get_selected_map(self): sel = self.view.get_selection () (model, it) = sel.get_selected () if it: (num,) = MapList.tree_view_model.get (it, self.COL_ID) return MapList.get_by_index(num) return None def cursor_change_cb (self, treeview): sensitive = bool(self.get_selected_map()) for x in self.view_dependants: x.set_sensitive(sensitive) def open_map_filename (self, fname): win = MainWindow.LabyrinthWindow (fname) win.show () def open_map (self, map, imported=False): win = MainWindow.LabyrinthWindow (map.filename, imported) win.connect ("title-changed", self.map_title_cb) win.connect ("window_closed", self.remove_map_cb) win.connect ("file_saved", self.file_save_cb) win.show () map.window = win return (MapList.index(map), win) def open_selected_map(self): map = self.get_selected_map() if map is None: raise ValueError("you clicked the 'open' button but had no map selected") if map.window: print "Window for map '%s' is already open" % map.title # may be the window should be raised? else: self.open_map (map) def show_help_clicked(self, arg): try: gtk.show_uri(None, 'help:labyrinth', 0) except gobject.GError, e: print _('Unable to display help: %s') % str(e) def about_clicked (self, arg): about_dialog = gtk.AboutDialog () about_dialog.set_name ("Labyrinth") about_dialog.set_version (__version__) if os.name != 'nt': try: about_dialog.set_logo_icon_name("labyrinth") except: pass else: about_dialog.set_logo (gtk.gdk.pixbuf_new_from_file("images\\labyrinth-24.png")) about_dialog.set_license ( "Labyrinth is free software; you can redistribute it and/or modify " "it under the terms of the GNU General Public Licence as published by " "the Free Software Foundation; either version 2 of the Licence, or " "(at your option) any later version." "\n\n" "Labyrinth 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 Licence for more details." "\n\n" "You should have received a copy of the GNU General Public Licence " "along with Labyrinth; if not, write to the Free Software Foundation, Inc., " "59 Temple Place, Suite 330, Boston, MA 02111-1307 USA") about_dialog.set_wrap_license (True) about_dialog.set_copyright ("2006-2008 Don Scorgie et. al") about_dialog.set_authors (AUTHORS) about_dialog.set_website ("http://code.google.com/p/labyrinth") about_dialog.set_translator_credits (_("Translation by Don Scorgie")) about_dialog.run () about_dialog.hide () del (about_dialog) return def open_clicked (self, button): self.open_selected_map() def open_row_cb (self, view, path, col): self.open_selected_map () def new_clicked (self, button): map = MapList.create_empty_map() self.open_map(map) def delete_clicked (self, button): map = self.get_selected_map () if not map: raise ValueError("You clicked on delete but had no map selected") error_message = "" if map.window: error_message = _("The map cannot be deleted right now. Is it open?") elif not map.filename: error_message = _("The map has no associated filename.") if error_message: dialog = gtk.MessageDialog (self, gtk.DIALOG_MODAL, gtk.MESSAGE_WARNING, gtk.BUTTONS_OK, _("Cannot delete this map")) dialog.format_secondary_text (error_message) dialog.run () dialog.hide () del (dialog) return dialog = gtk.MessageDialog (self, gtk.DIALOG_MODAL, gtk.MESSAGE_WARNING, gtk.BUTTONS_YES_NO, _("Do you really want to delete this Map?")) resp = dialog.run () dialog.hide () del (dialog) if resp != gtk.RESPONSE_YES: return MapList.delete (map) self.view.emit ('cursor-changed') def remove_map_cb (self, mobj, a): map = MapList.get_by_window(mobj) if map: MapList.delete(map) self.view.emit ('cursor-changed') return raise ValueError("Cant remove map of window %s" % mobj) def file_save_cb (self, mobj, new_fname, mobj1): map = MapList.get_by_window(mobj) if map: map.window = None map.filename = new_fname return def import_clicked(self, button, other=None, *data): chooser = gtk.FileChooserDialog(title=_("Open File"), action=gtk.FILE_CHOOSER_ACTION_OPEN, \ buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK)) filtr = gtk.FileFilter () filtr.set_name(_('MAPZ Compressed Map (*.mapz)')) filtr.add_pattern('*.mapz') chooser.add_filter(filtr) response = chooser.run() if response == gtk.RESPONSE_OK: filename = chooser.get_filename() tf = tarfile.open(filename) mapname = os.path.join (utils.get_save_dir (), tf.getnames()[0]) tf.extractall(utils.get_save_dir()) tf.close() map = MapList.new_from_file(mapname) map.filename = mapname chooser.destroy() def quit_clicked (self, button, other=None, *data): for map in MapList.get_open_windows(): map.window.close_window_cb (None) width, height = self.main_window.get_size() if os.name != 'nt': self.config_client.set_int('/apps/labyrinth/width', width) self.config_client.set_int('/apps/labyrinth/height', height) gtk.main_quit () def populate_view (self): cellrenderer = gtk.CellRendererText() cellrenderer.set_property("ellipsize", pango.ELLIPSIZE_END) column = gtk.TreeViewColumn(_("Map Name"), cellrenderer, text=self.COL_TITLE) column.set_resizable(True) column.set_expand (True) column.set_sort_column_id (1) self.view.append_column(column) col1 = gtk.TreeViewColumn (_("Last Modified"), gtk.CellRendererText(), text=self.COL_MODTIME) col1.set_resizable(True) col1.set_sort_column_id (2) self.view.append_column(col1) self.view.set_model (MapList.get_TreeViewModel()) self.view.set_search_column(self.COL_TITLE) self.view.set_enable_search (True) def sort_column_changed_cb (self, data): column_id, sort_order = data.get_sort_column_id () if os.name != 'nt': self.config_client.set_int('/apps/labyrinth/map_sort_order', sort_order) self.config_client.set_int('/apps/labyrinth/map_sort_order_column', column_id) labyrinth-0.6/labyrinth_lib/DrawingThought.py000066400000000000000000000642571204476542500215340ustar00rootroot00000000000000# DrawingThought.py # This file is part of Labyrinth # # Copyright (C) 2006 - Don Scorgie # # Labyrinth 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. # # Labyrinth 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 Labyrinth; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, # Boston, MA 02110-1301 USA # import gtk import xml.dom import gettext _ = gettext.gettext import math import BaseThought import utils import UndoManager STYLE_CONTINUE=0 STYLE_END=1 STYLE_BEGIN=2 ndraw =0 MODE_EDITING = 0 MODE_IMAGE = 1 MODE_DRAW = 2 UNDO_RESIZE = 0 UNDO_DRAW = 1 UNDO_ERASE = 2 class DrawingThought (BaseThought.ResizableThought): class DrawingPoint (object): def __init__ (self, coords, style=STYLE_CONTINUE, color = gtk.gdk.Color(0,0,0), width = 2): self.x, self.y = coords self.style = style if color == None: color = gtk.gdk.Color(0,0,0) self.color = color self.width = 1 def move_by (self, x, y): self.x += x self.y += y def __init__ (self, coords, pango_context, thought_number, save, undo, loading, background_color, foreground_color): global ndraw super (DrawingThought, self).__init__(save, "drawing_thought", undo, background_color, foreground_color) ndraw+=1 self.identity = thought_number self.want_move = False self.points = [] self.text = _("Drawing #%d" % ndraw) self.drawing = 0 if not loading: margin = utils.margin_required (utils.STYLE_NORMAL) self.ul = (coords[0]-margin[0], coords[1]-margin[1]) self.lr = (coords[0]+100+margin[2], coords[1]+100+margin[3]) self.min_x = coords[0]+90 self.max_x = coords[0]+15 self.min_y = coords[1]+90 self.max_y = coords[1]+15 self.width = 100 self.height = 100 self.all_okay = True def draw (self, context): if len (self.extended_buffer.get_text()) == 0: utils.draw_thought_outline (context, self.ul, self.lr, self.background_color, self.am_selected, self.am_primary, utils.STYLE_NORMAL) else: utils.draw_thought_outline (context, self.ul, self.lr, self.background_color, self.am_selected, self.am_primary, utils.STYLE_EXTENDED_CONTENT) cwidth = context.get_line_width () context.set_line_width (2) if len (self.points) > 0: for p in self.points: if p.style == STYLE_BEGIN: context.move_to (p.x, p.y) r,g,b = utils.gtk_to_cairo_color(self.foreground_color) context.set_source_rgb (r, g, b) elif p.style == STYLE_END: context.line_to (p.x, p.y) context.stroke() else: context.line_to (p.x, p.y) context.set_line_width (cwidth) context.stroke () return def want_motion (self): return self.want_move def recalc_edges (self): self.lr = (self.ul[0]+self.width, self.ul[1]+self.height) def undo_resize (self, action, mode): self.undo.block () choose = 1 if mode == UndoManager.UNDO: choose = 0 self.ul = action.args[choose][0] self.width = action.args[choose][1] self.height = action.args[choose][2] self.recalc_edges () self.emit ("update_links") self.emit ("update_view") self.undo.unblock () def undo_drawing (self, action, mode): self.undo.block () if mode == UndoManager.UNDO: choose = 1 for p in action.args[0]: self.points.remove (p) else: choose = 2 for p in action.args[0]: self.points.append (p) self.ul = action.args[choose][0] self.width = action.args[choose][1] self.height = action.args[choose][2] self.recalc_edges () self.emit ("update_links") self.emit ("update_view") self.undo.unblock () def process_button_down (self, event, mode, transformed): modifiers = gtk.accelerator_get_default_mod_mask () self.button_down = True if event.button == 1: if event.type == gtk.gdk.BUTTON_PRESS: self.emit ("select_thought", event.state & modifiers) self.emit ("update_view") if mode == MODE_EDITING and self.resizing != self.RESIZE_NONE: self.want_move = True self.drawing = 0 self.orig_size = (self.ul, self.width, self.height) return True elif mode == MODE_DRAW: self.want_move = True self.drawing = 2 if not event.state & gtk.gdk.SHIFT_MASK: self.drawing = 1 self.orig_size = (self.ul, self.width, self.height) self.ins_points = [] self.del_points = [] return True elif event.button == 3: self.emit ("popup_requested", event, 1) self.emit ("update_view") def process_button_release (self, event, unending_link, mode, transformed): self.button_down = False if unending_link: unending_link.set_child (self) self.emit ("claim_unending_link") if len(self.points) > 0: self.points[-1].style=STYLE_END self.emit ("update_view") if self.want_move and self.drawing == 0: self.undo.add_undo (UndoManager.UndoAction (self, UNDO_RESIZE, self.undo_resize, \ self.orig_size, (self.ul, self.width, self.height))) elif self.want_move and self.drawing == 1: self.undo.add_undo (UndoManager.UndoAction (self, UNDO_DRAW, self.undo_drawing, \ self.ins_points, self.orig_size, \ (self.ul, self.width, self.height))) elif self.want_move and self.drawing == 2: self.undo.add_undo (UndoManager.UndoAction (self, UNDO_ERASE, self.undo_erase, \ self.ins_points)) self.drawing = 0 self.want_move = False def undo_erase (self, action, mode): self.undo.block () action.args[0].reverse () if mode == UndoManager.UNDO: for x in action.args[0]: if x[0] == 0: self.points.remove (x[2]) else: self.points.insert (x[1],x[2]) else: for x in action.args[0]: if x[0] == 0: self.points.insert (x[1], x[2]) else: self.points.remove (x[2]) self.undo.unblock () self.emit ("update_view") def handle_motion (self, event, mode, transformed): if (self.resizing == self.RESIZE_NONE or not self.want_move or not event.state & gtk.gdk.BUTTON1_MASK) \ and mode != MODE_DRAW: if not event.state & gtk.gdk.BUTTON1_MASK or mode != MODE_EDITING: return False else: self.emit ("create_link", \ (self.ul[0]-((self.ul[0]-self.lr[0]) / 2.), self.ul[1]-((self.ul[1]-self.lr[1]) / 2.))) diffx = transformed[0] - self.motion_coords[0] diffy = transformed[1] - self.motion_coords[1] change = (len(self.points) == 0) tmp = self.motion_coords self.motion_coords = transformed if self.resizing != self.RESIZE_NONE: if self.resizing == self.RESIZE_LEFT: if self.ul[0] + diffx > self.min_x: self.motion_coords = tmp return True self.ul = (self.ul[0]+diffx, self.ul[1]) if change: self.max_x += diffx elif self.resizing == self.RESIZE_RIGHT: if self.lr[0] + diffx < self.max_x: self.motion_coords = tmp return True self.lr = (self.lr[0]+diffx, self.lr[1]) if change: self.min_x += diffx elif self.resizing == self.RESIZE_TOP: if self.ul[1] + diffy > self.min_y: self.motion_coords = tmp return True self.ul = (self.ul[0], self.ul[1]+diffy) if change: self.max_y += diffy elif self.resizing == self.RESIZE_BOTTOM: if self.lr[1] + diffy < self.max_y: self.motion_coords = tmp return True self.lr = (self.lr[0], self.lr[1]+diffy) if change: self.min_y += diffy elif self.resizing == self.RESIZE_UL: if self.ul[1] + diffy > self.min_y or self.ul[0] + diffx > self.min_x: self.motion_coords = tmp return True self.ul = (self.ul[0]+diffx, self.ul[1]+diffy) if change: self.max_x += diffx self.max_y += diffy elif self.resizing == self.RESIZE_UR: if self.ul[1] + diffy > self.min_y or self.lr[0] + diffx < self.max_x: self.motion_coords = tmp return True self.ul = (self.ul[0], self.ul[1]+diffy) self.lr = (self.lr[0]+diffx, self.lr[1]) if change: self.min_x += diffx self.max_y += diffy elif self.resizing == self.RESIZE_LL: if self.lr[1] + diffy < self.max_y or self.ul[0] + diffx > self.min_x: self.motion_coords = tmp return True self.ul = (self.ul[0]+diffx, self.ul[1]) self.lr = (self.lr[0], self.lr[1]+diffy) if change: self.max_x += diffx self.min_y += diffy elif self.resizing == self.RESIZE_LR: if self.lr[1] + diffy < self.max_y: self.motion_coords = tmp return True if self.lr[0] + diffx < self.max_x: self.motion_coords = tmp return True self.lr = (self.lr[0]+diffx, self.lr[1]+diffy) if change: self.min_x += diffx self.min_y += diffy self.width = self.lr[0] - self.ul[0] self.height = self.lr[1] - self.ul[1] self.emit ("update_links") self.emit ("update_view") return True elif self.drawing == 1: if transformed[0] < self.ul[0]+5: self.ul = (transformed[0]-5, self.ul[1]) elif transformed[0] > self.lr[0]-5: self.lr = (transformed[0]+5, self.lr[1]) if transformed[1] < self.ul[1]+5: self.ul = (self.ul[0], transformed[1]-5) elif transformed[1] > self.lr[1]-5: self.lr = (self.lr[0], transformed[1]+5) if transformed[0] < self.min_x: self.min_x = transformed[0]-10 elif transformed[0] > self.max_x: self.max_x = transformed[0]+5 if transformed[1] < self.min_y: self.min_y = transformed[1]-10 elif transformed[1] > self.max_y: self.max_y = transformed[1]+5 self.width = self.lr[0] - self.ul[0] self.height = self.lr[1] - self.ul[1] if len(self.points) == 0 or self.points[-1].style == STYLE_END: p = self.DrawingPoint (transformed, STYLE_BEGIN, self.foreground_color) else: p = self.DrawingPoint (transformed, STYLE_CONTINUE) self.points.append (p) self.ins_points.append (p) elif self.drawing == 2 and len (self.points) > 0: out = self.points[0] loc = [] handle = [] ins_point = -1 for x in self.points: ins_point += 1 dist = (x.x - transformed[0])**2 + (x.y - transformed[1])**2 if dist < 16: if x == self.points[0]: out = None loc.append ((ins_point, x, dist)) else: if len(loc) != 0: handle.append ((loc, out, x)) loc = [] elif x.style != STYLE_BEGIN: x1 = x.x - out.x y1 = x.y - out.y d_rsqr = x1**2 + y1 **2 d = ((out.x-transformed[0])*(x.y-transformed[1]) - (x.x-transformed[0])*(out.y-transformed[1])) det = (d_rsqr*16) - d**2 if det > 0: xt = -99999 yt = -99999 xalt = -99999 yalt = -99999 if y1 < 0: sgn = -1 else: sgn = 1 xt = (((d*y1) + sgn*x1 * math.sqrt (det)) / d_rsqr) +transformed[0] xalt = (((d*y1) - sgn*x1 * math.sqrt (det)) / d_rsqr) +transformed[0] yt = (((-d*x1) + abs(y1)*math.sqrt(det)) / d_rsqr) + transformed[1] yalt = (((-d*x1) - abs(y1)*math.sqrt(det)) / d_rsqr) +transformed[1] x1_inside = (xt > x.x and xt < out.x) or (xt > out.x and xt < x.x) x2_inside = (xalt > x.x and xalt < out.x) or (xalt > out.x and xalt < x.x) y1_inside = (yt > x.y and yt < out.y) or (yt > out.y and yt < x.y) y2_inside = (yalt > x.y and yalt < out.y) or (yalt > out.y and yalt < x.y) if (x1_inside and x2_inside and y1_inside and y2_inside): if abs (xalt - x.x) < abs (xt - x.x): handle.append ((None, out, x, ins_point, xt, xalt, yt, yalt)) else: handle.append ((None, out, x, ins_point, xalt, xt, yalt, yt)) elif x.x == out.x and y1_inside and y2_inside: if abs (yalt - x.y) < abs (yt - x.y): handle.append ((None, out, x, ins_point, xt, xalt, yt, yalt)) else: handle.append ((None, out, x, ins_point, xalt, xt, yalt, yt)) elif x.y == out.y and x1_inside and x2_inside: if abs (xalt - x.x) < abs (xt - x.x): handle.append ((None, out, x, ins_point, xt, xalt, yt, yalt)) else: handle.append ((None, out, x, ins_point, xalt, xt, yalt, yt)) out = x if loc: handle.append ((loc, out, None)) appends = [] dels = [] for l in handle: inside = l[0] prev = l[1] next = l[2] if not inside: ins = l[3] x1 = l[4] x2 = l[5] y1 = l[6] y2 = l[7] p1 = self.DrawingPoint ((x1,y1), STYLE_END) p2 = self.DrawingPoint ((x2,y2), STYLE_BEGIN) appends.append ((p1, ins)) appends.append ((p2, ins)) else: first = inside[0][1] last = inside[-1][1] done_ins = 0 if last.style != STYLE_END: end_dist = math.sqrt (inside[-1][2]) - 4 alpha = math.atan2 ((last.y-next.y), (last.x-next.x)) new_x = end_dist * math.cos(alpha) + last.x new_y = end_dist * math.sin(alpha) + last.y p = self.DrawingPoint ((new_x, new_y), STYLE_BEGIN) appends.append ((p, inside[-1][0])) done_ins = 1 if first.style != STYLE_BEGIN: start_dist = math.sqrt (inside[0][2]) - 4 alpha = math.atan2 ((first.y-prev.y),(first.x-prev.x)) new_x = start_dist * math.cos (alpha) + first.x new_y = start_dist * math.sin (alpha) + first.y p = self.DrawingPoint ((new_x, new_y), STYLE_END) appends.append ((p, inside[0][0]-done_ins)) for i in inside: dels.append (i[1]) inserts = 0 for x in appends: self.points.insert (x[1]+inserts, x[0]) self.ins_points.append ((0, x[1]+inserts, x[0])) inserts+=1 for x in dels: self.ins_points.append ((1, self.points.index (x), x)) self.points.remove (x) self.emit ("update_links") self.emit ("update_view") return True def move_by (self, x, y): self.ul = (self.ul[0]+x, self.ul[1]+y) self.min_x += x self.min_y += y self.max_x += x self.max_y += y for p in self.points: p.move_by(x, y) self.recalc_edges () self.emit ("update_links") def update_save (self): next = self.element.firstChild while next: m = next.nextSibling if next.nodeName == "point": self.element.removeChild (next) next.unlink () next = m text = self.extended_buffer.get_text () if text: self.extended_buffer.update_save() else: try: self.element.removeChild(self.extended_buffer.element) except xml.dom.NotFoundErr: pass self.element.setAttribute ("ul-coords", str(self.ul)) self.element.setAttribute ("lr-coords", str(self.lr)) self.element.setAttribute ("identity", str(self.identity)) self.element.setAttribute ("background-color", self.background_color.to_string()) self.element.setAttribute ("foreground-color", self.foreground_color.to_string()) self.element.setAttribute ("min_x", str(self.min_x)) self.element.setAttribute ("min_y", str(self.min_y)) self.element.setAttribute ("max_x", str(self.max_x)) self.element.setAttribute ("max_y", str(self.max_y)) if self.am_selected: self.element.setAttribute ("current_root", "true") else: try: self.element.removeAttribute ("current_root") except xml.dom.NotFoundErr: pass if self.am_primary: self.element.setAttribute ("primary_root", "true"); else: try: self.element.removeAttribute ("primary_root") except xml.dom.NotFoundErr: pass doc = self.element.ownerDocument for p in self.points: elem = doc.createElement ("point") self.element.appendChild (elem) elem.setAttribute ("coords", str((p.x,p.y))) elem.setAttribute ("type", str(p.style)) elem.setAttribute ("color", p.color.to_string()) return def load (self, node): tmp = node.getAttribute ("ul-coords") self.ul = utils.parse_coords (tmp) tmp = node.getAttribute ("lr-coords") self.lr = utils.parse_coords (tmp) self.identity = int (node.getAttribute ("identity")) try: tmp = node.getAttribute ("background-color") self.background_color = gtk.gdk.color_parse(tmp) tmp = node.getAttribute ("foreground-color") self.foreground_color = gtk.gdk.color_parse(tmp) except ValueError: pass self.min_x = float(node.getAttribute ("min_x")) self.min_y = float(node.getAttribute ("min_y")) self.max_x = float(node.getAttribute ("max_x")) self.max_y = float(node.getAttribute ("max_y")) self.width = self.lr[0] - self.ul[0] self.height = self.lr[1] - self.ul[1] self.am_selected = node.hasAttribute ("current_root") self.am_primary = node.hasAttribute ("primary_root") for n in node.childNodes: if n.nodeName == "Extended": self.extended_buffer.load(n) elif n.nodeName == "point": style = int (n.getAttribute ("type")) tmp = n.getAttribute ("coords") c = utils.parse_coords (tmp) col = None try: tmp = n.getAttribute ("color") col = gtk.gdk.color_parse (tmp) except ValueError: pass self.points.append (self.DrawingPoint (c, style, col)) else: print "Unknown node type: "+str(n.nodeName) def export (self, context, move_x, move_y): utils.export_thought_outline (context, self.ul, self.lr, self.background_color, self.am_selected, self.am_primary, utils.STYLE_NORMAL, (move_x, move_y)) cwidth = context.get_line_width () context.set_line_width (1) if len (self.points) > 0: for p in self.points: if p.style == STYLE_BEGIN: context.move_to (p.x+move_x, p.y+move_y) else: context.line_to (p.x+move_x,p.y+move_y) context.set_line_width (cwidth) r,g,b = utils.gtk_to_cairo_color(self.foreground_color) context.set_source_rgb (r, g, b) context.stroke () return def includes (self, coords, mode): if not self.ul or not self.lr or not coords: return False if self.want_move and mode == MODE_DRAW: self.emit ("change_mouse_cursor", gtk.gdk.PENCIL) return True inside = (coords[0] < self.lr[0] + self.sensitive) and \ (coords[0] > self.ul[0] - self.sensitive) and \ (coords[1] < self.lr[1] + self.sensitive) and \ (coords[1] > self.ul[1] - self.sensitive) self.resizing = self.RESIZE_NONE self.motion_coords = coords if inside and (mode != MODE_EDITING or self.button_down): if mode == MODE_DRAW: self.emit ("change_mouse_cursor", gtk.gdk.PENCIL) else: self.emit ("change_mouse_cursor", gtk.gdk.LEFT_PTR) return inside if inside: # 2 cases: 1. The click was within the main area # 2. The click was near the border # In the first case, we handle as normal # In the second case, we want to intercept all the fun thats # going to happen so we can resize the thought if abs (coords[0] - self.ul[0]) < self.sensitive: # its near the top edge somewhere if abs (coords[1] - self.ul[1]) < self.sensitive: # Its in the ul corner self.resizing = self.RESIZE_UL self.emit ("change_mouse_cursor", gtk.gdk.TOP_LEFT_CORNER) elif abs (coords[1] - self.lr[1]) < self.sensitive: # Its in the ll corner self.resizing = self.RESIZE_LL self.emit ("change_mouse_cursor", gtk.gdk.BOTTOM_LEFT_CORNER) elif coords[1] < self.lr[1] and coords[1] > self.ul[1]: #anywhere else along the left edge self.resizing = self.RESIZE_LEFT self.emit ("change_mouse_cursor", gtk.gdk.LEFT_SIDE) elif abs (coords[0] - self.lr[0]) < self.sensitive: if abs (coords[1] - self.ul[1]) < self.sensitive: # Its in the UR corner self.resizing = self.RESIZE_UR self.emit ("change_mouse_cursor", gtk.gdk.TOP_RIGHT_CORNER) elif abs (coords[1] - self.lr[1]) < self.sensitive: # Its in the lr corner self.resizing = self.RESIZE_LR self.emit ("change_mouse_cursor", gtk.gdk.BOTTOM_RIGHT_CORNER) elif coords[1] < self.lr[1] and coords[1] > self.ul[1]: #anywhere else along the right edge self.resizing = self.RESIZE_RIGHT self.emit ("change_mouse_cursor", gtk.gdk.RIGHT_SIDE) elif abs (coords[1] - self.ul[1]) < self.sensitive and \ (coords[0] < self.lr[0] and coords[0] > self.ul[0]): # Along the top edge somewhere self.resizing = self.RESIZE_TOP self.emit ("change_mouse_cursor", gtk.gdk.TOP_SIDE) elif abs (coords[1] - self.lr[1]) < self.sensitive and \ (coords[0] < self.lr[0] and coords[0] > self.ul[0]): # Along the bottom edge somewhere self.resizing = self.RESIZE_BOTTOM self.emit ("change_mouse_cursor", gtk.gdk.BOTTOM_SIDE) else: self.emit ("change_mouse_cursor", gtk.gdk.LEFT_PTR) self.want_move = (self.resizing != self.RESIZE_NONE) return inside def get_popup_menu_items(self): return [] labyrinth-0.6/labyrinth_lib/ImageThought.py000066400000000000000000000343721204476542500211560ustar00rootroot00000000000000# ImageThought.py # This file is part of labyrinth # # Copyright (C) 2006 - Don Scorgie # # labyrinth 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. # # labyrinth 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 labyrinth; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, # Boston, MA 02110-1301 USA # # Standard library import os.path import xml.dom import gettext _ = gettext.gettext # Gtk stuff import gtk import cairo # Local imports import BaseThought import utils import UndoManager MODE_EDITING = 0 MODE_IMAGE = 1 MODE_DRAW = 2 UNDO_RESIZE = 0 class ImageThought (BaseThought.ResizableThought): def __init__ (self, coords, pango_context, thought_number, save, undo, loading, background_color): super (ImageThought, self).__init__(save, "image_thought", undo, background_color, None) self.identity = thought_number margin = utils.margin_required (utils.STYLE_NORMAL) self.want_move = False if coords: self.ul = (coords[0]-margin[0], coords[1] - margin[1]) self.pic_location = coords else: self.ul = None self.button_press = False if not loading: self.all_okay = self.open_image () else: self.all_okay = True def open_image (self, filename = None): # Present a dialog for the user to choose an image here if not filename: fil = gtk.FileFilter () fil.set_name("Images") fil.add_pixbuf_formats () dialog = gtk.FileChooserDialog (_("Choose image to insert"), None, gtk.FILE_CHOOSER_ACTION_OPEN, \ (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK)) dialog.add_filter (fil) res = dialog.run () dialog.hide () if res != gtk.RESPONSE_OK: return False else: fname = dialog.get_filename() else: fname = filename try: self.orig_pic = gtk.gdk.pixbuf_new_from_file (fname) except: try: # lets see if file was imported and is already extracted fname = os.path.join (utils.get_images_dir (), + os.path.basename(filename)) self.orig_pic = gtk.gdk.pixbuf_new_from_file (fname) except: return False self.filename = fname if not filename: self.width = self.orig_pic.get_width () self.height = self.orig_pic.get_height () margin = utils.margin_required (utils.STYLE_NORMAL) self.lr = (self.pic_location[0]+self.width+margin[2], self.pic_location[1]+self.height+margin[3]) self.pic = self.orig_pic self.text = fname[fname.rfind('/')+1:fname.rfind('.')] return True def draw (self, context): if len (self.extended_buffer.get_text()) == 0: utils.draw_thought_outline (context, self.ul, self.lr, self.background_color, self.am_selected, self.am_primary, utils.STYLE_NORMAL) else: utils.draw_thought_outline (context, self.ul, self.lr, self.background_color, self.am_selected, self.am_primary, utils.STYLE_EXTENDED_CONTENT) if self.pic: context.set_source_pixbuf (self.pic, self.pic_location[0], self.pic_location[1]) context.rectangle (self.pic_location[0], self.pic_location[1], self.width, self.height) context.fill () context.set_source_rgb (0,0,0) def export (self, context, move_x, move_y): utils.export_thought_outline (context, self.ul, self.lr, self.background_color, self.am_selected, self.am_primary, utils.STYLE_NORMAL, (move_x, move_y)) if self.pic: if hasattr(context, "set_source_pixbuf"): context.set_source_pixbuf (self.pic, self.pic_location[0]+move_x, self.pic_location[1]+move_y) elif hasattr(context, "set_source_surface"): pixel_array = utils.pixbuf_to_cairo (self.pic.get_pixels_array()) image_surface = cairo.ImageSurface.create_for_data(pixel_array, cairo.FORMAT_ARGB32, self.width, self.height, -1) context.set_source_surface (image_surface, self.pic_location[0]+move_x, self.pic_location[1]+move_y) context.rectangle (self.pic_location[0]+move_x, self.pic_location[1]+move_y, self.width, self.height) context.fill () context.set_source_rgb (0,0,0) def want_motion (self): return self.want_move def recalc_edges (self): margin = utils.margin_required (utils.STYLE_NORMAL) self.pic_location = (self.ul[0]+margin[0], self.ul[1]+margin[1]) self.lr = (self.pic_location[0]+self.width+margin[2], self.pic_location[1]+self.height+margin[3]) def recalc_position (self): self.recalc_edges () def undo_resize (self, action, mode): self.undo.block () if mode == UndoManager.UNDO: choose = 0 else: choose = 1 self.ul = action.args[choose][0] self.width = action.args[choose][1] self.height = action.args[choose][2] self.pic = self.orig_pic.scale_simple (int(self.width), int(self.height), gtk.gdk.INTERP_HYPER) self.recalc_edges () self.emit ("update_links") self.emit ("update_view") self.undo.unblock () def process_button_down (self, event, mode, transformed): modifiers = gtk.accelerator_get_default_mod_mask () self.button_down = True if event.button == 1: if event.type == gtk.gdk.BUTTON_PRESS: self.emit ("select_thought", event.state & modifiers) self.emit ("update_view") if mode == MODE_EDITING and self.resizing != self.RESIZE_NONE: self.orig_size = (self.ul, self.width, self.height) self.want_move = True return True elif event.button == 3: self.emit ("popup_requested", event, 1) self.emit ("update_view") def process_button_release (self, event, unending_link, mode, transformed): self.button_down = False if unending_link: unending_link.set_child (self) self.emit ("claim_unending_link") if self.orig_pic: self.pic = self.orig_pic.scale_simple (int(self.width), int(self.height), gtk.gdk.INTERP_HYPER) self.emit ("update_view") if self.want_move: self.undo.add_undo (UndoManager.UndoAction (self, UNDO_RESIZE, self.undo_resize, \ self.orig_size, (self.ul, self.width, self.height))) self.want_move = False def handle_motion (self, event, mode, transformed): if self.resizing == self.RESIZE_NONE or not self.want_move or not event.state & gtk.gdk.BUTTON1_MASK: if not event.state & gtk.gdk.BUTTON1_MASK: return False elif mode == MODE_EDITING: self.emit ("create_link", \ (self.ul[0]-((self.ul[0]-self.lr[0]) / 2.), self.ul[1]-((self.ul[1]-self.lr[1]) / 2.))) return True diffx = transformed[0] - self.motion_coords[0] diffy = transformed[1] - self.motion_coords[1] tmp = self.motion_coords self.motion_coords = transformed if self.resizing == self.RESIZE_LEFT: if self.width - diffx < 10: self.motion_coords = tmp return True self.ul = (self.ul[0]+diffx, self.ul[1]) self.pic_location = (self.pic_location[0]+diffx, self.pic_location[1]) self.width -= diffx elif self.resizing == self.RESIZE_RIGHT: if self.width + diffx < 10: self.motion_coords = tmp return True self.lr = (self.lr[0]+diffx, self.lr[1]) self.width += diffx elif self.resizing == self.RESIZE_TOP: if self.height - diffy < 10: self.motion_coords = tmp return True self.ul = (self.ul[0], self.ul[1]+diffy) self.pic_location = (self.pic_location[0], self.pic_location[1]+diffy) self.height -= diffy elif self.resizing == self.RESIZE_BOTTOM: if self.height + diffy < 10: self.motion_coords = tmp return True self.lr = (self.lr[0], self.lr[1]+diffy) self.height += diffy elif self.resizing == self.RESIZE_UL: if self.height - diffy < 10 or self.width - diffx < 10: self.motion_coords = tmp return True self.ul = (self.ul[0]+diffx, self.ul[1]+diffy) self.pic_location = (self.pic_location[0]+diffx, self.pic_location[1]+diffy) self.width -= diffx self.height -= diffy elif self.resizing == self.RESIZE_UR: if self.height - diffy < 10 or self.width + diffx < 10: self.motion_coords = tmp return True self.ul = (self.ul[0], self.ul[1]+diffy) self.lr = (self.lr[0]+diffx, self.lr[1]) self.pic_location = (self.pic_location[0], self.pic_location[1]+diffy) self.width += diffx self.height -= diffy elif self.resizing == self.RESIZE_LL: if self.height + diffy < 10 or self.width - diffx < 10: self.motion_coords = tmp return True self.ul = (self.ul[0]+diffx, self.ul[1]) self.lr = (self.lr[0], self.lr[1]+diffy) self.pic_location = (self.pic_location[0]+diffx, self.pic_location[1]) self.width -= diffx self.height += diffy elif self.resizing == self.RESIZE_LR: if self.height + diffy < 10: self.motion_coords = tmp return True if self.width + diffx < 10: self.motion_coords = tmp return True self.lr = (self.lr[0]+diffx, self.lr[1]+diffy) self.width += diffx self.height += diffy if self.orig_pic: self.pic = self.orig_pic.scale_simple (int(self.width), int(self.height), gtk.gdk.INTERP_NEAREST) self.emit ("update_links") self.emit ("update_view") return True def update_save (self): text = self.extended_buffer.get_text () if text: self.extended_buffer.update_save() else: try: self.element.removeChild(self.extended_buffer.element) except xml.dom.NotFoundErr: pass self.element.setAttribute ("ul-coords", str(self.ul)) self.element.setAttribute ("lr-coords", str(self.lr)) self.element.setAttribute ("identity", str(self.identity)) self.element.setAttribute ("background-color", self.background_color.to_string()) self.element.setAttribute ("file", str(self.filename)) self.element.setAttribute ("image_width", str(self.width)) self.element.setAttribute ("image_height", str(self.height)) if self.am_selected: self.element.setAttribute ("current_root", "true") else: try: self.element.removeAttribute ("current_root") except xml.dom.NotFoundErr: pass if self.am_primary: self.element.setAttribute ("primary_root", "true") else: try: self.element.removeAttribute ("primary_root") except xml.dom.NotFoundErr: pass return def load (self, node): tmp = node.getAttribute ("ul-coords") self.ul = utils.parse_coords (tmp) tmp = node.getAttribute ("lr-coords") self.lr = utils.parse_coords (tmp) self.filename = node.getAttribute ("file") self.identity = int (node.getAttribute ("identity")) try: tmp = node.getAttribute ("background-color") self.background_color = gtk.gdk.color_parse(tmp) except ValueError: pass self.width = float(node.getAttribute ("image_width")) self.height = float(node.getAttribute ("image_height")) self.am_selected = node.hasAttribute ("current_root") self.am_primary = node.hasAttribute ("primary_root") for n in node.childNodes: if n.nodeName == "Extended": self.extended_buffer.load(n) else: print "Unknown: "+n.nodeName margin = utils.margin_required (utils.STYLE_NORMAL) self.pic_location = (self.ul[0]+margin[0], self.ul[1]+margin[1]) self.okay = self.open_image (self.filename) self.lr = (self.pic_location[0]+self.width+margin[2], self.pic_location[1]+self.height+margin[3]) if not self.okay: dialog = gtk.MessageDialog (None, gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_WARNING, gtk.BUTTONS_CLOSE, _("Error loading file")) dialog.format_secondary_text (_("%s could not be found. Associated thought will be empty."%self.filename)) dialog.run () dialog.hide () self.pic = None self.orig_pic = None else: self.pic = self.orig_pic.scale_simple (int(self.width), int(self.height), gtk.gdk.INTERP_HYPER) return def change_image_cb(self, widget): self.open_image() def get_popup_menu_items(self): image = gtk.Image() image.set_from_stock(gtk.STOCK_OPEN, gtk.ICON_SIZE_MENU) item = gtk.ImageMenuItem(_('Change Image')) item.set_image(image) item.connect('activate', self.change_image_cb) return [item] labyrinth-0.6/labyrinth_lib/Links.py000066400000000000000000000242731204476542500176500ustar00rootroot00000000000000# Link.py # This file is part of Labyrinth # # Copyright (C) 2006 - Don Scorgie # # Labyrinth 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. # # Labyrinth 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 Labyrinth; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, # Boston, MA 02110-1301 USA # import math import gettext _ = gettext.gettext import gobject import gtk import BaseThought import utils def norm(x, y): mod = math.sqrt(abs((x[0]**2 - y[0]**2) + (x[1]**2 - y[1]**2))) return [abs(x[0]-y[0]) / (mod), abs(x[1] - y[1]) / (mod)] class Link (gobject.GObject): __gsignals__ = dict (select_link = (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT,)), update_view = (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()), popup_requested = (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT, gobject.TYPE_INT))) def __init__ (self, save, parent = None, child = None, start_coords = None, end_coords = None, strength = 2): super (Link, self).__init__() self.parent = parent self.child = child self.end = end_coords self.start = start_coords self.strength = strength self.element = save.createElement ("link") self.selected = False self.color = utils.gtk_to_cairo_color(gtk.gdk.color_parse("black")) if not self.start and parent and parent.lr: self.start = (parent.ul[0]-((parent.ul[0]-parent.lr[0]) / 2.), \ parent.ul[1]-((parent.ul[1]-parent.lr[1]) / 2.)) if parent and child: self.find_ends () def get_save_element (self): return self.element def includes (self, coords, mode): # TODO: Change this to make link selection work. Also needs # some fairly large changes in MMapArea if not self.start or not self.end or not coords: return False mag = (math.sqrt(((self.end[0] - self.start[0]) ** 2) + \ ((self.end[1] - self.start[1]) ** 2))) U = (((coords[0] - self.start[0]) * (self.end[0] - self.start[0])) + \ ((coords[1] - self.start[1]) * (self.end[1] - self.start[1]))) / \ (mag**2) inter = [self.start[0] + U*(self.end[0] - self.start[0]), self.start[1] + U*(self.end[1] - self.start[1])] dist = math.sqrt(((coords[0] - inter[0]) ** 2) + \ ((coords[1] - inter[1]) ** 2)) if dist < (3+self.strength) and dist > -(3+self.strength): if self.start[0] < self.end[0] and coords[0] > self.start[0] and coords[0] < self.end[0]: return True elif coords[0] < self.start[0] and coords[0] > self.end[0]: return True return False def connects (self, thought, thought2): return (self.parent == thought and self.child == thought2) or \ (self.child == thought and self.parent == thought2) def set_end (self, coords): self.end = coords def set_strength (self, strength): self.strength = strength def change_strength (self, thought, thought2): if not self.connects (thought, thought2): return False if self.parent == thought: self.strength += 1 else: self.strength -= 1 return self.strength != 0 def set_child (self, child): self.child = child self.find_ends () def uses (self, thought): return self.parent == thought or self.child == thought def find_ends (self): (self.start, self.end) = self.parent.find_connection (self.child) def draw (self, context): if not self.start or not self.end: return cwidth = context.get_line_width () context.set_line_width (self.strength) context.move_to (self.start[0], self.start[1]) if utils.use_bezier_curves: dx = self.end[0] - self.start[0] x2 = self.start[0] + dx / 2.0 x3 = self.end[0] - dx / 2.0 context.curve_to(x2, self.start[1], x3, self.end[1], self.end[0], self.end[1]) else: context.line_to (self.end[0], self.end[1]) if self.selected: color = utils.selected_colors["bg"] context.set_source_rgb (color[0], color[1], color[2]) else: context.set_source_rgb (self.color[0], self.color[1], self.color[2]) context.stroke () context.set_line_width (cwidth) context.set_source_rgb (0.0, 0.0, 0.0) def export (self, context, move_x, move_y): rem = False if not self.start or not self.end: # Probably shouldn't do this, but its safe now self.start = (self.parent.ul[0]-((self.parent.ul[0]-self.parent.lr[0]) / 2.), \ self.parent.ul[1]-((self.parent.ul[1]-self.parent.lr[1]) / 2.)) self.end = (self.child.ul[0]-((self.child.ul[0]-self.child.lr[0]) / 2.), \ self.child.ul[1]-((self.child.ul[1]-self.child.lr[1]) / 2.)) rem = True cwidth = context.get_line_width () context.set_line_width (self.strength) context.move_to (self.start[0]+move_x, self.start[1]+move_y) context.line_to (self.end[0]+move_x, self.end[1]+move_y) context.stroke () context.set_line_width (cwidth) if rem: self.start = self.end = None def set_parent_child (self, parent, child): self.parent = parent self.child = child if self.parent and self.child: self.find_ends () def update_save (self): self.element.setAttribute ("start", str(self.start)) self.element.setAttribute ("end", str(self.end)) self.element.setAttribute ("strength", str(self.strength)) self.element.setAttribute ("color", str(self.color)) if self.child: self.element.setAttribute ("child", str(self.child.identity)) else: self.element.setAttribute ("child", "None") if self.parent: self.element.setAttribute ("parent", str(self.parent.identity)) else: self.element.setAttribute ("parent", "None") def load (self, node): self.parent_number = self.child_number = -1 tmp = node.getAttribute ("end") if not tmp: print "No tmp found" return self.end = utils.parse_coords (tmp) tmp = node.getAttribute ("start") if not tmp: print "No start found" return self.start = utils.parse_coords (tmp) self.strength = int(node.getAttribute ("strength")) try: colors = node.getAttribute ("color").split() self.color = (float(colors[0].strip('(,)')), float(colors[1].strip('(,)')), float(colors[2].strip('(,)'))) except: pass if node.hasAttribute ("parent"): tmp = node.getAttribute ("parent") if tmp == "None": self.parent_number = -1 else: self.parent_number = int (tmp) if node.hasAttribute ("child"): tmp = node.getAttribute ("child") if tmp == "None": self.child_number = -1 else: self.child_number = int (tmp) def process_button_down (self, event, mode, transformed): modifiers = gtk.accelerator_get_default_mod_mask () self.button_down = True if event.button == 1: if event.type == gtk.gdk.BUTTON_PRESS: self.emit ("select_link", event.state & modifiers) self.emit ("update_view") elif event.button == 3: self.emit ("popup_requested", event, 2) self.emit ("update_view") return False def process_button_release (self, event, unending_link, mode, transformed): return False def process_key_press (self, event, mode): if mode != BaseThought.MODE_EDITING or event.keyval == gtk.keysyms.Delete: return False if event.keyval == gtk.keysyms.plus or \ event.keyval == gtk.keysyms.KP_Add: self.strength += 1 elif (event.keyval == gtk.keysyms.minus or \ event.keyval == gtk.keysyms.KP_Subtract) and \ self.strength > 1: self.strength -= 1 elif event.keyval == gtk.keysyms.Escape: self.unselect() self.emit("update_view") return True def handle_motion (self, event, mode, transformed): pass def want_motion (self): return False def select(self): self.selected = True def unselect(self): self.selected = False def move_by (self, x,y): pass def can_be_parent (self): return False def set_color_cb(self, widget): dialog = gtk.ColorSelectionDialog(_('Choose Color')) dialog.connect('response', self.color_selection_ok_cb) self.color_sel = dialog.colorsel dialog.run() def color_selection_ok_cb(self, dialog, response_id): if response_id == gtk.RESPONSE_OK: self.color = utils.gtk_to_cairo_color(self.color_sel.get_current_color()) dialog.destroy() def get_popup_menu_items(self): image = gtk.Image() image.set_from_stock(gtk.STOCK_COLOR_PICKER, gtk.ICON_SIZE_MENU) item = gtk.ImageMenuItem(_('Set Color')) item.set_image(image) item.connect('activate', self.set_color_cb) return [item] labyrinth-0.6/labyrinth_lib/MMapArea.py000066400000000000000000001504241204476542500202110ustar00rootroot00000000000000#! /usr/bin/env python # MMapArea.py # This file is part of Labyrinth # # Copyright (C) 2006 - Don Scorgie # # Labyrinth 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. # # Labyrinth 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 Labyrinth; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, # Boston, MA 02110-1301 USA # import math import gtk import pango import gobject import gettext import copy _ = gettext.gettext import xml.dom.minidom as dom import Links import TextThought import ImageThought import DrawingThought import ResourceThought import UndoManager import utils RAD_UP = (- math.pi / 2.) RAD_DOWN = (math.pi / 2.) RAD_LEFT = (math.pi) RAD_RIGHT = (0) MODE_EDITING = 0 MODE_IMAGE = 1 MODE_DRAW = 2 MODE_RESOURCE = 3 # Until all references of MODE_MOVING are removed... MODE_MOVING = 999 VIEW_LINES = 0 VIEW_BEZIER = 1 TYPE_TEXT = 0 TYPE_IMAGE = 1 TYPE_DRAWING = 2 TYPE_RESOURCE = 3 # TODO: Need to expand to support popup menus MENU_EMPTY_SPACE = 0 # UNDO actions UNDO_MOVE = 0 UNDO_CREATE = 1 UNDO_DELETE = 2 UNDO_DELETE_SINGLE = 3 UNDO_COMBINE_DELETE_NEW = 4 UNDO_DELETE_LINK = 5 UNDO_STRENGTHEN_LINK = 6 UNDO_CREATE_LINK = 7 UNDO_ALIGN = 8 # Note: This is (atm) very broken. It will allow you to create new canvases, but not # create new thoughts or load existing maps. # To get it working either fix the TODO list at the bottom of the class, implement the # necessary features within all the thought types. If you do, please send a patch ;) # OR: Change this class to MMapAreaNew and MMapAreaOld to MMapArea class MMapArea (gtk.DrawingArea): '''A MindMapArea Widget. A blank canvas with a collection of child thoughts.\ It is responsible for processing signals and such from the whole area and \ passing these on to the correct child. It also informs things when to draw''' __gsignals__ = dict (title_changed = (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_STRING, )), doc_save = (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT)), doc_delete = (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ()), change_mode = (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_INT, )), change_buffer = (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_OBJECT, )), text_selection_changed = (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_INT, gobject.TYPE_INT, gobject.TYPE_STRING)), thought_selection_changed = (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT, gobject.TYPE_PYOBJECT)), set_focus = (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_PYOBJECT, gobject.TYPE_BOOLEAN)), set_attrs = (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_BOOLEAN, gobject.TYPE_BOOLEAN, gobject.TYPE_BOOLEAN, pango.FontDescription))) def __init__(self, undo): super (MMapArea, self).__init__() self.thoughts = [] self.links = [] self.selected = [] self.num_selected = 0 self.primary = None self.editing = None self.pango_context = self.create_pango_context() self.undo = undo self.scale_fac = 1.0 self.translate = False self.translation = [0.0,0.0] self.timeout = -1 self.current_cursor = None self.do_filter = True self.is_bbox_selecting = False self.unending_link = None self.nthoughts = 0 impl = dom.getDOMImplementation() self.save = impl.createDocument("http://www.donscorgie.blueyonder.co.uk/labns", "MMap", None) self.element = self.save.documentElement self.im_context = gtk.IMMulticontext () self.mode = MODE_EDITING self.old_mode = MODE_EDITING self.connect ("expose_event", self.expose) self.connect ("button_release_event", self.button_release) self.connect ("button_press_event", self.button_down) self.connect ("motion_notify_event", self.motion_event) self.connect ("key_press_event", self.key_press) self.connect ("key_release_event", self.key_release) self.connect ("scroll_event", self.scroll) self.commit_handler = None self.title_change_handler = None self.moving = False self.move_origin = None self.move_origin_new = None self.motion = None self.move_action = None self.current_root = [] self.rotation = 0 self.set_events (gtk.gdk.KEY_PRESS_MASK | gtk.gdk.KEY_RELEASE_MASK | gtk.gdk.BUTTON_PRESS_MASK | gtk.gdk.BUTTON_RELEASE_MASK | gtk.gdk.POINTER_MOTION_MASK | gtk.gdk.SCROLL_MASK) self.set_flags (gtk.CAN_FOCUS) # set theme colors w = gtk.Window() w.realize() style = w.get_style() self.pango_context.set_font_description(style.font_desc) self.font_name = style.font_desc.to_string() utils.default_font = self.font_name utils.default_colors["text"] = utils.gtk_to_cairo_color(style.text[gtk.STATE_NORMAL]) utils.default_colors["base"] = utils.gtk_to_cairo_color(style.base[gtk.STATE_NORMAL]) self.background_color = style.base[gtk.STATE_NORMAL] self.foreground_color = style.text[gtk.STATE_NORMAL] utils.default_colors["bg"] = utils.gtk_to_cairo_color(style.bg[gtk.STATE_NORMAL]) utils.default_colors["fg"] = utils.gtk_to_cairo_color(style.fg[gtk.STATE_NORMAL]) utils.selected_colors["text"] = utils.gtk_to_cairo_color(style.text[gtk.STATE_SELECTED]) utils.selected_colors["bg"] = utils.gtk_to_cairo_color(style.bg[gtk.STATE_SELECTED]) utils.selected_colors["fg"] = utils.gtk_to_cairo_color(style.fg[gtk.STATE_SELECTED]) utils.selected_colors["fill"] = utils.gtk_to_cairo_color(style.base[gtk.STATE_SELECTED]) def transform_coords(self, loc_x, loc_y): if hasattr(self, "transform"): return self.transform.transform_point(loc_x, loc_y) def untransform_coords(self, loc_x, loc_y): if hasattr(self, "untransform"): return self.untransform.transform_point(loc_x, loc_y) def button_down (self, widget, event): coords = self.transform_coords (event.get_coords()[0], event.get_coords()[1]) ret = False obj = self.find_object_at (coords) if event.button == 2: self.set_cursor (gtk.gdk.FLEUR) self.original_translation = self.translation self.origin_x = event.x self.origin_y = event.y return if obj and obj.want_motion (): self.motion = obj ret = obj.process_button_down (event, self.mode, coords) if event.button == 1 and self.mode == MODE_EDITING: self.moving = not (event.state & gtk.gdk.CONTROL_MASK) self.move_origin = (coords[0], coords[1]) self.move_origin_new = self.move_origin return ret if obj: if event.button == 1 and self.mode == MODE_EDITING: self.moving = not (event.state & gtk.gdk.CONTROL_MASK) self.move_origin = (coords[0], coords[1]) self.move_origin_new = self.move_origin ret = obj.process_button_down (event, self.mode, coords) elif event.button == 1 and self.mode == MODE_EDITING and not self.editing: self.bbox_origin = coords self.is_bbox_selecting = True elif event.button == 3: ret = self.create_popup_menu (None, event, MENU_EMPTY_SPACE) return ret def undo_move (self, action, mode): self.undo.block () move_thoughts = action.args[1] old_coords = action.args[0] new_coords = action.args[2] move_x = old_coords[0] - new_coords[0] move_y = old_coords[1] - new_coords[1] if mode == UndoManager.REDO: move_x = -move_x move_y = -move_y self.unselect_all () for t in move_thoughts: self.select_thought (t, -1) t.move_by (move_x, move_y) self.undo.unblock () self.invalidate ((old_coords[0], old_coords[1], new_coords[0], new_coords[1])) def button_release (self, widget, event): coords = self.transform_coords (event.get_coords()[0], event.get_coords()[1]) if self.mode == MODE_EDITING: self.set_cursor(gtk.gdk.LEFT_PTR) else: self.set_cursor(gtk.gdk.CROSSHAIR) ret = False if self.is_bbox_selecting: self.is_bbox_selecting = False self.invalidate () try: if abs(self.bbox_origin[0] - coords[0]) > 2.0: return True except AttributeError: # no bbox_current pass if self.translate: self.translate = False return True if self.moving and self.move_action: self.move_action.add_arg (coords) self.undo.add_undo (self.move_action) self.move_action = None self.motion = None self.moving = False self.move_origin = None obj = self.find_object_at (coords) if event.button == 2: self.undo.add_undo (UndoManager.UndoAction (self, UndoManager.TRANSFORM_CANVAS, self.undo_transform_cb, self.scale_fac, self.scale_fac, self.original_translation, self.translation)) if obj: ret = obj.process_button_release (event, self.unending_link, self.mode, coords) if len(self.selected) != 1: self.invalidate() # does not invalidate correctly with obj.get_max_area() return ret elif self.unending_link or event.button == 1: sel = self.selected thought = self.create_new_thought (coords) if not thought: return True if not self.primary: self.make_primary (thought) self.select_thought (thought, None) else: self.emit ("change_buffer", thought.extended_buffer) self.hookup_im_context (thought) # Creating links adds an undo action. Block it here self.undo.block () for x in self.current_root: self.create_link (x, None, thought) for x in self.selected: x.unselect () self.selected = [thought] thought.select () if self.unending_link: self.unending_link.set_child (thought) self.links.append (self.unending_link) element = self.unending_link.get_save_element () self.element.appendChild (element) self.unending_link = None self.undo.unblock () thought.foreground_color = self.foreground_color thought.background_color = self.background_color act = UndoManager.UndoAction (self, UNDO_CREATE, self.undo_create_cb, thought, sel, \ self.mode, self.old_mode, event.get_coords()) for l in self.links: if l.uses (thought): act.add_arg (l) if self.undo.peak ().undo_type == UNDO_DELETE_SINGLE: last_action = self.undo.pop () action = UndoManager.UndoAction (self, UNDO_COMBINE_DELETE_NEW, self.undo_joint_cb, \ last_action, act) self.undo.add_undo (action) else: self.undo.add_undo (act) self.begin_editing (thought) self.invalidate () return ret def undo_transform_cb (self, action, mode): if mode == UndoManager.UNDO: self.scale_fac = action.args[0] self.translation = action.args[2] else: self.scale_fac = action.args[1] self.translation = action.args[3] self.invalidate () def scroll (self, widget, event): scale = self.scale_fac if event.direction == gtk.gdk.SCROLL_UP: if self.scale_fac > 10: return # Limit zoom in to 10x self.scale_fac*=1.2 # Zoom based on where cursor is located. coords = self.transform_coords(event.x, event.y) geom = self.window.get_geometry() middle = self.transform_coords(geom[2]/2.0, geom[3]/2.0) # Without the /4.0, the window jumps to where the cursor is # centred, which is very awkward and hard to use. This method makes # the centre move smoothly towards the cursor's location. self.translation[0] -= (coords[0] - middle[0])/4.0 self.translation[1] -= (coords[1] - middle[1])/4.0 elif event.direction == gtk.gdk.SCROLL_DOWN: if self.scale_fac <= 0.1: return # Limit zoom out to 1/10th scale self.scale_fac/=1.2 self.undo.add_undo (UndoManager.UndoAction (self, UndoManager.TRANSFORM_CANVAS, \ self.undo_transform_cb, scale, self.scale_fac, self.translation, self.translation)) self.invalidate() def undo_joint_cb (self, action, mode): delete = action.args[0] create = action.args[1] if mode == UndoManager.UNDO: self.undo_create_cb (create, mode) self.undo_deletion (delete, mode) else: self.undo_deletion (delete, mode) self.undo_create_cb (create, mode) self.invalidate () def key_press (self, widget, event): if not self.do_filter or not self.im_context.filter_keypress (event): if self.editing: if not self.editing.process_key_press (event, self.mode): return self.global_key_handler (event) return True if len(self.selected) != 1 or not self.selected[0].process_key_press (event, self.mode): return self.global_key_handler (event) return True def key_release (self, widget, event): self.im_context.filter_keypress (event) return True def motion_event(self, widget, event): coords = self.transform_coords (event.get_coords()[0], event.get_coords()[1]) if self.motion: if self.motion.handle_motion (event, self.mode, coords): return True obj = self.find_object_at (coords) if self.unending_link and not self.is_bbox_selecting: self.unending_link.set_end (coords) self.invalidate () return True elif event.state & gtk.gdk.BUTTON1_MASK and self.is_bbox_selecting: self.bbox_current = coords self.invalidate() ul = [ self.bbox_origin[0], self.bbox_origin[1] ] lr = [ coords[0], coords[1] ] if self.bbox_origin[0] > coords[0]: if self.bbox_origin[1] < coords[1]: ul[0] = coords[0] ul[1] = self.bbox_origin[1] lr[0] = self.bbox_origin[0] lr[1] = coords[1] else: ul = coords lr = self.bbox_origin elif self.bbox_origin[1] > coords[1]: ul[0] = self.bbox_origin[0] ul[1] = coords[1] lr[0] = coords[0] lr[1] = self.bbox_origin[1] # FIXME: O(n) runtime is bad for t in self.thoughts: if t.lr[0] > ul[0] and t.ul[1] < lr[1] and t.ul[0] < lr[0] and t.lr[1] > ul[1] : if t not in self.selected: self.select_thought(t, gtk.gdk.SHIFT_MASK) else: if t in self.selected: t.unselect() self.selected.remove(t) return True elif self.moving and not self.editing and not self.unending_link: self.set_cursor(gtk.gdk.FLEUR) if not self.move_action: self.move_action = UndoManager.UndoAction (self, UNDO_MOVE, self.undo_move, self.move_origin, self.selected) for t in self.selected: t.move_by (coords[0] - self.move_origin_new[0], coords[1] - self.move_origin_new[1]) self.move_origin_new = (coords[0], coords[1]) self.invalidate () return True elif self.editing and event.state & gtk.gdk.BUTTON1_MASK and not obj and not self.is_bbox_selecting: # We were too quick with the movement. We really actually want to # create the unending link self.create_link (self.editing) self.finish_editing () elif event.state & gtk.gdk.BUTTON2_MASK: self.translate = True self.translation[0] -= (self.origin_x - event.x) / self.scale_fac self.translation[1] -= (self.origin_y - event.y) / self.scale_fac self.origin_x = event.x self.origin_y = event.y self.invalidate() return True if obj: obj.handle_motion (event, self.mode, coords) elif self.mode == MODE_IMAGE or self.mode == MODE_DRAW: self.set_cursor(gtk.gdk.CROSSHAIR) else: self.set_cursor(gtk.gdk.LEFT_PTR) def find_object_at (self, coords): for x in reversed(self.thoughts): if x.includes (coords, self.mode): return x for x in self.links: if x.includes (coords, self.mode): return x return None def realize_cb (self, widget): self.disconnect (self.realize_handle) if self.mode == MODE_IMAGE or self.mode == MODE_DRAW: self.set_cursor (gtk.gdk.CROSSHAIR) else: self.set_cursor (gtk.gdk.LEFT_PTR) return False def set_cursor(self, kind): new_cursor = CursorFactory().get_cursor(kind) if self.current_cursor != new_cursor: self.current_cursor = new_cursor self.window.set_cursor(self.current_cursor) def set_mode (self, mode): if mode == self.mode: return self.old_mode = self.mode self.mode = mode self.finish_editing () self.hookup_im_context () if self.window: if mode == MODE_IMAGE or mode == MODE_DRAW: self.set_cursor (gtk.gdk.CROSSHAIR) else: self.set_cursor (gtk.gdk.LEFT_PTR) else: self.realize_handle = self.connect ("realize", self.realize_cb) self.mode = mode if self.window: self.invalidate () def title_changed_cb (self, widget, new_title): self.emit ("title_changed", new_title) def make_primary (self, thought): if self.primary: print "Warning: Already have a primary root" if self.title_change_handler: self.primary.disconnect (self.title_change_handler) self.title_change_handler = thought.connect ("title_changed", self.title_changed_cb) self.emit ("title_changed", thought.text) self.primary = thought thought.make_primary () def hookup_im_context (self, thought = None): if self.commit_handler: self.im_context.disconnect (self.commit_handler) self.im_context.disconnect (self.delete_handler) self.im_context.disconnect (self.preedit_changed_handler) self.im_context.disconnect (self.preedit_end_handler) self.im_context.disconnect (self.preedit_start_handler) self.im_context.disconnect (self.retrieve_handler) self.commit_handler = None if thought: try: self.commit_handler = self.im_context.connect ("commit", thought.commit_text, self.mode, self.font_name) self.delete_handler = self.im_context.connect ("delete-surrounding", thought.delete_surroundings, self.mode) self.preedit_changed_handler = self.im_context.connect ("preedit-changed", thought.preedit_changed, self.mode) self.preedit_end_handler = self.im_context.connect ("preedit-end", thought.preedit_end, self.mode) self.preedit_start_handler = self.im_context.connect ("preedit-start", thought.preedit_start, self.mode) self.retrieve_handler = self.im_context.connect ("retrieve-surrounding", thought.retrieve_surroundings, \ self.mode) self.do_filter = True except AttributeError: self.do_filter = False else: self.do_filter = False def unselect_all (self): self.hookup_im_context () for t in self.selected: t.unselect () self.selected = [] def select_link (self, link, modifiers): if modifiers and modifiers & gtk.gdk.SHIFT_MASK and len (self.selected) > 1 and self.selected.count (link) > 0: self.selected.remove (link) link.unselect () return self.hookup_im_context() if self.editing: self.finish_editing () if modifiers and (modifiers & gtk.gdk.SHIFT_MASK or modifiers == -1): if self.selected.count (link) == 0: self.selected.append (link) else: for t in self.selected: t.unselect() self.selected = [link] link.select() self.emit("change_buffer", None) def select_thought (self, thought, modifiers): self.hookup_im_context () if self.editing: self.finish_editing () if thought in self.selected and self.moving: return if thought not in self.thoughts: self.thoughts.append(thought) if modifiers and (modifiers & gtk.gdk.SHIFT_MASK or modifiers == -1): if self.selected.count (thought) == 0: self.selected.append (thought) else: for x in self.selected: x.unselect() self.selected = [thought] self.current_root = [] for x in self.selected: if x.can_be_parent(): self.current_root.append(x) thought.select () if len(self.selected) == 1: self.emit ("thought_selection_changed", thought.background_color, thought.foreground_color) self.background_color = thought.background_color # Image thoughts don't have a foreground colour, so we shouldn't # copy it. if thought.foreground_color is not None: self.foreground_color = thought.foreground_color try: self.emit ("change_buffer", thought.extended_buffer) except AttributeError: self.emit ("change_buffer", None) self.hookup_im_context (thought) else: self.emit ("change_buffer", None) def begin_editing (self, thought): if self.editing and thought != self.editing: self.finish_editing () if thought.begin_editing (): self.editing = thought self.invalidate() def undo_link_action (self, action, mode): self.undo.block () if self.editing: self.finish_editing () link = action.args[0] if action.undo_type == UNDO_CREATE_LINK: if mode == UndoManager.REDO: self.element.appendChild (link.element) self.links.append (link) else: self.delete_link (link) elif action.undo_type == UNDO_DELETE_LINK: if mode == UndoManager.UNDO: self.element.appendChild (link.element) self.links.append (link) else: self.delete_link (link) elif action.undo_type == UNDO_STRENGTHEN_LINK: if mode == UndoManager.UNDO: link.set_strength (action.args[1]) else: link.set_strength (action.args[2]) self.undo.unblock () self.invalidate () def connect_link (self, link): link.connect ("select_link", self.select_link) link.connect ("update_view", self.update_view) link.connect ("popup_requested", self.create_popup_menu) def create_link (self, thought, thought_coords = None, child = None, child_coords = None, strength = 2): if child: for x in self.links: if x.connects (thought, child): if x.change_strength (thought, child): self.delete_link (x) return link = Links.Link (self.save, parent = thought, child = child, strength = strength) self.connect_link (link) element = link.get_save_element () self.element.appendChild (element) self.links.append (link) return link else: if self.unending_link: del self.unending_link self.unending_link = Links.Link (self.save, parent = thought, start_coords = thought_coords, end_coords = child_coords, strength = strength) def set_mouse_cursor_cb (self, thought, cursor_type): if not self.moving: self.set_cursor (cursor_type) def update_all_links(self): for l in self.links: l.find_ends() def update_links_cb (self, thought): for x in self.links: if x.uses (thought): x.find_ends () def claim_unending_link (self, thought): if not self.unending_link: return if self.unending_link.parent == thought: del self.unending_link self.unending_link = None return for x in self.links: if x.connects (self.unending_link.parent, thought): old_strength = x.strength x.change_strength (self.unending_link.parent, thought) new_strength = x.strength self.undo.add_undo (UndoManager.UndoAction (self, UNDO_STRENGTHEN_LINK, self.undo_link_action, x, \ old_strength, new_strength)) del self.unending_link self.unending_link = None return self.undo.add_undo (UndoManager.UndoAction (self, UNDO_CREATE_LINK, self.undo_link_action, self.unending_link)) self.unending_link.set_child (thought) self.links.append (self.unending_link) self.connect_link(self.unending_link) element = self.unending_link.get_save_element () self.element.appendChild (element) self.unending_link = None def create_popup_menu (self, thought, event, menu_type): menu = gtk.Menu() undo_item = gtk.ImageMenuItem(gtk.STOCK_UNDO) undo_item.connect('activate', self.undo.undo_action) undo_item.set_sensitive(self.undo.exists_undo_action()) redo_item = gtk.ImageMenuItem(gtk.STOCK_REDO) redo_item.connect('activate', self.undo.redo_action) redo_item.set_sensitive(self.undo.exists_redo_action()) sep_item = gtk.SeparatorMenuItem() menu.append(undo_item) menu.append(redo_item) menu.append(sep_item) undo_item.show() redo_item.show() sep_item.show() if thought: for item in thought.get_popup_menu_items(): menu.append(item) item.show() menu.popup(None, None, None, event.button, event.get_time()) def finish_editing (self, thought = None): if not self.editing or (thought and thought != self.editing): return self.editing.finish_editing () thought = self.editing self.editing = None def update_view (self, thought): if not self.editing: self.invalidate () else: x,y,w,h = thought.get_max_area() w += 10 h += 10 self.invalidate ((x,y,w,h)) def invalidate (self, transformed_area = None): '''Helper function to invalidate the entire screen, forcing a redraw''' rect = None if not transformed_area: alloc = self.get_allocation () rect = gtk.gdk.Rectangle (0, 0, alloc.width, alloc.height) else: ul = self.untransform_coords(transformed_area[0], transformed_area[1]) lr = self.untransform_coords(transformed_area[2], transformed_area[3]) rect = gtk.gdk.Rectangle (int(ul[0]), int(ul[1]), int(lr[0]-ul[0]), int(lr[1]-ul[1])) if self.window: self.window.invalidate_rect (rect, True) def expose (self, widget, event): '''Expose event. Calls the draw function''' context = self.window.cairo_create () self.draw (event, context) return False def draw (self, event, context): '''Draw the map and all the associated thoughts''' area = event.area context.rectangle (area.x, area.y, area.width, area.height) context.clip () context.set_source_rgb (1.0,1.0,1.0) context.move_to (area.x, area.y) context.paint () context.set_source_rgb (0.0,0.0,0.0) alloc = self.get_allocation () context.translate(alloc.width/2., alloc.height/2.) context.scale(self.scale_fac, self.scale_fac) context.translate(-alloc.width/2., -alloc.height/2.) context.translate(self.translation[0], self.translation[1]) for l in self.links: l.draw (context) if self.unending_link: self.unending_link.draw (context) self.untransform = context.get_matrix() self.transform = context.get_matrix() self.transform.invert() ax, ay = self.transform_coords(area.x, area.y) width = area.width / self.scale_fac height = area.height / self.scale_fac for t in self.thoughts: try: if max(t.ul[0],ax)<=min(t.lr[0],ax+width) and max(t.ul[1],ay)<=min(t.lr[1],ay+height): t.draw (context) except: t.draw(context) if self.is_bbox_selecting: xs = self.bbox_origin[0] ys = self.bbox_origin[1] xe = self.bbox_current[0] - xs ye = self.bbox_current[1] - ys xs,ys = context.user_to_device(xs, ys) xe,ye = context.user_to_device_distance(xe, ye) xs = int(xs) + 0.5 ys = int(ys) + 0.5 xe = int(xe) ye = int(ye) xs,ys = context.device_to_user(xs, ys) xe,ye = context.device_to_user_distance(xe, ye) color = utils.selected_colors["border"] context.set_line_width(1.0) context.set_source_rgb(color[0], color[1], color[2]) context.rectangle(xs, ys, xe, ye) context.stroke() color = utils.selected_colors["fill"] context.set_source_rgba(color[0], color[1], color[2], 0.3) context.rectangle(xs, ys, xe, ye) context.fill() context.set_line_width(2.0) context.set_source_rgba(0.0, 0.0, 0.0, 1.0) def undo_create_cb (self, action, mode): self.undo.block () if mode == UndoManager.UNDO: if action.args[0] == self.editing: self.editing = None self.unselect_all () for t in action.args[1]: self.select_thought (t, -1) self.delete_thought (action.args[0]) self.emit ("change_mode", action.args[3]) else: self.emit ("change_mode", action.args[2]) thought = action.args[0] self.thoughts.append (thought) for t in action.args[1]: self.unselect_all () self.select_thought (t, -1) self.hookup_im_context (thought) self.emit ("change_buffer", thought.extended_buffer) self.element.appendChild (thought.element) for l in action.args[5:]: self.links.append (l) self.element.appendChild (l.element) self.begin_editing (thought) self.emit ("set_focus", None, False) self.undo.unblock () self.invalidate () def create_new_thought (self, coords, thought_type = None, loading = False): if self.editing: self.editing.finish_editing () if thought_type != None: type = thought_type else: type = self.mode if type == TYPE_TEXT: thought = TextThought.TextThought (coords, self.pango_context, self.nthoughts, self.save, self.undo, loading, self.background_color, self.foreground_color) elif type == TYPE_IMAGE: thought = ImageThought.ImageThought (coords, self.pango_context, self.nthoughts, self.save, self.undo, loading, self.background_color) elif type == TYPE_DRAWING: thought = DrawingThought.DrawingThought (coords, self.pango_context, self.nthoughts, self.save, self.undo, \ loading,self.background_color, self.foreground_color) elif type == TYPE_RESOURCE: thought = ResourceThought.ResourceThought (coords, self.pango_context, self.nthoughts, self.save, self.undo, loading, self.background_color, self.foreground_color) if not thought.okay (): return None if type == TYPE_IMAGE: self.emit ("change_mode", self.old_mode) self.nthoughts += 1 self.element.appendChild (thought.element) thought.connect ("select_thought", self.select_thought) thought.connect ("begin_editing", self.begin_editing) thought.connect ("popup_requested", self.create_popup_menu) thought.connect ("create_link", self.create_link) thought.connect ("claim_unending_link", self.claim_unending_link) thought.connect ("update_view", self.update_view) thought.connect ("finish_editing", self.finish_editing) thought.connect ("delete_thought", self.delete_thought) thought.connect ("text_selection_changed", self.text_selection_cb) thought.connect ("change_mouse_cursor", self.set_mouse_cursor_cb) thought.connect ("update_links", self.update_links_cb) thought.connect ("grab_focus", self.regain_focus_cb) thought.connect ("update-attrs", self.update_attr_cb) self.thoughts.append (thought) return thought def regain_focus_cb (self, thought, ext): self.emit ("set_focus", None, ext) def update_attr_cb (self, widget, bold, italics, underline, pango_font): self.emit ("set_attrs", bold, italics, underline, pango_font) def delete_thought (self, thought): action = UndoManager.UndoAction (self, UNDO_DELETE_SINGLE, self.undo_deletion, [thought]) if thought.element in self.element.childNodes: self.element.removeChild (thought.element) self.thoughts.remove (thought) try: self.selected.remove (thought) except: pass if self.editing == thought: self.hookup_im_context () self.editing = None if self.primary == thought: thought.disconnect (self.title_change_handler) self.title_change_handler = None self.primary = None if self.thoughts: self.make_primary (self.thoughts[0]) rem_links = [] for l in self.links: if l.uses (thought): action.add_arg (l) rem_links.append (l) for l in rem_links: self.delete_link (l) self.undo.add_undo (action) return True def undo_deletion (self, action, mode): self.undo.block () if mode == UndoManager.UNDO: self.unselect_all () for l in action.args[1:]: self.links.append (l) self.element.appendChild (l.element) for t in action.args[0]: self.thoughts.append (t) self.select_thought (t, -1) self.element.appendChild (t.element) if action.undo_type == UNDO_DELETE_SINGLE: self.begin_editing (action.args[0][0]) self.emit ("change_buffer", action.args[0][0].extended_buffer) if not self.primary: self.make_primary (action.args[0][0]) else: self.emit ("change_buffer", None) else: for t in action.args[0]: self.delete_thought (t) for l in action.args[1:]: self.delete_link (l) self.emit ("set_focus", None, False) self.undo.unblock () self.invalidate () def delete_selected_elements (self): if len(self.selected) == 0: return action = UndoManager.UndoAction (self, UNDO_DELETE, self.undo_deletion, copy.copy(self.selected)) # delete_thought as a callback adds it's own undo action. Block that here self.undo.block () tmp = self.selected t = tmp.pop() while t: if t in self.thoughts: for l in self.links: if l.uses (t): action.add_arg (l) self.delete_thought (t) if t in self.links: self.delete_link (t) if len (tmp) == 0: t = None else: t = tmp.pop() self.undo.unblock () self.undo.add_undo (action) self.invalidate () def delete_link (self, link): if link.element in self.element.childNodes: self.element.removeChild (link.element) #link.element.unlink () self.links.remove (link) def popup_menu_key (self, event): print "Popup Menu Key" def find_related_thought (self, radians): # Find thought within angle best = None bestangle = 1000. bestdist = 10000. def do_find (one, two, currentangle, curdist, sensitivity): init_x = (one.ul[0] + one.lr[0]) / 2. init_y = (one.ul[1] + one.lr[1]) / 2. other_x = (two.ul[0] + two.lr[0]) / 2. other_y = (two.ul[1] + two.lr[1]) / 2. angle = math.atan2 ((other_y - init_y), (other_x - init_x)) while angle > math.pi: angle -= math.pi while angle < -math.pi: angle += math.pi # We have to special-case left due to stupidity of tan's # We shift it by pi radians if radians == RAD_LEFT: relangle = abs((angle+math.pi) - (radians+math.pi)) if relangle > math.pi*2.: relangle -= math.pi*2. else: relangle = abs(angle - radians) newdist = math.sqrt ((init_x - other_x)**2 + (init_y - other_y)**2) magicnum = newdist + (50. * relangle) # Used for debugging. Spits out lots of useful info # to determine interesting things about the thought relations #print "angle: "+str(angle)+" rel: "+str(magicnum)+" rads: "+str(radians), #print " , "+str(math.pi / 3.0)+" , "+str(currentangle)+"\n: "+str(relangle) if (relangle < sensitivity) and \ (magicnum < currentangle): return (magicnum, newdist) return (currentangle, curdist) if len(self.selected) != 1: return None initial = self.selected[0] for x in self.links: if x.parent == initial: other = x.child elif x.child == initial: other = x.parent else: continue (curr, dist) = do_find (initial, other, bestangle, bestdist, math.pi/3.) if curr < bestangle: bestangle = curr best = other bestdist = dist if not best: for x in self.thoughts: if x == self.selected[0]: continue (curr, dist) = do_find (initial, x, bestangle, bestdist, math.pi/4.) if curr < bestangle: best = x bestangle = curr bestdist = dist return best def undo_align(self, action, mode): self.undo.block () dic = action.args[0] if mode == UndoManager.UNDO: for t in dic: t.move_by(-dic[t][0], -dic[t][1]) else: for t in dic: t.move_by(dic[t][0], dic[t][1]) self.undo.unblock () def align_top_left(self, vertical=True): dic = {} if len(self.selected) != 0: x = self.selected[0].ul[0] y = self.selected[0].ul[1] for t in self.selected: if vertical: vec = (-(t.ul[0]-x), 0) else: vec = (0, -(t.ul[1]-y)) t.move_by(vec[0], vec[1]) dic[t] = vec self.undo.add_undo (UndoManager.UndoAction (self, UNDO_ALIGN, self.undo_align, dic)) def align_bottom_right(self, vertical=True): dic = {} if len(self.selected) != 0: x = self.selected[0].lr[0] y = self.selected[0].lr[1] for t in self.selected: if vertical: vec = (-(t.lr[0]-x), 0) else: vec = (0, -(t.lr[1]-y)) t.move_by(vec[0], vec[1]) dic[t] = vec self.undo.add_undo (UndoManager.UndoAction (self, UNDO_ALIGN, self.undo_align, dic)) def align_centered(self, vertical=True): dic = {} if len(self.selected) != 0: x = self.selected[0].ul[0] + (self.selected[0].lr[0] - self.selected[0].ul[0]) / 2.0 y = self.selected[0].ul[1] + (self.selected[0].lr[1] - self.selected[0].ul[1]) / 2.0 for t in self.selected: if vertical: vec = (-((t.ul[0] + (t.lr[0]-t.ul[0])/2.0)-x), 0) else: vec = (0, -((t.ul[1] + (t.lr[1]-t.ul[1])/2.0)-y)) t.move_by(vec[0], vec[1]) dic[t] = vec self.undo.add_undo (UndoManager.UndoAction (self, UNDO_ALIGN, self.undo_align, dic)) def global_key_handler (self, event): thought = None if event.keyval == gtk.keysyms.Up: thought = self.find_related_thought (RAD_UP) elif event.keyval == gtk.keysyms.Down: thought = self.find_related_thought (RAD_DOWN) elif event.keyval == gtk.keysyms.Left: thought = self.find_related_thought (RAD_LEFT) elif event.keyval == gtk.keysyms.Right: thought = self.find_related_thought (RAD_RIGHT) elif event.keyval == gtk.keysyms.Delete: self.delete_selected_elements () elif event.keyval == gtk.keysyms.BackSpace: self.delete_selected_elements () elif event.keyval == gtk.keysyms.Menu: self.popup_menu_key (event) elif event.keyval == gtk.keysyms.Escape: self.unselect_all () elif event.keyval == gtk.keysyms.a and event.state & gtk.gdk.CONTROL_MASK: self.unselect_all () for t in self.thoughts: t.select () self.selected.append (t) else: return False if thought: self.select_thought (thought, None) self.invalidate () return True def load_thought (self, node, type): thought = self.create_new_thought (None, type, loading = True) thought.load (node) def load_link (self, node): link = Links.Link (self.save) self.connect_link (link) link.load (node) self.links.append (link) element = link.get_save_element () self.element.appendChild (element) def load_thyself (self, top_element, doc): for node in top_element.childNodes: if node.nodeName == "thought": self.load_thought (node, TYPE_TEXT) elif node.nodeName == "image_thought": self.load_thought (node, TYPE_IMAGE) elif node.nodeName == "drawing_thought": self.load_thought (node, TYPE_DRAWING) elif node.nodeName == "res_thought": self.load_thought (node, TYPE_RESOURCE) elif node.nodeName == "link": self.load_link (node) else: print "Warning: Unknown element type. Ignoring: "+node.nodeName self.finish_loading () def finish_loading (self): # Possible TODO: This all assumes we've been given a proper, # consistant file. It should fallback nicely, but... # First, find the primary root: for t in self.thoughts: if t.am_primary: self.make_primary (t) if t.am_selected: self.selected.append (t) t.select () if t.editing: self.begin_editing (t) if t.identity >= self.nthoughts: self.nthoughts = t.identity + 1 if self.selected: self.current_root = self.selected else: self.current_root = [self.primary] if len(self.selected) == 1: self.emit ("change_buffer", self.selected[0].extended_buffer) self.hookup_im_context (self.selected[0]) self.emit ("thought_selection_changed", self.selected[0].background_color, \ self.selected[0].foreground_color) else: self.emit ("change_buffer", None) del_links = [] for l in self.links: if (l.parent_number == -1 and l.child_number == -1) or \ (l.parent_number == l.child_number): del_links.append (l) continue parent = child = None for t in self.thoughts: if t.identity == l.parent_number: parent = t elif t.identity == l.child_number: child = t if parent and child: break l.set_parent_child (parent, child) if not l.parent or not l.child: del_links.append (l) for l in del_links: self.delete_link (l) def prepare_save(self): for t in self.thoughts: t.update_save () for l in self.links: l.update_save () def save_thyself (self): self.prepare_save() if len(self.thoughts) > 0: self.emit ("doc_save", self.save, self.element) else: self.emit ("doc_delete") def text_selection_cb (self, thought, start, end, text): self.emit ("text_selection_changed", start, end, text) def copy_clipboard (self, clip): if len (self.selected) != 1: return self.selected[0].copy_text (clip) def cut_clipboard (self, clip): if len (self.selected) != 1: return self.selected[0].cut_text (clip) def paste_clipboard (self, clip): if len (self.selected) != 1: return self.selected[0].paste_text (clip) def export (self, context, width, height, native): context.rectangle (0, 0, width, height) context.clip () context.set_source_rgb (1.0,1.0,1.0) context.move_to (0,0) context.paint () context.set_source_rgb (0.0,0.0,0.0) if not native: move_x = self.move_x move_y = self.move_y else: move_x = 0 move_y = 0 for l in self.links: l.export (context, move_x, move_y) for t in self.thoughts: t.export (context, move_x, move_y) def get_max_area (self): minx = 999 maxx = -999 miny = 999 maxy = -999 for t in self.thoughts: mx,my,mmx,mmy = t.get_max_area () if mx < minx: minx = mx if my < miny: miny = my if mmx > maxx: maxx = mmx if mmy > maxy: maxy = mmy # Add a 10px border around all self.move_x = 10-minx self.move_y = 10-miny maxx = maxx-minx+20 maxy = maxy-miny+20 return (maxx,maxy) def get_selection_bounds (self): if len (self.selected) == 1: try: return self.selected[0].index, self.selected[0].end_index except AttributeError: return None, None else: return None, None def thoughts_are_linked (self): if len (self.selected) != 2: return False for l in self.links: if l.connects (self.selected[0], self.selected[1]): return True return False def link_menu_cb (self): if len (self.selected) != 2: return lnk = None for l in self.links: if l.connects (self.selected[0], self.selected[1]): lnk = l break if lnk: self.undo.add_undo (UndoManager.UndoAction (self, UNDO_DELETE_LINK, self.undo_link_action, lnk)) self.delete_link (lnk) else: lnk = self.create_link (self.selected[0], None, self.selected[1]) self.undo.add_undo (UndoManager.UndoAction (self, UNDO_CREATE_LINK, self.undo_link_action, lnk)) self.invalidate () def set_bold (self, active): if len(self.selected) != 1: return self.selected[0].set_bold (active) self.invalidate() def set_italics (self, active): if len(self.selected) != 1: return self.selected[0].set_italics (active) self.invalidate() def set_underline (self, active): if len(self.selected) != 1: return self.selected[0].set_underline (active) self.invalidate() def set_background_color(self, color): for s in self.selected: s.background_color = color self.background_color = color if len(self.selected) > 1: self.invalidate() def set_foreground_color(self, color): for s in self.selected: s.foreground_color = color self.foreground_color = color if len(self.selected) > 1: self.invalidate() def set_font(self, font_name): if len (self.selected) == 1 and hasattr(self.selected[0], "set_font"): self.selected[0].set_font(font_name) self.font_name = font_name self.invalidate() class CursorFactory: # Shared state cursors = {} def get_cursor(self, cur_type): if cur_type not in self.cursors: self.cursors[cur_type] = gtk.gdk.Cursor(cur_type) return self.cursors[cur_type] labyrinth-0.6/labyrinth_lib/MainWindow.py000066400000000000000000000773311204476542500206470ustar00rootroot00000000000000# MainWindow.py # This file is part of Labyrinth # # Copyright (C) 2006 - Don Scorgie # # Labyrinth 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. # # Labyrinth 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 Labyrinth; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, # Boston, MA 02110-1301 USA # # Standard library import hashlib import os import tarfile import gettext _ = gettext.gettext import xml.dom.minidom as dom # Gtk stuff import gtk import cairo, pangocairo import gobject if os.name != 'nt': import gconf # Local imports import MMapArea import UndoManager import PeriodicSaveThread import ImageThought import utils # UNDO varieties for us UNDO_MODE = 0 UNDO_SHOW_EXTENDED = 1 class LabyrinthWindow (gobject.GObject): __gsignals__ = dict (title_changed = (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_STRING, gobject.TYPE_OBJECT)), doc_save = (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_STRING, gobject.TYPE_OBJECT)), file_saved = (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_STRING, gobject.TYPE_OBJECT)), window_closed = (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, (gobject.TYPE_OBJECT, ))) def __init__ (self, filename, imported=False): super(LabyrinthWindow, self).__init__() # FIXME: This can go when we move entirely to gtk 2.10 # pygtk 2.8 doesn't have the correct function :( self.set_val = gtk.gtk_version[1] > 8 # First, construct the MainArea and connect it all up self.undo = UndoManager.UndoManager (self) self.undo.block () self.MainArea = MMapArea.MMapArea (self.undo) self.MainArea.connect ("title_changed", self.title_changed_cb) self.MainArea.connect ("doc_save", self.doc_save_cb) self.MainArea.connect ("doc_delete", self.doc_del_cb) self.MainArea.connect ("change_mode", self.mode_request_cb) self.MainArea.connect ("button-press-event", self.main_area_focus_cb) self.MainArea.connect ("change_buffer", self.switch_buffer_cb) self.MainArea.connect ("thought_selection_changed", self.thought_selected_cb) self.MainArea.connect ("set_focus", self.main_area_focus_cb) self.MainArea.connect ("set_attrs", self.attrs_cb) if os.name != 'nt': self.MainArea.connect ("text_selection_changed", self.selection_changed_cb) self.config_client = gconf.client_get_default() glade = gtk.glade.XML(utils.get_data_file_name('labyrinth.glade')) self.main_window = glade.get_widget ('MapWindow') self.main_window.set_focus_child (self.MainArea) if os.name != 'nt': try: self.main_window.set_icon_name ('labyrinth') except: self.main_window.set_icon_from_file(utils.get_data_file_name('labyrinth.svg')) else: self.main_window.set_icon_from_file('images\\labyrinth-24.png') # insert menu, toolbar and map self.create_menu() glade.get_widget ('main_area_insertion').pack_start(self.MainArea) vbox = glade.get_widget ('map_window_vbox') menubar = self.ui.get_widget('/MenuBar') menubar.show_all() vbox.pack_start(menubar) vbox.reorder_child(menubar, 0) vbox.set_child_packing(menubar, 0, 0, 0, gtk.PACK_START) toolbar = self.ui.get_widget('/ToolBar') toolbar.show_all() vbox.pack_start(toolbar) vbox.reorder_child(toolbar, 1) vbox.set_child_packing(toolbar, 0, 0, 0, gtk.PACK_START) # TODO: Bold, Italics etc. self.bold_widget = glade.get_widget('tool_bold') self.bold_widget.connect('toggled', self.bold_toggled) self.bold_block = False self.bold_state = False self.italic_widget = glade.get_widget('tool_italic') self.italic_widget.connect('toggled', self.italic_toggled) self.italic_block = False self.italic_state = False self.underline_widget = glade.get_widget('tool_underline') self.underline_widget.connect('toggled', self.underline_toggled) self.underline_block = False self.underline_state = False self.font_widget = glade.get_widget('font_button') self.font_widget.connect ("font-set", self.font_change_cb) self.background_widget = glade.get_widget('background_color_button') self.background_widget.connect ("color-set", self.background_change_cb) self.foreground_widget = glade.get_widget('foreground_color_button') self.foreground_widget.connect ("color-set", self.foreground_change_cb) self.cut = self.ui.get_widget ('/MenuBar/EditMenu/Cut') self.copy = self.ui.get_widget ('/MenuBar/EditMenu/Copy') self.paste = self.ui.get_widget ('/MenuBar/EditMenu/Paste') self.link = self.ui.get_widget ('/MenuBar/EditMenu/LinkThoughts') self.delete = self.ui.get_widget ('/MenuBar/EditMenu/DeleteNodes') self.ui.get_widget('/MenuBar/EditMenu').connect ('activate', self.edit_activated_cb) self.cut.set_sensitive (False) self.copy.set_sensitive (False) # get toolbars and activate corresponding menu entries self.main_toolbar = self.ui.get_widget ('/ToolBar') self.format_toolbar = glade.get_widget ('format_toolbar') self.ui.get_widget('/MenuBar/ViewMenu/ShowToolbars/ShowMainToolbar').set_active(True) self.ui.get_widget('/MenuBar/ViewMenu/ShowToolbars/ShowFormatToolbar').set_active(True) self.ui.get_widget('/MenuBar/ViewMenu/UseBezier').set_active(utils.use_bezier_curves) # Add in the extended info view self.extended_window = glade.get_widget('extended_window') self.extended = glade.get_widget('extended') self.invisible_buffer = gtk.TextBuffer () # Connect all our signals self.main_window.connect ("configure_event", self.configure_cb) self.main_window.connect ("window-state-event", self.window_state_cb) self.main_window.connect ("destroy", self.close_window_cb) # Deal with loading the map if not filename: self.MainArea.set_size_request (400, 400) # TODO: This shouldn't be set to a hard-coded number. Fix. self.pane_pos = 500 self.title_cp = _("Untitled Map") self.mode = MMapArea.MODE_EDITING self.extended_visible = False else: self.parse_file (filename) up_box = glade.get_widget('up_box') up_box.connect("button-press-event", self.translate, "Up") up_box.connect("button-release-event", self.finish_translate) down_box = glade.get_widget('down_box') down_box.connect("button-press-event", self.translate, "Down") down_box.connect("button-release-event", self.finish_translate) right_box = glade.get_widget('right_box') right_box.connect("button-press-event", self.translate, "Right") right_box.connect("button-release-event", self.finish_translate) left_box = glade.get_widget('left_box') left_box.connect("button-press-event", self.translate, "Left") left_box.connect("button-release-event", self.finish_translate) panes = glade.get_widget('vpaned1') panes.connect ("button-release-event", self.pos_changed) panes.set_position (self.pane_pos) # Other stuff self.width, self.height = self.main_window.get_size () # if we import, we dump the old filename to create a new hashed one self.save_file = None if not imported: self.save_file = filename self.maximised = False self.view_type = 0 if self.set_val: self.act.set_current_value (self.mode) self.undo.unblock () self.start_timer () def show(self): self.main_window.show_all() self.ext_act.set_active(self.extended_visible) if not self.extended_visible: self.extended_window.hide() def create_menu (self): actions = [ ('FileMenu', None, _('File')), ('Export', None, _('Export as Image'), None, _("Export your map as an image"), self.export_cb), ('ExportMap', gtk.STOCK_SAVE_AS, _('Export Map...'), 'S', _("Export your map as XML"), self.export_map_cb), ('Close', gtk.STOCK_CLOSE, None, 'W', _('Close the current window'), self.close_window_cb), ('EditMenu', None, _('_Edit')), ('ViewMenu', None, _('_View')), ('ShowToolbars', None, _('_Toolbar')), ('Undo', gtk.STOCK_UNDO, None, 'Z', None), ('Redo', gtk.STOCK_REDO, None, 'Z', None), ('Cut', gtk.STOCK_CUT, None, 'X', None, self.cut_text_cb), ('Copy', gtk.STOCK_COPY, None, 'C', None, self.copy_text_cb), ('Paste', gtk.STOCK_PASTE, None, 'V', None, self.paste_text_cb), ('LinkThoughts', None, _("Link Thoughts"), 'L', _("Link the selected thoughts"), self.link_thoughts_cb), ('ModeMenu', None, _('_Mode')), ('ZoomIn', gtk.STOCK_ZOOM_IN, None, 'plus', None, self.zoomin_cb), ('ZoomOut', gtk.STOCK_ZOOM_OUT, None, 'minus', None, self.zoomout_cb), ('Zoom100', gtk.STOCK_ZOOM_100, None, '0', None, self.zoom100_cb)] self.radio_actions = [ ('Edit', gtk.STOCK_EDIT, _('_Edit Mode'), 'E', _('Turn on edit mode'), MMapArea.MODE_EDITING), ('AddImage', gtk.STOCK_ADD, _('_Add Image'), None, _('Add an image to selected thought'), MMapArea.MODE_IMAGE), ('Drawing', gtk.STOCK_COLOR_PICKER, _('_Drawing Mode'), None, _('Make a pretty drawing'), MMapArea.MODE_DRAW)] self.view_radio_actions = [ ('UseBezier', None, _('Use _Curves'), None, _('Use curves as links'), MMapArea.VIEW_BEZIER), ('UseLines', None, _('Use _Lines'), None, _('Use straight lines as links'), MMapArea.VIEW_LINES)] self.toggle_actions = [ ('ViewExtend', None, _('_Extended Information'), None, _('Show extended information for thoughts'), self.view_extend_cb), ('ShowMainToolbar', None, _('_Main'), None, _('Show main toolbar'), self.show_main_toolbar_cb), ('ShowFormatToolbar', None, _('_Format'), None, _('Show format toolbar'), self.show_format_toolbar_cb)] ag = gtk.ActionGroup ('WindowActions') ag.set_translation_domain(gettext.textdomain()) ag.add_actions (actions) ag.add_radio_actions (self.radio_actions) ag.add_radio_actions (self.view_radio_actions) ag.add_toggle_actions (self.toggle_actions) self.act = ag.get_action ('Edit') self.ext_act = ag.get_action ('ViewExtend') self.act.connect ("changed", self.mode_change_cb) self.undo.set_widgets (ag.get_action ('Undo'), ag.get_action ('Redo')) self.view_action = ag.get_action('UseBezier') self.view_action.connect ("changed", self.view_change_cb) self.ui = gtk.UIManager () self.ui.insert_action_group (ag, 0) self.ui.add_ui_from_file (utils.get_data_file_name('labyrinth-ui.xml')) self.main_window.add_accel_group (self.ui.get_accel_group ()) def align_cb(self, widget, direction): if direction == "vl" or direction == "ht": self.MainArea.align_top_left(direction == "vl") elif direction == "vr" or direction == "hb": self.MainArea.align_bottom_right(direction == "vr") else: self.MainArea.align_centered(direction == "vc") if widget != self.align_button: self.align_button.disconnect(self.align_handler_id) self.align_handler_id = self.align_button.connect('clicked', self.align_cb, direction) self.align_button.set_icon_name(widget.get_image().get_icon_name()[0]) def link_thoughts_cb (self, arg): self.MainArea.link_menu_cb () def undo_show_extended (self, action, mode): self.undo.block () self.ext_act.set_active (not self.ext_act.get_active ()) self.undo.unblock () def view_extend_cb (self, arg): self.undo.add_undo (UndoManager.UndoAction (self, UNDO_SHOW_EXTENDED, self.undo_show_extended)) self.extended_visible = arg.get_active () if self.extended_visible: self.extended_window.show () self.view_type = 1 else: self.extended_window.hide () self.view_type = 0 def show_main_toolbar_cb(self, arg): if arg.get_active(): self.main_toolbar.show() else: self.main_toolbar.hide() def show_format_toolbar_cb(self, arg): if arg.get_active(): self.format_toolbar.show() else: self.format_toolbar.hide() def view_change_cb(self, base, activated): utils.use_bezier_curves = activated.get_current_value() == MMapArea.VIEW_BEZIER if os.name != 'nt': self.config_client.set_bool('/apps/labyrinth/curves', utils.use_bezier_curves) self.MainArea.update_all_links() self.MainArea.invalidate() def attrs_cb (self, widget, bold, italics, underline, pango_font): # Yes, there is a block method for signals # but I don't currently know how to # implement it for action-based signals # without messyness if bold != self.bold_state: self.bold_block = True self.bold_widget.set_active(bold) if italics != self.italic_state: self.italic_block = True self.italic_widget.set_active(italics) if underline != self.underline_state: self.underline_block = True self.underline_widget.set_active(underline) if pango_font: font_name = pango_font.to_string() self.font_widget.set_font_name (font_name) self.MainArea.set_font(font_name) else: self.font_widget.set_font_name (utils.default_font) def translate (self, box, arg1, direction): self.orig_translate = [self.MainArea.translation[0], self.MainArea.translation[1]] if direction == "Up": translation_x = 0 translation_y = 5 elif direction == "Down": translation_x = 0 translation_y = -5 elif direction == "Right": translation_x = -5 translation_y = 0 elif direction == "Left": translation_x = 5 translation_y = 0 else: print "Error" return gobject.timeout_add (20, self.translate_timeout, translation_x, translation_y) self.tr_to = True def translate_timeout (self, addition_x, addition_y): if not self.tr_to: return False self.MainArea.translation[0] += addition_x / self.MainArea.scale_fac self.MainArea.translation[1] += addition_y / self.MainArea.scale_fac self.MainArea.invalidate() return self.tr_to def finish_translate (self, box, arg1): self.undo.add_undo (UndoManager.UndoAction (self.MainArea, UndoManager.TRANSFORM_CANVAS, \ self.MainArea.undo_transform_cb, self.MainArea.scale_fac, self.MainArea.scale_fac, self.orig_translate, self.MainArea.translation)) self.tr_to = False def pos_changed (self, panes, arg2): self.pane_pos = panes.get_position () def bold_toggled (self, action): self.bold_state = (not self.bold_state) if self.bold_block: self.bold_block = False return if self.extended.is_focus (): self.extended.get_buffer().set_bold(action.get_active()) else: self.MainArea.set_bold (action.get_active()) def italic_toggled (self, action): self.italic_state = (not self.italic_state) if self.italic_block: self.italic_block = False return if self.extended.is_focus (): self.extended.get_buffer().set_italics(action.get_active()) else: self.MainArea.set_italics (action.get_active()) def underline_toggled (self, action): self.underline_state = (not self.underline_state) if self.underline_block: self.underline_block = False return if self.extended.is_focus (): self.extended.get_buffer().set_underline(action.get_active()) else: self.MainArea.set_underline (action.get_active()) def foreground_change_cb (self, button): if not self.extended.is_focus (): self.MainArea.set_foreground_color (button.get_color()) def background_change_cb (self, button): if not self.extended.is_focus (): self.MainArea.set_background_color (button.get_color()) def font_change_cb (self, button): if not self.extended.is_focus (): self.MainArea.set_font (button.get_font_name ()) def zoomin_cb(self, arg): if self.MainArea.scale_fac < 10: self.MainArea.scale_fac *= 1.2 self.MainArea.invalidate() def zoomout_cb(self, arg): if self.MainArea.scale_fac > 0.1: self.MainArea.scale_fac /= 1.2 self.MainArea.invalidate() def zoom100_cb(self, arg): self.MainArea.scale_fac = 1.0 self.MainArea.translation = [0.0, 0.0] self.MainArea.invalidate() def switch_buffer_cb (self, arg, new_buffer): if new_buffer: self.extended.set_editable (True) self.extended.set_buffer (new_buffer) else: self.extended.set_buffer (self.invisible_buffer) self.extended.set_editable (False) def thought_selected_cb (self, arg, background_color, foreground_color): if background_color: self.background_widget.set_color(background_color) if foreground_color: self.foreground_widget.set_color(foreground_color) def main_area_focus_cb (self, arg, event, extended = False): if not extended: self.MainArea.grab_focus () else: self.extended.grab_focus () def revert_mode (self, action, mode): self.undo.block () if mode == UndoManager.UNDO: self.mode_request_cb (None, action.args[0]) else: self.mode_request_cb (None, action.args[1]) self.undo.unblock () def mode_change_cb (self, base, activated): self.MainArea.set_mode (activated.get_current_value ()) self.mode = activated.get_current_value () def mode_request_cb (self, widget, mode): if self.set_val: self.act.set_current_value (mode) def title_changed_cb (self, widget, new_title): self.title_cp = self.title_cp = _('Untitled Map') if new_title != '': split = new_title.splitlines () self.title_cp = reduce(lambda x,y : x + ' ' + y, split) if len(self.title_cp) > 27: x = self.title_cp[:27] + "..." self.emit ("title-changed", x, self) else: self.emit ("title-changed", self.title_cp, self) self.main_window.set_title (self.title_cp) def delete_cb (self, event): self.MainArea.delete_selected_elements () def close_window_cb (self, event): self.SaveTimer.cancel = True self.main_window.hide () self.MainArea.save_thyself () del (self) def doc_del_cb (self, widget): self.emit ('window_closed', None) def serialize_to_xml(self, doc, top_element): top_element.setAttribute ("title", self.title_cp) top_element.setAttribute ("mode", str(self.mode)) top_element.setAttribute ("size", str((self.width,self.height))) top_element.setAttribute ("position", str((self.xpos,self.ypos))) top_element.setAttribute ("maximised", str(self.maximised)) top_element.setAttribute ("view_type", str(self.view_type)) top_element.setAttribute ("pane_position", str(self.pane_pos)) top_element.setAttribute ("scale_factor", str(self.MainArea.scale_fac)) top_element.setAttribute ("translation", str(self.MainArea.translation)) string = doc.toxml () return string.encode ("utf-8" ) def doc_save_cb (self, widget, doc, top_element): save_string = self.serialize_to_xml(doc, top_element) if not self.save_file: hsh = hashlib.sha256 (save_string) save_loc = utils.get_save_dir () self.save_file = os.path.join (save_loc, hsh.hexdigest() + ".map") counter = 1 while os.path.exists(self.save_file): print "Warning: Duplicate File. Saving to alternative" alt_name = "Dup" + str(counter) + hsh.hexdigest() + ".map" self.save_file = save_loc + os.path.join (save_loc, alt_name) counter += 1 with open(self.save_file, 'w') as f: f.write(save_string) self.emit ('file_saved', self.save_file, self) def export_map_cb(self, event): chooser = gtk.FileChooserDialog(title=_("Save File As"), action=gtk.FILE_CHOOSER_ACTION_SAVE, \ buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK)) chooser.set_current_name ("%s.mapz" % self.main_window.title) response = chooser.run() if response == gtk.RESPONSE_OK: filename = chooser.get_filename () self.MainArea.save_thyself () tf = tarfile.open (filename, "w") tf.add (self.save_file, os.path.basename(self.save_file)) for t in self.MainArea.thoughts: if isinstance(t, ImageThought.ImageThought): tf.add (t.filename, 'images/' + os.path.basename(t.filename)) tf.close() chooser.destroy() def parse_file (self, filename): with open(filename, 'r') as f: doc = dom.parse(f) top_element = doc.documentElement self.title_cp = top_element.getAttribute ("title") self.mode = int (top_element.getAttribute ("mode")) if top_element.hasAttribute ("maximised"): maxi = top_element.getAttribute ("maximised") else: maxi = False if maxi == "True": self.main_window.maximize () if top_element.hasAttribute ("pane_position"): self.pane_pos = int (top_element.getAttribute ("pane_position")) else: self.pane_pos = 500 if top_element.hasAttribute ("view_type"): vt = int (top_element.getAttribute ("view_type")) else: vt = 0 self.extended_visible = vt == 1 tmp = top_element.getAttribute ("size") (width, height) = utils.parse_coords (tmp) tmp = top_element.getAttribute ("position") (x, y) = utils.parse_coords (tmp) self.main_window.resize (int (width), int (height)) # Don't know why, but metacity seems to move the window 24 pixels # further down than requested. Compensate by removing 24 # pixels from the stored size y -= 24 self.main_window.move (int (x), int (y)) self.MainArea.set_mode (self.mode) self.MainArea.load_thyself (top_element, doc) if top_element.hasAttribute("scale_factor"): self.MainArea.scale_fac = float (top_element.getAttribute ("scale_factor")) if top_element.hasAttribute("translation"): tmp = top_element.getAttribute("translation") (x,y) = utils.parse_coords(tmp) self.MainArea.translation = [x,y] def configure_cb (self, window, event): self.xpos = event.x self.ypos = event.y self.width = event.width self.height = event.height return False def window_state_cb (self, window, event): if event.changed_mask & gtk.gdk.WINDOW_STATE_MAXIMIZED: self.maximised = not self.maximised def toggle_range (self, arg, native_width, native_height, max_width, max_height): if arg.get_active (): self.spin_width.set_value (max_width) self.spin_height.set_value (max_height) # TODO: Fix this (and below) to cope with non-native resolutions properly #self.spin_width.set_sensitive (True) #self.spin_height.set_sensitive (True) else: #self.spin_width.set_sensitive (False) #self.spin_height.set_sensitive (False) self.spin_width.set_value (native_width) self.spin_height.set_value (native_height) def export_cb (self, event): maxx, maxy = self.MainArea.get_max_area () x, y, width, height, bitdepth = self.MainArea.window.get_geometry () glade = gtk.glade.XML (utils.get_data_file_name('labyrinth.glade')) dialog = glade.get_widget ('ExportImageDialog') box = glade.get_widget ('dialog_insertion') fc = gtk.FileChooserWidget(gtk.FILE_CHOOSER_ACTION_SAVE) box.pack_end (fc) filter_mapping = [ (_('All Files'), ['*']), (_('PNG Image (*.png)'), ['*.png']), (_('JPEG Image (*.jpg, *.jpeg)'), ['*.jpeg', '*.jpg']), (_('SVG Vector Image (*.svg)'), ['*.svg']), (_('PDF Portable Document (*.pdf)'), ['*.pdf']) ] for (filter_name, filter_patterns) in filter_mapping: fil = gtk.FileFilter () fil.set_name(filter_name) for pattern in filter_patterns: fil.add_pattern(pattern) fc.add_filter(fil) fc.set_current_name ("%s.png" % self.main_window.title) rad = glade.get_widget ('rb_complete_map') rad2 = glade.get_widget ('rb_visible_area') self.spin_width = glade.get_widget ('width_spin') self.spin_height = glade.get_widget ('height_spin') self.spin_width.set_value (maxx) self.spin_height.set_value (maxy) self.spin_width.set_sensitive (False) self.spin_height.set_sensitive (False) rad.connect ('toggled', self.toggle_range, width, height,maxx,maxy) fc.show () while 1: # Cheesy loop. Break out as needed. response = dialog.run() if response == gtk.RESPONSE_OK: ext_mime_mapping = { 'png':'png', 'jpg':'jpeg', 'jpeg':'jpeg', \ 'svg':'svg', 'pdf':'pdf' } filename = fc.get_filename() ext = filename[filename.rfind('.')+1:] try: mime = ext_mime_mapping[ext] break except KeyError: msg = gtk.MessageDialog(self, gtk.DIALOG_DESTROY_WITH_PARENT, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK, \ _("Unknown file format")) msg.format_secondary_text (_("The file type '%s' is unsupported. Please use the suffix '.png',"\ " '.jpg' or '.svg'." % ext)) msg.run () msg.destroy () else: dialog.destroy () return true_width = int (self.spin_width.get_value ()) true_height = int (self.spin_height.get_value ()) native = not rad.get_active () dialog.destroy () if mime in ['png', 'jpg']: self.save_as_pixmap(filename, mime, true_width, true_height, bitdepth, native) else: surface = None if mime == 'svg': surface = cairo.SVGSurface(filename, true_width, true_height) elif mime == 'pdf': surface = cairo.PDFSurface(filename, true_width, true_height) self.save_surface(surface, true_width, true_height, native) def save_as_pixmap(self, filename, mime, width, height, bitdepth, native): pixmap = gtk.gdk.Pixmap (None, width, height, bitdepth) self.MainArea.export (pixmap.cairo_create (), width, height, native) pb = gtk.gdk.Pixbuf.get_from_drawable(gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True, 8, width, height), \ pixmap, gtk.gdk.colormap_get_system(), 0, 0, 0, 0, width, height) pb.save(filename, mime) def save_surface(self, surface, width, height, native): cairo_context = cairo.Context(surface) context = pangocairo.CairoContext(cairo_context) self.MainArea.export(context, width, height, native) surface.finish() def selection_changed_cb (self, area, start, end, text): clip = gtk.Clipboard (selection="PRIMARY") if text: clip.set_text (text) else: clip.clear () def edit_activated_cb (self, menu): # FIXME: Keybindings should also be deactivated. self.cut.set_sensitive (False) self.copy.set_sensitive (False) self.paste.set_sensitive (False) self.link.set_sensitive (False) if self.extended.is_focus (): self.paste.set_sensitive (True) stend = self.extended.get_buffer().get_selection_bounds() if len (stend) > 1: start, end = stend else: start = end = stend else: start, end = self.MainArea.get_selection_bounds () try: if self.mode == MMapArea.MODE_EDITING and len(self.MainArea.selected) and \ self.MainArea.selected[0].editing: self.paste.set_sensitive (True) except AttributeError: pass if len (self.MainArea.selected) == 2: self.link.set_sensitive (True) if start and start != end: self.cut.set_sensitive (True) self.copy.set_sensitive (True) def cut_text_cb (self, event): clip = gtk.Clipboard () if self.extended.is_focus (): self.extended.get_buffer().cut_clipboard (clip) else: self.MainArea.cut_clipboard (clip) def copy_text_cb (self, event): clip = gtk.Clipboard () if self.extended.is_focus (): self.extended.get_buffer().copy_clipboard (clip) else: self.MainArea.copy_clipboard (clip) def paste_text_cb (self, event): clip = gtk.Clipboard () if self.extended.is_focus (): self.extended.get_buffer().paste_clipboard (clip, None, True) else: self.MainArea.paste_clipboard (clip) def start_timer (self): self.SaveTimer = PeriodicSaveThread.PeriodicSaveThread(self.MainArea) self.SaveTimer.setDaemon( True) self.SaveTimer.start() labyrinth-0.6/labyrinth_lib/MapList.py000066400000000000000000000156761204476542500201500ustar00rootroot00000000000000# MapList.py # This file is part of Labyrinth # # Copyright (C) 2006 - Andreas Sliwka # # Labyrinth 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. # # Labyrinth 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 Labyrinth; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, # Boston, MA 02110-1301 USA # import os import utils import gtk import xml.dom.minidom as dom import datetime from xml.parsers.expat import ExpatError class MapList(object): COL_ID = 0 COL_TITLE = 1 COL_FNAME = 2 COL_OPEN = 3 """Holds the list of maps. has a couple of convinience functions. Sings irish folk this is (regarding to MCV) a model class. """ class MapCore(object): __slots__ = "__dict__ filename title nodes window index".split(" ") def __init__(self, index): self.__dict__["filename"] = None self.__dict__["title"] = None self.__dict__["modtime"] = None self.__dict__["nodes"] = [] self.__dict__["window"] = None self.__dict__["index"] = index def _read_from_file(self, filename): doc = dom.parse (filename) top_element = doc.documentElement self.filename = filename self.title = top_element.getAttribute ("title") self.window = None def __getattr__(self, key): dict = self.__dict__ if key in dict: return dict[key] else: raise ValueError("Class MapCore does not have an attribute named %s" % key) def __setattr__(self, key, value): dict = self.__dict__ if key in dict: old_value=dict[key] dict[key]=value else: raise ValueError("Class MapCore does not have an attribute named %s" % key) if "dont_listen" in dict: return listener = "_%s_changed" % key class_dict = self.__class__.__dict__ if listener in class_dict and callable(class_dict[listener]): class_dict[listener](self, value, old_value) # these listeners get called after the attribute has been changed already def _filename_changed(self, value, old_value): if not old_value is None: del MapList._maps_by_filename[old_value] if not value is None: MapList._maps_by_filename[value] = self.index def _title_changed(self, value, old_value): MapList._at_col_set_value(self.index, MapList.COL_TITLE, value) def __str__(self): return "" % (self.title, self.window and "yes" or "no") def __repr__(self): return self.__str__() _maps = [] _maps_by_filename = {} tree_view_model = gtk.ListStore(int, str, str, str, 'gboolean') def __init__(self): raise Exception("This class is a singleton full of classmethods, dont instantiate it.") @classmethod def load_all_from_dir(cls,dir): for f in os.listdir (dir): path = os.path.join (dir, f) if not os.path.isdir (path): cls.new_from_file (path) @classmethod def new_from_file(cls, filename): index = len(cls._maps) map = cls.MapCore(index = index) try: map._read_from_file(filename) cls._maps.append(map) map.modtime = datetime.datetime.fromtimestamp(os.stat(filename)[8]).strftime("%x %X") cls.tree_view_model.append([map.index, map.title, map.modtime, map.filename, False]) except ExpatError: map = None return map @classmethod def create_empty_map(cls): index = cls.next_col_id () map = cls.MapCore(index = index) map.modtime = datetime.datetime.now().strftime("%x %X") cls._maps.append(map) cls.tree_view_model.append([map.index, map.title, map.modtime, map.filename, False]) return map @classmethod def __str__(cls): return "\n\t%s\n" % "\n\t".join([ map.__str__() for map in cls._maps]) @classmethod def delete(cls, map): index = cls._maps.index(map) del cls._maps[ index ] if map.filename: del cls._maps_by_filename[map.filename] os.unlink(map.filename) iter = cls.get_iter_by_col_id(map.index) if iter: cls.tree_view_model.remove(iter) @classmethod def index(cls, map): cls._maps.index(map) # these functions return None or a single MapCore @classmethod def get_by_index(cls, index): for map in cls._maps: if map.index == index: return map return None @classmethod def __getitem__(cls, index): return cls._maps[index] @classmethod def get_by_filename(cls, name): return cls._maps[cls._maps_by_filename[name]] @classmethod def get_by_window(cls, window): for map in cls._maps: if map.window == window: return map return None #These functions return a (possibly empty) list of MapCores @classmethod def get_open_windows(cls): return [map for map in cls._maps if map.window is not None] # other functions @classmethod def count(cls): return len(cls._maps) # these functions wrap the gtk.ListStore that is used as View @classmethod def get_TreeViewModel(cls): return cls.tree_view_model @classmethod def _at_col_set_value(cls, col_id, col, value): iter = cls.get_iter_by_col_id (col_id) if iter: cls.tree_view_model.set_value(iter, col, value) @classmethod def get_iter_by_col_id(cls, col_id): found = False iter = cls.tree_view_model.get_iter_first () while iter: (num,) = cls.tree_view_model.get (iter, MapList.COL_ID) if col_id == num: found = True break iter = cls.tree_view_model.iter_next (iter) if not found: iter = None return iter @classmethod def next_col_id(cls): next_col_id = -1 iter = cls.tree_view_model.get_iter_first () while iter: (num,) = cls.tree_view_model.get (iter, MapList.COL_ID) if next_col_id < num: next_col_id = num iter = cls.tree_view_model.iter_next (iter) return next_col_id + 1 MapList.load_all_from_dir(utils.get_save_dir ()) labyrinth-0.6/labyrinth_lib/PeriodicSaveThread.py000066400000000000000000000022101204476542500222600ustar00rootroot00000000000000# PeriodicSaveThread.py # This file is part of Labyrinth # # Copyright (C) 2008 - Labyrinth-Dev-Team # # Labyrinth 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. # # Labyrinth 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 Labyrinth; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, # Boston, MA 02110-1301 USA # import threading import time class PeriodicSaveThread(threading.Thread): def __init__(self, main_area): threading.Thread.__init__(self) self.main_area = main_area self.cancel = False def run (self): time.sleep (60) while not self.cancel: self.main_area.save_thyself () time.sleep (60) labyrinth-0.6/labyrinth_lib/ResourceThought.py000066400000000000000000000125151204476542500217160ustar00rootroot00000000000000# ResourceThought.py # This file is part of Labyrinth # # Copyright (C) 2008 - Labyrinth-Dev-Team # # Labyrinth 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. # # Labyrinth 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 Labyrinth; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, # Boston, MA 02110-1301 USA # import gtk import pango import webbrowser import gettext _ = gettext.gettext import utils import BaseThought, TextThought import prefs class ResourceThought (TextThought.TextThought): def __init__ (self, coords, pango_context, thought_number, save, undo, loading, background_color, foreground_color): super (ResourceThought, self).__init__(coords, pango_context, thought_number, save, undo, loading, background_color, foreground_color, "res_thought") self.uri = "" # TODO: we should handle such things with a singleton self.glade = gtk.glade.XML(utils.get_data_file_name('labyrinth.glade')) self.dialog = self.glade.get_widget('ResourceChooserDialog') self.dialog.add_buttons(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OK, gtk.RESPONSE_OK) if not loading: self.process_uri_dialog() self.all_okay = True def process_uri_dialog(self, initial=True): res = self.dialog.run() self.dialog.hide() if res == gtk.RESPONSE_OK: # FIXME: validate input self.uri = self.glade.get_widget('urlEntry').get_text() if initial: self.add_text(self.uri) self.rebuild_byte_table() def process_button_down (self, event, mode, transformed): modifiers = gtk.accelerator_get_default_mod_mask () if event.type == gtk.gdk.BUTTON_PRESS and not self.editing: self.emit ("select_thought", event.state & modifiers) if event.button == 1 and mode == BaseThought.MODE_EDITING and event.type == gtk.gdk._2BUTTON_PRESS: if self.uri.find("http://") == -1: webbrowser.open("http://" + self.uri) else: webbrowser.open(self.uri) elif event.button == 3: self.emit ("popup_requested", event, 1) def update_save (self): super(ResourceThought, self).update_save() self.element.setAttribute ("uri", self.uri) def load (self, node): super(ResourceThought, self).load(node) self.uri = node.getAttribute ("uri") self.glade.get_widget('urlEntry').set_text(self.uri) def draw (self, context): if not self.layout: self.recalc_edges () if not self.editing: if not self.ul or not self.lr: print "Warning: Trying to draw unfinished box "+str(self.identity)+". Aborting." return utils.draw_thought_extended (context, self.ul, self.lr, \ self.am_selected, self.am_primary, self.background_color, False, True) else: ux, uy = self.ul if prefs.get_direction() == gtk.TEXT_DIR_LTR: context.move_to (ux, uy+5) context.line_to (ux, uy) context.line_to (ux+5, uy) else: lx = self.lr[0] context.move_to (lx, uy+5) context.line_to (lx, uy) context.line_to (lx-5, uy) context.stroke () (textx, texty) = (self.text_location[0], self.text_location[1]) r, g, b = utils.gtk_to_cairo_color(self.foreground_color) context.set_source_rgb (r, g, b) context.move_to (textx, texty) context.show_layout (self.layout) if self.editing: if self.preedit: (strong, weak) = self.layout.get_cursor_pos (self.index + self.preedit[2]) else: (strong, weak) = self.layout.get_cursor_pos (self.index) (startx, starty, curx,cury) = strong startx /= pango.SCALE starty /= pango.SCALE curx /= pango.SCALE cury /= pango.SCALE context.move_to (textx + startx, texty + starty) context.line_to (textx + startx, texty + starty + cury) context.stroke () context.set_source_rgb (0,0,0) context.stroke () def get_popup_menu_items(self): image = gtk.Image() image.set_from_stock(gtk.STOCK_EDIT, gtk.ICON_SIZE_MENU) edit_item = gtk.ImageMenuItem(_('Edit Text')) edit_item.set_image(image) edit_item.connect('activate', self.edit_cb) image = gtk.Image() image.set_from_stock(gtk.STOCK_NETWORK, gtk.ICON_SIZE_MENU) uri_item = gtk.ImageMenuItem(_('Edit URI')) uri_item.set_image(image) uri_item.connect('activate', self.edit_uri_cb) return [edit_item, uri_item] def edit_cb(self, widget): self.emit ("begin_editing") def edit_uri_cb(self, widget): self.process_uri_dialog(False) labyrinth-0.6/labyrinth_lib/TextBufferMarkup.py000066400000000000000000000333451204476542500220260ustar00rootroot00000000000000# TextBufferMarkup.py # This file is part of labyrinth # # Copyright (C) 2007 - Don Scorgie # # labyrinth 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. # # labyrinth 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 labyrinth; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, # Boston, MA 02110-1301 USA # import gtk import gobject import pango import UndoManager ADD_ATTR = 42 REMOVE_ATTR = 43 class ExtendedBuffer(gtk.TextBuffer): __gsignals__ = dict (set_focus = (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ()), set_attrs = (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_BOOLEAN, gobject.TYPE_BOOLEAN, gobject.TYPE_BOOLEAN, pango.FontDescription))) def __init__(self, undo_manager, save, save_doc): super(ExtendedBuffer, self).__init__() self.undo = undo_manager self.connect('insert-text', self.insert_text_cb) self.connect_after('insert-text', self.apply_attrs_cb) self.connect('delete-range', self.delete_range_cb) self.text_elem = save_doc.createTextNode ("Extended") self.save = save_doc self.element = save self.element.appendChild(self.text_elem) self.bold_tag = self.create_tag("bold", weight=pango.WEIGHT_BOLD) self.italics_tag = self.create_tag("italics", style=pango.STYLE_ITALIC) self.underline_tag = self.create_tag("underline", underline=pango.UNDERLINE_SINGLE) self.current_tags = [] self.requested_tags = [] self.connect_after('mark-set',self.mark_set_cb) self.bold_block = False self.italic_block = False def undo_action (self, action, mode): self.undo.block () self.emit ("set_focus") if action.undo_type == UndoManager.DELETE_LETTER or action.undo_type == UndoManager.DELETE_WORD: real_mode = not mode else: real_mode = mode if real_mode == UndoManager.UNDO: self.delete (self.get_iter_at_offset(action.args[0]), self.get_iter_at_offset (action.args[0]+action.args[2])) else: self.insert (self.get_iter_at_offset(action.args[0]), action.args[1]) self.undo.unblock () bold = italics = underline = False for x in self.current_tags: if x == "bold": bold = True elif x == "italic": italics = True elif x == "underline": underline = True self.emit("set_attrs_bla", bold, italics, underline, None) def delete_range_cb (self, buffer, iter, it1): text = self.get_text (iter, it1) self.undo.add_undo (UndoManager.UndoAction (self, UndoManager.DELETE_LETTER, self.undo_action, iter.get_offset(), text, len (text), -1, None, None)) return False def insert_text_cb (self, buffer, iter, text, length): self.undo.add_undo (UndoManager.UndoAction (self, UndoManager.INSERT_LETTER, self.undo_action, iter.get_offset(), text, length, None, None)) return False def apply_attrs_cb (self, buffer, iter, text, length): prev_iter = iter.copy() if not prev_iter.backward_chars(length): print "Errored" for x in self.current_tags: self.apply_tag_by_name(x, prev_iter, iter) return False def mark_set_cb(self, buffer, iter, mark, *params): italics = underline = bold = False if iter.has_tag(self.bold_tag): bold = True elif self.current_tags.count("bold") > 0: self.current_tags.remove("bold") if iter.has_tag(self.italics_tag): italics = True elif self.current_tags.count("italics") > 0: self.current_tags.remove("italics") if iter.has_tag(self.underline_tag): underline = True elif self.current_tags.count("underline") > 0: self.current_tags.remove("underline") for x in self.requested_tags: if x == "bold": bold = True if x == "italics": italics = True if x == "underline": underline = True if self.current_tags.count(x) == 0: self.current_tags.append(x) self.emit("set_attrs", bold, italics, underline, None) return False def update_save (self): next = self.element.firstChild while next: m = next.nextSibling if next.nodeName == "attribute": self.element.removeChild (next) next.unlink () next = m self.text_elem.replaceWholeText (self.get_text()) mark = self.get_insert() it = self.get_iter_at_mark(mark) self.element.setAttribute("mark", str(it.get_offset())) iter = self.get_start_iter() cur = 0 tags = {} doc = self.element.ownerDocument tag_table = self.get_tag_table() while(1): if iter.begins_tag(tag_table.lookup("bold")): tags["bold"] = cur if iter.ends_tag(tag_table.lookup("bold")): elem = doc.createElement ("attribute") self.element.appendChild (elem) start = tags.pop("bold") elem.setAttribute("start", str(start)) elem.setAttribute("end", str(cur)) elem.setAttribute("type", "bold") if iter.begins_tag(tag_table.lookup("italics")): tags["italics"] = cur if iter.ends_tag(tag_table.lookup("italics")): elem = doc.createElement ("attribute") self.element.appendChild (elem) start = tags.pop("italics") elem.setAttribute("start", str(start)) elem.setAttribute("end", str(cur)) elem.setAttribute("type", "italics") if iter.begins_tag(tag_table.lookup("underline")): tags["underline"] = cur if iter.ends_tag(tag_table.lookup("underline")): elem = doc.createElement ("attribute") self.element.appendChild (elem) start = tags.pop("underline") elem.setAttribute("start", str(start)) elem.setAttribute("end", str(cur)) elem.setAttribute("type", "underline") cur+=1 if not iter.forward_char(): break for x in tags: elem = doc.createElement ("attribute") self.element.appendChild (elem) elem.setAttribute("start", str(tags[x])) elem.setAttribute("end", str(-1)) elem.setAttribute("type", x) def load(self, node): mark = None if node.hasAttribute("mark"): mark = int(node.getAttribute("mark")) for n in node.childNodes: if n.nodeType == n.TEXT_NODE: if n.data != "LABYRINTH_AUTOGEN_TEXT_REMOVE": self.set_text(n.data) elif n.nodeName == "attribute": attrType = n.getAttribute("type") start = int(n.getAttribute("start")) end = int(n.getAttribute("end")) start_it = self.get_iter_at_offset(start) if end >= 0: end_it = self.get_iter_at_offset(end) else: end_it = self.get_end_iter() self.apply_tag_by_name(attrType, start_it, end_it) else: print "Error: Unknown type: %s. Ignoring." % n.nodeName if mark: ins_iter = self.get_iter_at_offset(mark) self.move_mark_by_name("insert", ins_iter) self.move_mark_by_name("selection_bound", ins_iter) def get_text (self, start=None, end=None, include_hidden_chars=True): if not start: start=self.get_start_iter() if not end: end=self.get_end_iter() return gtk.TextBuffer.get_text(self,start,end) def undo_attr (self, action, mode): if mode == UndoManager.UNDO: if action.undo_type == ADD_ATTR and len(action.args[1]) > 0: self.remove_tag_by_name(action.args[0], action.args[1][0], action.args[1][1]) elif action.undo_type == ADD_ATTR and len(action.args[1]) == 0: self.current_tags.remove(action.args[0]) self.requested_tags.remove(action.args[0]) elif action.undo_type == REMOVE_ATTR and len(action.args[1]) > 0: self.apply_tag_by_name(action.args[0], action.args[1][0], action.args[1][1]) else: self.current_tags.append(action.args[0]) self.requested_tags.append(action.args[0]) else: if action.undo_type == ADD_ATTR and len(action.args[1]) > 0: self.apply_tag_by_name(action.args[0], action.args[1][0], action.args[1][1]) elif action.undo_type == ADD_ATTR and len(action.args[1]) == 0: self.current_tags.append(action.args[0]) self.requested_tags.append(action.args[0]) elif action.undo_type == REMOVE_ATTR and len(action.args[1]) > 0: self.remove_tag_by_name(action.args[0], action.args[1][0], action.args[1][1]) else: self.current_tags.remove(action.args[0]) self.requested_tags.remove(action.args[0]) bold = italics = underline = False for x in self.current_tags: if x == "bold": bold = True elif x == "italics": italics = True elif x == "underline": underline = True self.emit("set_attrs", bold, italics, underline) def set_bold (self, bold): selection = self.get_selection_bounds() if bold: if len(selection) > 0: self.apply_tag_by_name("bold", selection[0], selection[1]) else: self.current_tags.append("bold") self.requested_tags.append("bold") self.undo.add_undo(UndoManager.UndoAction(self, ADD_ATTR, self.undo_attr, "bold", selection)) else: if len(selection) > 0: self.remove_tag_by_name("bold", selection[0], selection[1]) else: self.current_tags.remove("bold") self.requested_tags.remove("bold") self.undo.add_undo(UndoManager.UndoAction(self, REMOVE_ATTR, self.undo_attr, "bold", selection)) def set_italics (self, italics): selection = self.get_selection_bounds() if italics: if len(selection) > 0: self.apply_tag_by_name("italics", selection[0], selection[1]) else: self.current_tags.append("italics") self.requested_tags.append("italics") self.undo.add_undo(UndoManager.UndoAction(self, ADD_ATTR, self.undo_attr, "italics", selection)) else: if len(selection) > 0: self.remove_tag_by_name("italics", selection[0], selection[1]) else: self.current_tags.remove("italics") self.requested_tags.remove("italics") self.undo.add_undo(UndoManager.UndoAction(self, REMOVE_ATTR, self.undo_attr, "italics", selection)) def set_underline (self, underline): selection = self.get_selection_bounds() if underline: if len(selection) > 0: self.apply_tag_by_name("underline", selection[0], selection[1]) else: self.current_tags.append("underline") self.requested_tags.append("underline") self.undo.add_undo(UndoManager.UndoAction(self, ADD_ATTR, self.undo_attr, "underline", selection)) else: if len(selection) > 0: self.remove_tag_by_name("underline", selection[0], selection[1]) else: self.current_tags.remove("underline") self.requested_tags.remove("underline") self.undo.add_undo(UndoManager.UndoAction(self, REMOVE_ATTR, self.undo_attr, "underline", selection)) labyrinth-0.6/labyrinth_lib/TextThought.py000066400000000000000000001341061204476542500210540ustar00rootroot00000000000000#! /usr/bin/env python # Thoughts.py # This file is part of Labyrinth # # Copyright (C) 2006 - Don Scorgie # # Labyrinth 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. # # Labyrinth 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 Labyrinth; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, # Boston, MA 02110-1301 USA # import gtk import pango import os import xml.dom import utils import BaseThought import UndoManager import prefs UNDO_ADD_ATTR=64 UNDO_ADD_ATTR_SELECTION=65 UNDO_REMOVE_ATTR=66 UNDO_REMOVE_ATTR_SELECTION=67 def wrap_attriterator(ai): """Wraps a pango AttrIterator so it can be used like a regular Python iterator. Yields (ai.get_attrs(), ai.range()) at each step. """ yield ai.get_attrs(), ai.range() while ai.next(): yield ai.get_attrs(), ai.range() def minmax(a, b): return (min(a, b), max(a, b)) class TextThought (BaseThought.BaseThought): def __init__ (self, coords, pango_context, thought_number, save, undo, loading, background_color, foreground_color, name="thought"): super (TextThought, self).__init__(save, name, undo, background_color, foreground_color) self.index = 0 self.end_index = 0 self.bytes = "" self.bindex = 0 self.text_location = coords self.text_element = save.createTextNode ("GOOBAH") self.element.appendChild (self.text_element) self.layout = None self.identity = thought_number self.pango_context = pango_context self.moving = False self.preedit = None self.attrlist = None self.attributes = pango.AttrList() self.current_attrs = [] if prefs.get_direction () == gtk.TEXT_DIR_LTR: self.pango_context.set_base_dir (pango.DIRECTION_LTR) else: self.pango_context.set_base_dir (pango.DIRECTION_RTL) self.b_f_i = self.bindex_from_index margin = utils.margin_required (utils.STYLE_NORMAL) if coords: self.ul = (coords[0]-margin[0], coords[1] - margin[1]) else: self.ul = None self.all_okay = True def index_from_bindex (self, bindex): index = 0 if bindex > 0: index = sum([ int(self.bytes[i]) for i in range(bindex) ]) return index def bindex_from_index (self, index): if index == 0: return 0 bind = 0 nbytes = 0 for x in self.bytes: nbytes += int (x) bind += 1 if nbytes == index: break if nbytes < index: bind = len(self.bytes) return bind def attrs_changed (self): bold = False italics = False underline = False pango_font = None del self.attrlist self.attrlist = self.attributes.copy() if self.preedit: ins_text = self.preedit[0] ins_style = self.preedit[1] if self.index == len(self.text): show_text = self.text + ins_text elif self.index == 0: show_text = ins_text + self.text else: split1 = self.text[:self.index] split2 = self.text[self.index:] show_text = split1 + ins_text + split2 self.attrlist.splice(ins_style, self.index, len(ins_text)) else: show_text = self.text it = wrap_attriterator(self.attributes.get_iterator()) for attrs, (start, end) in it: found = False if self.index == self.end_index: if start <= self.index and end > self.index: found = True elif self.index < self.end_index: if start > self.end_index: break elif start <= self.index and \ end >= self.end_index: # We got a winner! found = True else: # i.e. self.index > self.end_index if start > self.index: break elif start <= self.end_index and \ end >= self.index: # We got another winner! found = True if found: for x in attrs: if x.type == pango.ATTR_WEIGHT and \ x.value == pango.WEIGHT_BOLD: bold = True elif x.type == pango.ATTR_STYLE and \ x.value == pango.STYLE_ITALIC: italics = True elif x.type == pango.ATTR_UNDERLINE and \ x.value == pango.UNDERLINE_SINGLE: underline = True elif x.type == pango.ATTR_FONT_DESC: pango_font = x.desc to_add = [] if bold: to_add.append(pango.AttrWeight(pango.WEIGHT_BOLD, self.index, self.index)) if italics: to_add.append(pango.AttrStyle(pango.STYLE_ITALIC, self.index, self.index)) if underline: to_add.append(pango.AttrUnderline(pango.UNDERLINE_SINGLE, self.index, self.index)) if pango_font: to_add.append(pango.AttrFontDesc(pango_font, self.index, self.index)) for x in self.current_attrs: if x.type == pango.ATTR_WEIGHT and x.value == pango.WEIGHT_BOLD: bold = True to_add.append(x) if x.type == pango.ATTR_STYLE and x.value == pango.STYLE_ITALIC: italics = True to_add.append(x) if x.type == pango.ATTR_UNDERLINE and x.value == pango.UNDERLINE_SINGLE: underline = True to_add.append(x) if x.type == pango.ATTR_FONT_DESC: pango_font = x.desc to_add.append(x) del self.current_attrs self.current_attrs = to_add self.emit("update-attrs", bold, italics, underline, pango_font) return show_text def recalc_edges (self): if not hasattr(self, 'layout'): return del self.layout show_text = self.attrs_changed () r,g,b = utils.selected_colors["fill"] r *= 65536 g *= 65536 b *= 65536 if self.index > self.end_index: bgsel = pango.AttrBackground (int(r), int(g), int(b), self.end_index, self.index) else: bgsel = pango.AttrBackground (int(r), int(g), int(b), self.index, self.end_index) self.attrlist.insert (bgsel) self.layout = pango.Layout (self.pango_context) self.layout.set_text (show_text) self.layout.set_attributes(self.attrlist) self.recalc_position () def recalc_position (self): if self.layout is None: self.recalc_edges() (x,y) = self.layout.get_pixel_size () margin = utils.margin_required (utils.STYLE_NORMAL) if prefs.get_direction () == gtk.TEXT_DIR_LTR: self.text_location = (self.ul[0] + margin[0], self.ul[1] + margin[1]) self.lr = (x + self.text_location[0]+margin[2], y + self.text_location[1] + margin[3]) else: self.layout.set_alignment (pango.ALIGN_RIGHT) tmp1 = self.ul[1] if not self.lr: self.lr = (self.ul[0], self.ul[1] + y + margin[1] + margin[3]) self.text_location = (self.lr[0] - margin[2] - x, self.ul[1] + margin[1]) self.ul = (self.lr[0] - margin[0] - margin[2] - x, tmp1) def commit_text (self, context, string, mode, font_name): if not self.editing: self.emit ("begin_editing") self.set_font(font_name) self.add_text (string) self.recalc_edges () self.emit ("title_changed", self.text) self.emit ("update_view") def add_text (self, string): if self.index > self.end_index: self.index, self.end_index = self.end_index, self.index left = self.text[:self.index] right = self.text[self.end_index:] bleft = self.bytes[:self.b_f_i (self.index)] bright = self.bytes[self.b_f_i (self.end_index):] change = self.index - self.end_index + len(string) # Rather a hack: font descriptions override bold/italic attributes, so # we pull them out and set them before other changes. changes = [] fontdesc_changes = [] def cache_change(x): if x.type == pango.ATTR_FONT_DESC: fontdesc_changes.append(x) else: changes.append(x) for x in self.current_attrs: x.start_index = self.index x.end_index = self.index + len(string) cache_change(x) old_attrs = [] it = wrap_attriterator(self.attributes.get_iterator()) for attrs, (start, end) in it: if start <= self.index: if end > self.end_index: # Inside range for x in attrs: old_attrs.append(x.copy()) x.end_index += change cache_change(x) else: for x in attrs: old_attrs.append(x.copy()) cache_change(x) else: if end > self.end_index: for x in attrs: old_attrs.append(x.copy()) x.end_index += change x.start_index += change cache_change(x) else: for x in attrs: old_attrs.append(x.copy()) cache_change(x) del self.attributes self.attributes = pango.AttrList() for x in fontdesc_changes + changes: self.attributes.change(x) self.text = left + string + right self.undo.add_undo (UndoManager.UndoAction (self, UndoManager.INSERT_LETTER, self.undo_text_action, self.bindex, string, len(string), old_attrs, changes)) self.index += len (string) self.bytes = bleft + str(len(string)) + bright self.bindex = self.b_f_i (self.index) self.end_index = self.index def draw (self, context): if not self.layout: self.recalc_edges () if not self.editing: # We should draw the entire bounding box around ourselves # We should also have our coordinates figured out. If not, scream! if not self.ul or not self.lr: print "Warning: Trying to draw unfinished box "+str(self.identity)+". Aborting." return style = utils.STYLE_EXTENDED_CONTENT if len (self.extended_buffer.get_text()) == 0: style = utils.STYLE_NORMAL utils.draw_thought_outline (context, self.ul, self.lr, self.background_color, self.am_selected, self.am_primary, style) else: ux, uy = self.ul if prefs.get_direction() == gtk.TEXT_DIR_LTR: context.move_to (ux, uy+5) context.line_to (ux, uy) context.line_to (ux+5, uy) else: lx = self.lr[0] context.move_to (lx, uy+5) context.line_to (lx, uy) context.line_to (lx-5, uy) context.stroke () textx, texty = (self.text_location[0], self.text_location[1]) if (self.foreground_color): r, g, b = utils.gtk_to_cairo_color(self.foreground_color) else: r, g ,b = utils.default_colors["text"] context.set_source_rgb (r, g, b) context.move_to (textx, texty) context.show_layout (self.layout) if self.editing: if self.preedit: strong, weak = self.layout.get_cursor_pos (self.index + self.preedit[2]) else: strong, weak = self.layout.get_cursor_pos (self.index) (startx, starty, curx,cury) = strong startx /= pango.SCALE starty /= pango.SCALE curx /= pango.SCALE cury /= pango.SCALE context.move_to (textx + startx, texty + starty) context.line_to (textx + startx, texty + starty + cury) context.stroke () context.set_source_rgb (0,0,0) context.stroke () def begin_editing (self): self.editing = True self.emit ("update_links") return True def finish_editing (self): if not self.editing: return self.editing = False self.end_index = self.index self.emit ("update_links") self.recalc_edges () if len (self.text) == 0: self.emit ("delete_thought") def includes (self, coords, mode): if not self.ul or not self.lr or not coords: return False inside = (coords[0] < self.lr[0] + self.sensitive) and \ (coords[0] > self.ul[0] - self.sensitive) and \ (coords[1] < self.lr[1] + self.sensitive) and \ (coords[1] > self.ul[1] - self.sensitive) if inside and self.editing: self.emit ("change_mouse_cursor", gtk.gdk.XTERM) elif inside: self.emit ("change_mouse_cursor", gtk.gdk.LEFT_PTR) return inside def process_key_press (self, event, mode): modifiers = gtk.accelerator_get_default_mod_mask () shift = event.state & modifiers == gtk.gdk.SHIFT_MASK handled = True clear_attrs = True if not self.editing: return False if (event.state & modifiers) & gtk.gdk.CONTROL_MASK: if event.keyval == gtk.keysyms.a: self.index = self.bindex = 0 self.end_index = len (self.text) elif event.keyval == gtk.keysyms.Escape: self.emit ("finish_editing") elif event.keyval == gtk.keysyms.Left: if prefs.get_direction() == gtk.TEXT_DIR_LTR: self.move_index_back (shift) else: self.move_index_forward (shift) elif event.keyval == gtk.keysyms.Right: if prefs.get_direction() == gtk.TEXT_DIR_RTL: self.move_index_back (shift) else: self.move_index_forward (shift) elif event.keyval == gtk.keysyms.Up: self.move_index_up (shift) elif event.keyval == gtk.keysyms.Down: self.move_index_down (shift) elif event.keyval == gtk.keysyms.Home: if prefs.get_direction() == gtk.TEXT_DIR_LTR: self.move_index_horizontal (shift, True) # move home else: self.move_index_horizontal (shift) # move end self.move_index_horizontal (shift, True) # move home elif event.keyval == gtk.keysyms.End: self.move_index_horizontal (shift) # move elif event.keyval == gtk.keysyms.BackSpace and self.editing: self.backspace_char () elif event.keyval == gtk.keysyms.Delete and self.editing: self.delete_char () elif len (event.string) != 0: self.add_text (event.string) clear_attrs = False else: handled = False if handled and clear_attrs: del self.current_attrs self.current_attrs = [] self.recalc_edges () self.selection_changed () self.emit ("title_changed", self.text) self.bindex = self.bindex_from_index (self.index) self.emit ("update_view") return handled def undo_text_action (self, action, mode): self.undo.block () if action.undo_type == UndoManager.DELETE_LETTER or action.undo_type == UndoManager.DELETE_WORD: real_mode = not mode attrslist = [action.args[5], action.args[4]] else: real_mode = mode attrslist = [action.args[3], action.args[4]] self.bindex = action.args[0] self.index = self.index_from_bindex (self.bindex) self.end_index = self.index if real_mode == UndoManager.UNDO: attrs = attrslist[0] self.end_index = self.index + action.args[2] self.delete_char () else: attrs = attrslist[1] self.add_text (action.text) self.rebuild_byte_table () self.bindex = self.b_f_i (self.index) del self.attributes self.attributes = pango.AttrList() for a in attrs: self.attributes.change(a) self.recalc_edges () self.emit ("begin_editing") self.emit ("title_changed", self.text) self.emit ("update_view") self.emit ("grab_focus", False) self.undo.unblock () def delete_char (self): if self.index == self.end_index == len (self.text): return if self.index > self.end_index: self.index, self.end_index = self.end_index, self.index if self.index != self.end_index: left = self.text[:self.index] right = self.text[self.end_index:] local_text = self.text[self.index:self.end_index] bleft = self.bytes[:self.b_f_i (self.index)] bright = self.bytes[self.b_f_i (self.end_index):] local_bytes = self.bytes[self.b_f_i (self.index):self.b_f_i (self.end_index)] change = -len(local_text) else: left = self.text[:self.index] right = self.text[self.index+int(self.bytes[self.bindex]):] local_text = self.text[self.index:self.index+int(self.bytes[self.bindex])] bleft = self.bytes[:self.b_f_i(self.index)] bright = self.bytes[self.b_f_i(self.index)+1:] local_bytes = self.bytes[self.b_f_i(self.index)] change = -len(local_text) changes = [] old_attrs = [] accounted = -change for l, (start, end) in wrap_attriterator(self.attributes.get_iterator()): if end <= self.index: for x in l: changes.append(x) elif start < self.index and end <= self.end_index: # partial ending for x in l: old_attrs.append(x.copy()) accounted -= (x.end_index - self.index) x.end_index -= (x.end_index - self.index) changes.append(x) elif start <= self.index and end >= self.end_index: # Swallow whole accounted -= (end - start) for x in l: old_attrs.append(x.copy()) x.end_index += change changes.append(x) elif start < self.end_index and end > self.end_index: # partial beginning for x in l: old_attrs.append(x.copy()) accounted -= (x.start_index - self.index) x.start_index = self.index x.end_index = x.start_index + (end - start) - accounted changes.append(x) else: # Past for x in l: old_attrs.append(x.copy()) x.start_index += change x.end_index += change changes.append(x) del self.attributes self.attributes = pango.AttrList() for a in changes: self.attributes.change(a) self.undo.add_undo (UndoManager.UndoAction (self, UndoManager.DELETE_LETTER, self.undo_text_action, self.b_f_i (self.index), local_text, len(local_text), local_bytes, old_attrs, changes)) self.text = left+right self.bytes = bleft+bright self.end_index = self.index def backspace_char (self): if self.index == self.end_index == 0: return if self.index > self.end_index: self.index, self.end_index = self.end_index, self.index if self.index != self.end_index: left = self.text[:self.index] right = self.text[self.end_index:] bleft = self.bytes[:self.b_f_i (self.index)] bright = self.bytes[self.b_f_i (self.end_index):] local_text = self.text[self.index:self.end_index] local_bytes = self.bytes[self.b_f_i (self.index):self.b_f_i (self.end_index)] change = -len(local_text) else: left = self.text[:self.index-int(self.bytes[self.bindex-1])] right = self.text[self.index:] bleft = self.bytes[:self.b_f_i(self.index)-1] bright = self.bytes[self.b_f_i(self.index):] local_text = self.text[self.index-int(self.bytes[self.bindex-1]):self.index] local_bytes = self.bytes[self.b_f_i(self.index)-1] self.index-=int(self.bytes[self.bindex-1]) change = -len(local_text) old_attrs = [] changes= [] accounted = -change for l, (start, end) in wrap_attriterator(self.attributes.get_iterator()): if end <= self.index: for x in l: old_attrs.append(x.copy()) changes.append(x) elif start < self.index and end <= self.end_index: # partial ending for x in l: old_attrs.append(x.copy()) accounted -= (x.end_index - self.index) x.end_index -= (x.end_index - self.index) changes.append(x) elif start <= self.index and end >= self.end_index: # Swallow whole accounted -= (end - start) for x in l: old_attrs.append(x.copy()) x.end_index += change changes.append(x) elif start < self.end_index and end > self.end_index: # partial beginning for x in l: old_attrs.append(x.copy()) accounted -= (x.start_index - self.index) x.start_index = self.index x.end_index = x.start_index + (end - start) - accounted changes.append(x) else: # Past for x in l: old_attrs.append(x.copy()) x.start_index += change x.end_index += change changes.append(x) del self.attributes self.attributes = pango.AttrList() for a in changes: self.attributes.change(a) self.text = left+right self.bytes = bleft+bright self.end_index = self.index self.undo.add_undo (UndoManager.UndoAction (self, UndoManager.DELETE_LETTER, self.undo_text_action, self.b_f_i (self.index), local_text, len(local_text), local_bytes, old_attrs, changes)) if self.index < 0: self.index = 0 def move_index_back (self, mod): if self.index <= 0: self.end_index = self.index return self.index -= int(self.bytes[self.bindex-1]) if not mod: self.end_index = self.index def move_index_forward (self, mod): if self.index >= len(self.text): self.end_index = self.index return self.index += int(self.bytes[self.bindex]) if not mod: self.end_index = self.index def move_index_up (self, mod): tmp = self.text.decode () lines = tmp.splitlines () if len (lines) == 1: self.end_index = self.index return loc = 0 line = 0 for i in lines: loc += len (i)+1 if loc > self.index: loc -= len (i)+1 line -= 1 break line += 1 if line == -1: self.end_index = self.index return elif line >= len (lines): self.bindex -= len (lines[-1])+1 self.index = self.index_from_bindex (self.bindex) if not mod: self.end_index = self.index return dist = self.bindex - loc -1 self.bindex = loc if dist < len (lines[line]): self.bindex -= (len (lines[line]) - dist) else: self.bindex -= 1 if self.bindex < 0: self.bindex = 0 self.index = self.index_from_bindex (self.bindex) if not mod: self.end_index = self.index def move_index_down (self, mod): tmp = self.text.decode () lines = tmp.splitlines () if len (lines) == 1: self.end_index = self.index return loc = 0 line = 0 for i in lines: loc += len (i)+1 if loc > self.bindex: break line += 1 if line >= len (lines)-1: self.end_index = self.index return dist = self.bindex - (loc - len (lines[line]))+1 self.bindex = loc if dist > len (lines[line+1]): self.bindex += len (lines[line+1]) else: self.bindex += dist self.index = self.index_from_bindex (self.bindex) if not mod: self.end_index = self.index def move_index_horizontal(self, mod, home=False): lines = self.text.splitlines () loc = 0 line = 0 for i in lines: loc += len (i) + 1 if loc > self.index: self.index = loc - 1 if home: self.index -= len(i) if not mod: self.end_index = self.index return line += 1 def process_button_down (self, event, mode, transformed): modifiers = gtk.accelerator_get_default_mod_mask () if event.button == 1: if event.type == gtk.gdk.BUTTON_PRESS and not self.editing: self.emit ("select_thought", event.state & modifiers) elif event.type == gtk.gdk.BUTTON_PRESS and self.editing: x = int ((transformed[0] - self.ul[0])*pango.SCALE) y = int ((transformed[1] - self.ul[1])*pango.SCALE) loc = self.layout.xy_to_index (x, y) self.index = loc[0] if loc[0] >= len(self.text) -1 or self.text[loc[0]+1] == '\n': self.index += loc[1] self.bindex = self.bindex_from_index (self.index) if not (event.state & modifiers) & gtk.gdk.SHIFT_MASK: self.end_index = self.index elif mode == BaseThought.MODE_EDITING and event.type == gtk.gdk._2BUTTON_PRESS: if self.editing: self.move_index_horizontal(False) # go to the end self.index = 0 # and mark all else: self.emit ("begin_editing") elif event.button == 2 and self.editing: x = int ((transformed[0] - self.ul[0])*pango.SCALE) y = int ((transformed[1] - self.ul[1])*pango.SCALE) loc = self.layout.xy_to_index (x, y) self.index = loc[0] if loc[0] >= len(self.text) -1 or self.text[loc[0]+1] == '\n': self.index += loc[1] self.bindex = self.bindex_from_index (self.index) self.end_index = self.index if os.name != 'nt': clip = gtk.Clipboard (selection="PRIMARY") self.paste_text (clip) elif event.button == 3: self.emit ("popup_requested", event, 1) del self.current_attrs self.current_attrs = [] self.recalc_edges() self.emit ("update_view") def process_button_release (self, event, unending_link, mode, transformed): if unending_link: unending_link.set_child (self) self.emit ("claim_unending_link") def selection_changed (self): start, end = minmax(self.index, self.end_index) self.emit ("text_selection_changed", start, end, self.text[start:end]) def handle_motion (self, event, mode, transformed): if event.state & gtk.gdk.BUTTON1_MASK and self.editing: if transformed[0] < self.lr[0] and transformed[0] > self.ul[0] and \ transformed[1] < self.lr[1] and transformed[1] > self.ul[1]: x = int ((transformed[0] - self.ul[0])*pango.SCALE) y = int ((transformed[1] - self.ul[1])*pango.SCALE) loc = self.layout.xy_to_index (x, y) self.index = loc[0] if loc[0] >= len(self.text) -1 or self.text[loc[0]+1] == '\n': self.index += loc[1] self.bindex = self.bindex_from_index (self.index) self.selection_changed () elif mode == BaseThought.MODE_EDITING: self.emit ("finish_editing") self.emit ("create_link", \ (self.ul[0]-((self.ul[0]-self.lr[0]) / 2.), self.ul[1]-((self.ul[1]-self.lr[1]) / 2.))) return True elif event.state & gtk.gdk.BUTTON1_MASK and not self.editing and \ mode == BaseThought.MODE_EDITING and event.state & gtk.gdk.CONTROL_MASK: self.emit ("create_link", \ (self.ul[0]-((self.ul[0]-self.lr[0]) / 2.), self.ul[1]-((self.ul[1]-self.lr[1]) / 2.))) self.recalc_edges() self.emit ("update_view") def export (self, context, move_x, move_y): utils.export_thought_outline (context, self.ul, self.lr, self.background_color, self.am_selected, self.am_primary, utils.STYLE_NORMAL, (move_x, move_y)) r,g,b = utils.gtk_to_cairo_color (self.foreground_color) context.set_source_rgb (r, g, b) context.move_to (self.text_location[0]+move_x, self.text_location[1]+move_y) context.show_layout (self.layout) context.set_source_rgb (0,0,0) context.stroke () def update_save (self): next = self.element.firstChild while next: m = next.nextSibling if next.nodeName == "attribute": self.element.removeChild (next) next.unlink () next = m if self.text_element.parentNode is not None: self.text_element.replaceWholeText (self.text) text = self.extended_buffer.get_text () if text: self.extended_buffer.update_save() else: try: self.element.removeChild(self.extended_buffer.element) except xml.dom.NotFoundErr: pass self.element.setAttribute ("cursor", str(self.index)) self.element.setAttribute ("selection_end", str(self.end_index)) self.element.setAttribute ("ul-coords", str(self.ul)) self.element.setAttribute ("lr-coords", str(self.lr)) self.element.setAttribute ("identity", str(self.identity)) self.element.setAttribute ("background-color", self.background_color.to_string()) self.element.setAttribute ("foreground-color", self.foreground_color.to_string()) if self.editing: self.element.setAttribute ("edit", "true") else: try: self.element.removeAttribute ("edit") except xml.dom.NotFoundErr: pass if self.am_selected: self.element.setAttribute ("current_root", "true") else: try: self.element.removeAttribute ("current_root") except xml.dom.NotFoundErr: pass if self.am_primary: self.element.setAttribute ("primary_root", "true"); else: try: self.element.removeAttribute ("primary_root") except xml.dom.NotFoundErr: pass doc = self.element.ownerDocument for attrs, r in wrap_attriterator(self.attributes.get_iterator()): for x in attrs: elem = doc.createElement ("attribute") elem.setAttribute("start", str(r[0])) elem.setAttribute("end", str(r[1])) self.element.appendChild (elem) if x.type == pango.ATTR_WEIGHT and x.value == pango.WEIGHT_BOLD: elem.setAttribute("type", "bold") elif x.type == pango.ATTR_STYLE and x.value == pango.STYLE_ITALIC: elem.setAttribute("type", "italics") elif x.type == pango.ATTR_UNDERLINE and x.value == pango.UNDERLINE_SINGLE: elem.setAttribute("type", "underline") elif x.type == pango.ATTR_FONT_DESC: elem.setAttribute("type", "font") elem.setAttribute("value", x.desc.to_string ()) def rebuild_byte_table (self): # Build the Byte table del self.bytes self.bytes = '' tmp = self.text.encode ("utf-8") current = 0 for z in range(len(self.text)): if str(self.text[z]) == str(tmp[current]): self.bytes += '1' else: blen = 2 while 1: try: if str(tmp[current:current+blen].encode()) == str(self.text[z]): self.bytes += str(blen) current+=(blen-1) break blen += 1 except: blen += 1 current+=1 self.bindex = self.b_f_i (self.index) self.text = tmp def load (self, node): self.index = int (node.getAttribute ("cursor")) if node.hasAttribute ("selection_end"): self.end_index = int (node.getAttribute ("selection_end")) else: self.end_index = self.index tmp = node.getAttribute ("ul-coords") self.ul = utils.parse_coords (tmp) tmp = node.getAttribute ("lr-coords") self.lr = utils.parse_coords (tmp) self.identity = int (node.getAttribute ("identity")) try: tmp = node.getAttribute ("background-color") self.background_color = gtk.gdk.color_parse(tmp) tmp = node.getAttribute ("foreground-color") self.foreground_color = gtk.gdk.color_parse(tmp) except ValueError: pass if node.hasAttribute ("edit"): self.editing = True else: self.editing = False self.end_index = self.index self.am_selected = node.hasAttribute ("current_root") self.am_primary = node.hasAttribute ("primary_root") for n in node.childNodes: if n.nodeType == n.TEXT_NODE: self.text = n.data elif n.nodeName == "Extended": self.extended_buffer.load(n) elif n.nodeName == "attribute": attrType = n.getAttribute("type") start = int(n.getAttribute("start")) end = int(n.getAttribute("end")) if attrType == "bold": attr = pango.AttrWeight(pango.WEIGHT_BOLD, start, end) elif attrType == "italics": attr = pango.AttrStyle(pango.STYLE_ITALIC, start, end) elif attrType == "underline": attr = pango.AttrUnderline(pango.UNDERLINE_SINGLE, start, end) elif attrType == "font": font_name = str(n.getAttribute("value")) pango_font = pango.FontDescription (font_name) attr = pango.AttrFontDesc (pango_font, start, end) self.attributes.change(attr) else: print "Unknown: " + n.nodeName self.rebuild_byte_table () self.recalc_edges () def copy_text (self, clip): start, end = minmax(self.index, self.end_index) clip.set_text (self.text[start:end]) def cut_text (self, clip): self.copy_text (clip) self.delete_char () self.recalc_edges () self.emit ("title_changed", self.text) self.bindex = self.bindex_from_index (self.index) self.emit ("update_view") def paste_text (self, clip): text = clip.wait_for_text() if not text: return self.add_text (text) self.rebuild_byte_table () self.recalc_edges () self.emit ("title_changed", self.text) self.bindex = self.bindex_from_index (self.index) self.emit ("update_view") def delete_surroundings(self, imcontext, offset, n_chars, mode): # TODO: Add in Attr stuff orig = len(self.text) left = self.text[:offset] right = self.text[offset+n_chars:] local_text = self.text[offset:offset+n_chars] self.text = left+right self.rebuild_byte_table () new = len(self.text) if self.index > len(self.text): self.index = len(self.text) change = old - new changes = [] old_attrs = [] accounted = -change index = offset end_index = offset - (new-orig) for l, (start, end) in wrap_attriterator(self.attributes.get_iterator()): if end <= start: for x in l: changes.append(x) elif start < index and end <= end_index: # partial ending for x in l: old_attrs.append(x.copy()) accounted -= (x.end_index - index) x.end_index -= (x.end_index - index) changes.append(x) elif start <= index and end >= end_index: # Swallow whole accounted -= (end - start) for x in l: old_attrs.append(x.copy()) x.end_index += change changes.append(x) elif start < end_index and end > end_index: # partial beginning for x in l: old_attrs.append(x.copy()) accounted -= (x.start_index - index) x.start_index = index x.end_index = x.start_index + (end - start) - accounted changes.append(x) else: # Past for x in l: old_attrs.append(x.copy()) x.start_index += change x.end_index += change changes.append(x) del self.attributes self.attributes = pango.AttrList() for x in changes: self.attributes.change(x) self.recalc_edges () self.undo.add_undo (UndoManager.UndoAction (self, UndoManager.DELETE_LETTER, self.undo_text_action, self.b_f_i (offset), local_text, len(local_text), local_bytes, old_attrs, changes)) self.emit ("title_changed", self.text) self.bindex = self.bindex_from_index (self.index) self.emit ("update_view") def preedit_changed (self, imcontext, mode): self.preedit = imcontext.get_preedit_string () if self.preedit[0] == '': self.preedit = None self.recalc_edges () self.emit ("update_view") def retrieve_surroundings (self, imcontext, mode): imcontext.set_surrounding (self.text, -1, self.bindex) return True def undo_attr_cb(self, action, mode): self.undo.block() if mode == UndoManager.UNDO: if action.undo_type == UNDO_REMOVE_ATTR: self.current_attrs.append(action.args[0]) elif action.undo_type == UNDO_ADD_ATTR: self.current_attrs.remove(action.args[0]) elif action.undo_type == UNDO_REMOVE_ATTR_SELECTION: self.attributes = action.args[0].copy() elif action.undo_type == UNDO_ADD_ATTR_SELECTION: self.attributes = action.args[0].copy() else: if action.undo_type == UNDO_REMOVE_ATTR: self.current_attrs.remove(action.args[0]) elif action.undo_type == UNDO_ADD_ATTR: self.current_attrs.append(action.args[0]) elif action.undo_type == UNDO_REMOVE_ATTR_SELECTION: self.attributes = action.args[1].copy() elif action.undo_type == UNDO_ADD_ATTR_SELECTION: self.attributes = action.args[1].copy() self.recalc_edges() self.emit("update_view") self.undo.unblock() def create_attribute(self, attribute, start, end, value): if attribute == 'bold': return pango.AttrWeight(value, start, end) elif attribute == 'italic': return pango.AttrStyle(value, start, end) elif attribute == 'underline': return pango.AttrUnderline(value, start, end) def set_attribute(self, active, attribute): if not self.editing: return if attribute == 'bold': pdefault, ptype, pvalue = (pango.WEIGHT_NORMAL, pango.ATTR_WEIGHT, pango.WEIGHT_BOLD) elif attribute == 'italic': pdefault, ptype, pvalue = (pango.STYLE_NORMAL, pango.ATTR_STYLE, pango.STYLE_ITALIC) elif attribute == 'underline': pdefault, ptype, pvalue = (pango.UNDERLINE_NONE, pango.ATTR_UNDERLINE, pango.UNDERLINE_SINGLE) index, end_index = (self.index, self.end_index) init, end = minmax(index, end_index) if not active: attr = self.create_attribute(attribute, init, end, pdefault) if index != end_index: self.attributes.change(attr) if index == end_index: tmp = [] attr = None for x in self.current_attrs: if x.type == ptype and x.value == pvalue: attr = x else: tmp.append(x) self.current_attrs = tmp self.recalc_edges() self.undo.add_undo(UndoManager.UndoAction(self, UNDO_REMOVE_ATTR, \ self.undo_attr_cb,\ attr)) return old_attrs = self.attributes.copy() changed = [] # If we have removed the middle section of a style, split it into # before and after sections. for attrs, (astart, aend) in wrap_attriterator(self.attributes.get_iterator()): if astart <= init and aend >= end: for x in attrs: if x.type == ptype and x.value == pvalue: changed.append(self.create_attribute(attribute, astart, init, pvalue)) changed.append(self.create_attribute(attribute, end, aend, pvalue)) else: changed.append(x) else: changed.extend(attrs) del self.attributes self.attributes = pango.AttrList() for x in changed: self.attributes.change(x) self.current_attrs = [ x for x in self.current_attrs if x.type != ptype or x.value != pvalue ] self.undo.add_undo(UndoManager.UndoAction(self, UNDO_REMOVE_ATTR_SELECTION, self.undo_attr_cb, old_attrs, self.attributes.copy())) else: if index == end_index: attr = self.create_attribute(attribute, index, end_index, pvalue) self.undo.add_undo(UndoManager.UndoAction(self, UNDO_ADD_ATTR, self.undo_attr_cb, attr)) self.current_attrs.append(attr) else: attr = self.create_attribute(attribute, init, end, pvalue) old_attrs = self.attributes.copy() self.attributes.change(attr) self.undo.add_undo(UndoManager.UndoAction(self, UNDO_ADD_ATTR_SELECTION, self.undo_attr_cb, old_attrs, self.attributes.copy())) self.recalc_edges() def set_bold (self, active): self.set_attribute(active, 'bold') def set_italics (self, active): self.set_attribute(active, 'italic') def set_underline (self, active): self.set_attribute(active, 'underline') def set_font (self, font_name): if not self.editing: return start, end = minmax(self.index, self.end_index) pango_font = pango.FontDescription (font_name) attr = pango.AttrFontDesc (pango_font, start, end) if start == end: self.undo.add_undo(UndoManager.UndoAction(self, UNDO_ADD_ATTR, self.undo_attr_cb, attr)) self.current_attrs.append(attr) else: old_attrs = self.attributes.copy() self.attributes.change(attr) self.undo.add_undo(UndoManager.UndoAction(self, UNDO_ADD_ATTR_SELECTION, self.undo_attr_cb, old_attrs, self.attributes.copy())) self.recalc_edges() def get_popup_menu_items(self): return [] labyrinth-0.6/labyrinth_lib/TrayIcon.py000066400000000000000000000051431204476542500203130ustar00rootroot00000000000000# TrayIcon.py # This file is part of Labyrinth # # Copyright (C) 2006 - Andreas Sliwka # # Labyrinth 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. # # Labyrinth 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 Labyrinth; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, # Boston, MA 02110-1301 USA # """ this module implements a tray icon for Labyrinth. As of now it only brings the application to front if it is clicked. """ import sys import gtk class TrayIcon(object): """This is possibly the thinnest wrapper class I've written. Ever. It's a tray icon that you can parameterize during initialisation with the name or file of an icon, with a menu and a simple callback It will create such an Icon, will display the image, call back the callback when left clicked and pop up the menu when right clicked. """ def __init__(self, icon_name="TestTrayIcon", icon_file=None, menu=None, activate=None): # thats so incredibly simple! if icon_file: self.status_icon=gtk.status_icon_new_from_file(icon_file) else: self.status_icon=gtk.status_icon_new_from_icon_name(icon_name) # connect the menu and the callback if given if menu: self.connect_popup_menu(menu) if activate: self.connect_activate(activate) def connect_activate(self, method): def activate_callback(status_icon, *data): method() self.status_icon.connect("activate", activate_callback) def connect_popup_menu(self, menu): def popup_menu_callback(status_icon, button, activate_time, *data): menu.popup(None, None, gtk.status_icon_position_menu, button, activate_time, status_icon) self.status_icon.connect("popup-menu", popup_menu_callback) if __name__ == "__main__": menu = gtk.Menu() quit_item = gtk.MenuItem("Quit") quit_item.connect("activate", gtk.main_quit) menu.add(quit_item) menu.show_all() yell_at_them = lambda : sys.stdout.write("you hit %s...\n" % trayicon) trayicon = TrayIcon(icon_name="labyrinth", menu=menu, activate=yell_at_them) gtk.main() labyrinth-0.6/labyrinth_lib/UndoManager.py000066400000000000000000000210221204476542500207550ustar00rootroot00000000000000# UndoManager.py # This file is part of Labyrinth # # Copyright (C) 2006 - Don Scorgie # # Labyrinth 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. # # Labyrinth 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 Labyrinth; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, # Boston, MA 02110-1301 USA # # Different modes of operation - redo, undo UNDO = 0 REDO = 1 # Some general actions we should always expect. # Some require special handling within ourselves # (taking care of letter insertion / word insertion) INSERT_LETTER = 100 INSERT_WORD = 101 DELETE_LETTER = 102 DELETE_WORD = 103 TRANSFORM_CANVAS = 104 class UndoAction: def __init__(self, owner, undo_type, callback, *args): self.owner = owner self.undo_type = undo_type self.callback = callback self.text = "" if undo_type == INSERT_LETTER or undo_type == INSERT_WORD or undo_type == DELETE_LETTER or \ undo_type == DELETE_WORD: for z in args: if isinstance(z, basestring): self.text = z break self.args = args def add_arg (self, *args): for t in args: self.args += (t,) class UndoManager: ''' A basic manager for undoing and redoing actions.\ Doesn't do anything itself, instead it marshals \ all the minion classes to do its bidding. Any class \ can add items to its lists and they're corresponding \ methods will be called if and when needed. The \ manager doesn't care what you give it, so long as it has a method to call and an owner''' def __init__(self, top_owner, undo_widget = None, redo_widget = None): self.undo = undo_widget self.redo = redo_widget self.blocked = False self.undo_list = [] self.redo_list = [] if self.undo: self.undo.connect('activate', self.undo_action) if self.redo: self.redo.connect('activate', self.redo_action) self.owner = top_owner self.update_sensitive () def block (self): ''' Used as generally, when an undo is performed a \ signal will be emitted that causes an undo action \ to be added. Use this to block tht from happening \ To add actions again, call unblock''' self.blocked = True def unblock (self): self.blocked = False def set_widgets (self, undo, redo): self.undo = undo self.redo = redo self.undo.connect('activate', self.undo_action) self.redo.connect('activate', self.redo_action) self.update_sensitive () def update_sensitive (self): if not self.undo or not self.redo: return self.undo.set_sensitive(len(self.undo_list) > 0) self.redo.set_sensitive(len(self.redo_list) > 0) def undo_action (self, arg): result = self.undo_list.pop() self.redo_list.append (result) self.update_sensitive () result.callback (result, mode=UNDO) def redo_action (self, arg): result = self.redo_list.pop() self.undo_list.append (result) self.update_sensitive () result.callback (result, mode=REDO) def combine_insertions (self, action): final_text = action.text start_iter = action.args[0] length = action.args[2] owner = action.owner cb = action.callback old_attrs = action.args[3] new_attrs = action.args[4] if len (self.undo_list) > 0: back = self.undo_list.pop () else: self.undo_list.append (action) return add_back = True while back and back.owner == owner \ and (back.undo_type == INSERT_LETTER or back.undo_type == INSERT_WORD): if back.text.rfind(' ') != -1: break old_attrs = back.args[3] if back.args[0] <= start_iter: start_iter = back.args[0] final_text = back.text+final_text else: final_text += back.text length += back.args[2] if len (self.undo_list) == 0: add_back = False break back = self.undo_list.pop () if add_back: self.undo_list.append (back) combi = UndoAction (owner, INSERT_WORD, cb, start_iter, final_text, length, old_attrs, new_attrs) self.undo_list.append (combi) def combine_deletions (self, action): bytes = True byte_collection = action.args[3] final_text = action.text start_iter = action.args[0] length = action.args[2] owner = action.owner cb = action.callback old_attrs = action.args[4] new_attrs = action.args[5] if len (self.undo_list) > 0: back = self.undo_list.pop () else: self.undo_list.append (action) return add_back = True while back and back.owner == owner \ and (back.undo_type == DELETE_LETTER or back.undo_type == DELETE_WORD): if back.text.rfind(' ') != -1: break old_attrs = back.args[4] if back.args[0] <= start_iter: start_iter = back.args[0] final_text = back.text+final_text if bytes: byte_collection = back.args[3] + byte_collection else: final_text += back.text if bytes: byte_collection += back.args[3] length += back.args[2] if len (self.undo_list) == 0: add_back = False break back = self.undo_list.pop () if add_back: self.undo_list.append (back) if bytes: combi = UndoAction (owner, DELETE_WORD, cb, start_iter, final_text, length, byte_collection, old_attrs, new_attrs) else: combi = UndoAction (owner, DELETE_WORD, cb, start_iter, final_text, length, -1, old_attrs, new_attrs) self.undo_list.append (combi) def combine_transforms (self, action): if len (self.undo_list) > 0: back = self.undo_list.pop () else: self.undo_list.append (action) return add_back = True final_zoom = action.args[1] final_trans = action.args[3] orig_zoom = action.args[0] orig_trans = action.args[2] owner = action.owner cb = action.callback while back and back.owner == owner and \ back.undo_type == TRANSFORM_CANVAS: orig_zoom = back.args[0] orig_trans = back.args[2] if len (self.undo_list) == 0: add_back = False break back = self.undo_list.pop () if add_back: self.undo_list.append (back) self.undo_list.append (UndoAction (owner, TRANSFORM_CANVAS, cb, orig_zoom, final_zoom, orig_trans, final_trans)) def peak (self): if len (self.undo_list) > 0: return self.undo_list[-1] else: return UndoAction (None, None, None) def pop (self): if len (self.undo_list) > 0: return self.undo_list.pop () else: return None def exists_undo_action (self): return len(self.undo_list) > 0 def exists_redo_action (self): return len(self.redo_list) > 0 def add_undo (self, action): if self.blocked: return if not isinstance(action, UndoAction): print "Error: Not a valid undo action. Ignoring." return del self.redo_list[:] if action.undo_type == INSERT_LETTER: self.combine_insertions (action) elif action.undo_type == DELETE_LETTER: self.combine_deletions (action) elif action.undo_type == TRANSFORM_CANVAS: self.combine_transforms (action) else: self.undo_list.append (action) self.update_sensitive () labyrinth-0.6/labyrinth_lib/__init__.py000066400000000000000000000000241204476542500203130ustar00rootroot00000000000000__version__ = "0.6" labyrinth-0.6/labyrinth_lib/debug.py000066400000000000000000000006341204476542500176510ustar00rootroot00000000000000"""Debugging functions""" def show_attrlist(al): """Display a pango attribute list.""" it = al.get_iterator() def show_range(): print "%d-%d:" % it.range(), for x in it.get_attrs(): print (x.type, x.start_index, x.end_index), if hasattr(x, 'value'): print x.value, print show_range() while it.next(): show_range() labyrinth-0.6/labyrinth_lib/prefs.py000066400000000000000000000020121204476542500176720ustar00rootroot00000000000000# prefs.py # This file is part of Labyrinth # # Copyright (C) 2006 - Don Scorgie # # Labyrinth 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. # # Labyrinth 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 Labyrinth; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, # Boston, MA 02110-1301 USA # # Generally available prefs for all sorts of interesting stuff import gtk _dirn = None def init (): global _dirn _dirn = gtk.widget_get_default_direction () def get_direction (): global _dirn return _dirn init () labyrinth-0.6/labyrinth_lib/utils.py000066400000000000000000000157521204476542500177320ustar00rootroot00000000000000# functions.py # This file is part of labyrinth # # Copyright (C) 2006 - Don Scorgie # - Andreas Sliwka # # labyrinth 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. # # labyrinth 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 Labyrinth; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, # Boston, MA 02110-1301 USA # # This file defines various useful functions # that can be accessed from anywhere :) import sys from os.path import join, dirname, exists, isdir, isfile import os import warnings from numpy import array from xdg import BaseDirectory __BE_VERBOSE=os.environ.get('DEBUG_LABYRINTH',0) if __BE_VERBOSE: def print_debug(*data): sys.stderr.write("\n".join(data) + "\n") else: def print_debug(*data): pass # FIXME: this is a no-go, but fast and efficient # global variables use_bezier_curves = False default_colors = { "text" : (0.0, 0.0, 0.0), "fg" : (0.0, 0.0, 0.0), "bg" : (0.0, 0.0, 0.0), "base" : (0.0, 0.0, 0.0) } selected_colors = { "text" : (0.0, 0.0, 0.0), "fg" : (0.0, 0.0, 0.0), "bg" : (0.0, 0.0, 0.0), "border" : (0.0, 0.0, 0.0), # bounding box "fill" : (0.0, 0.0, 0.0) # bounding box } default_font = None def get_save_dir (): ''' Returns the path to the directory to save the maps to ''' if os.name == 'nt': savedir = os.path.join(os.path.expanduser('~'), '.labyrinth') if not os.access (savedir, os.W_OK): os.makedirs (savedir) return savedir old_savedir = os.path.join (os.path.expanduser('~'), ".gnome2", "labyrinth") savedir = BaseDirectory.save_data_path("labyrinth") # Migrate maps to the new save directory. if os.path.exists(old_savedir) and os.path.isdir(old_savedir): for m in os.listdir(old_savedir): try: os.rename(os.path.join(old_savedir, m), os.path.join(savedir, m)) except Exception as e: warnings.warn("Failed to migrate %s: %s" % (m, e)) # remove old dir try: os.rmdir(old_savedir) except Exception as e: warnings.warn("Could not remove old map dir (%s): %s" % (old_savedir, e)) return savedir def get_images_dir (): return os.path.join(get_save_dir(), 'images') def parse_coords (string): if string == "None": return None local = string[1:string.find(',')] local_2 = string[string.find (',')+1:string.find(')')] coord = (float(local), float(local_2)) return coord __data_dir = None def get_data_dir(): '''returns the data dir. Tries to find it the first time its called''' global __data_dir if os.name != 'nt': if __data_dir is None: #decide wether we run under development or if the program has been installed path = join(dirname(__file__), '..') if exists(path) and isdir(path) and isfile(path+"/AUTHORS"): __data_dir = os.sep.join([dirname(__file__), '..' , 'data']) else: __data_dir = "/usr/share/labyrinth" else: if __data_dir is None: __data_dir = join (".","data") return __data_dir def get_data_file_name (file_name): ''' takes a string and returns it with the data directory prepended.''' return os.path.join(get_data_dir(), file_name) def get_data_file (file_name): ''' takes a string and either returns a data file of that name or raises an exception if it cant find it ''' return open(get_data_file_name(file_name)) # Drawing functions # These are thought outline styles. # Currently, there is only 1 - STYLE_NORMAL, which is the slightly rounded corners # - The normal thought type STYLE_NORMAL = 0 STYLE_EXTENDED_CONTENT = 1 def draw_thought_outline (context, ul, lr, background_color, am_root = False, am_primary = False, style=STYLE_NORMAL): draw_thought_extended(context, ul, lr, am_root, am_primary, background_color, style == STYLE_EXTENDED_CONTENT) # This is used to find the required margin from the (real) ul / lr coords to the edge of the # box area. Makes selection of thoughts less erratic def margin_required (style = STYLE_NORMAL): if style == STYLE_NORMAL: return margin_thought_classic () else: print "Error: Unknown thought margine style: "+str(style) # Classic thought style drawing code def margin_thought_classic (): return (5, 5, 5, 5) def gtk_to_cairo_color(color): return (color.red / 65535.0, color.green / 65535.0, color.blue / 65535.0) def draw_thought_extended (context, ul, lr, am_root, am_primary, background_color, fatborder=False, dashborder=False): context.move_to (ul[0], ul[1]+5) context.line_to (ul[0], lr[1]-5) context.curve_to (ul[0], lr[1], ul[0], lr[1], ul[0]+5, lr[1]) context.line_to (lr[0]-5, lr[1]) context.curve_to (lr[0], lr[1], lr[0], lr[1], lr[0], lr[1]-5) context.line_to (lr[0], ul[1]+5) context.curve_to (lr[0], ul[1], lr[0], ul[1], lr[0]-5, ul[1]) context.line_to (ul[0]+5, ul[1]) context.curve_to (ul[0], ul[1], ul[0], ul[1], ul[0], ul[1]+5) if am_root: bg = selected_colors["bg"] context.set_source_rgb (bg[0], bg[1], bg[2]) elif am_primary: context.set_source_rgb (0.937, 0.831, 0.000) else: r,g,b = gtk_to_cairo_color(background_color) context.set_source_rgb (r, g, b) context.fill_preserve () context.set_source_rgb (0,0,0) if dashborder: context.set_dash([4.0], 0.0) if fatborder: orig_line_width = context.get_line_width () context.set_line_width (5.0) context.stroke () context.set_line_width (orig_line_width) else: context.stroke () if dashborder: context.set_dash([], 0.0) # Export outline stuff def export_thought_outline (context, ul, lr, background_color, am_root = False, am_primary = False, style=STYLE_NORMAL, move=(0,0)): real_ul = (ul[0]+move[0], ul[1]+move[1]) real_lr = (lr[0]+move[0], lr[1]+move[1]) draw_thought_extended (context, real_ul, real_lr, False, am_primary, background_color, style == STYLE_EXTENDED_CONTENT) def pixbuf_to_cairo (pixel_array): result = [] for y in pixel_array: row = [] for x in y: color = [int(x[2][0]), int(x[1][0]), int(x[0][0])] if len(x) == 3: color.append(255) elif len(x) == 4: color.append(int(x[3][0])) row.append(color) result.append(row) return array(result, 'b') labyrinth-0.6/po/000077500000000000000000000000001204476542500140025ustar00rootroot00000000000000labyrinth-0.6/po/ChangeLog000066400000000000000000000054511204476542500155610ustar00rootroot000000000000002011-04-23 Matthias Vogelgesang * po/zh_CN.po: Added simplified Chinese translation 2011-04-23 Matthias Vogelgesang * po/de.po: Updated German translation 2011-04-23 Matthias Vogelgesang * po/pt_BR.po: Fixed issue 142 2008-03-26 Don Scorgie * LINGUAS: * fa.po: Add Persian translation by Pedram Azimaie 2008-03-24 Matthias Vogelgesang * po/de.po Updated German translation. 2007-04-07 Don Scorgie * pt_BR.po: Fix build issue 2007-03-10 Don Scorgie * pt_BR.po: Updated Brazilian Portugese translation (Leonardo Gregianin) 2006-12-04 Don Scorgie * ru.po: Updated Russian translation from Alexandre Prokoudine 2006-11-25 Don Scorgie * it.po: mv it_IT.po it.po Fix build again ;) (issue #40) 2006-11-15 Don Scorgie * it_IT.po: * LINGUAS: Add Italian Translation (Francesco Fullone) ======= 0.3 ======= 2006-11-08 Don Scorgie * de.po: Minor update to German (Florian Ludwig) * pt_PT.po: Small updates to European Portugese (Luis Gomes) 2006-11-07 Don Scorgie * de.po: Add German translation (Raphael Schmid) * sv.po: Add Swedish translation (Robin Sonefors) * ca.po: Another Catalan update (Gil Forcada) * LINGUAS: * eu.po: Add Basque translation (Zunbeltz Izaola) * pt_PT.po: Add European Portugese translation (Luis Gomes) * ca.po: Updated Catalan translation (Gil Forcada) * nl.po: Updated Dutch translation (Max Beauchez) * cz.po: Updated Czech translation (Josef Vybíral) * fr.po: Updated French translation (Jean-François Fortin Tam) 2006-11-06 Don Scorgie * labyrinth.pot: Update for new strings * fr.po: * LINGUAS: Add French translation (Mathieu Leduc-Hamel) 2006-10-21 Don Scorgie * LINGUAS: * cs.po: Add Czech translation (Josef Vybíral) 2006-10-18 Don Scorgie * pt_BR.po: Fix compilation error * LINGUAS: * ca.po: Added Catalan Translation (Gil Forcada) 2006-10-16 Don Scorgie * LINGUAS: * pt_BR.po: Added Brazilian Portugese Translation (Leonardo Gregianin) 2006-10-11 Don Scorgie * LINGUAS: * pl.po: Add Polish translation (Tomasz Dominikowski) * LINGUAS: * nl.po: Add Dutch translation (Rigo Ketelings) * labyrinth.pot: Add convenience file to SVN for translators 2006-10-09 Don Scorgie * LINGUAS: * ru.po: Add Russian Translation (Alexandre Prokoudine) :) labyrinth-0.6/po/LINGUAS000066400000000000000000000001461204476542500150300ustar00rootroot00000000000000# please keep this list sorted alphabetically # ca cs de es eu fa fr it nl pl pt_BR pt_PT ru sv zh_CN labyrinth-0.6/po/Makefile000066400000000000000000000022571204476542500154500ustar00rootroot00000000000000LANGS=ca cs de es eu fa fr it nl pl pt_BR pt_PT ru sv zh_CN LANG_FOLDERS:=$(addprefix $(localedir)/,$(LANGS)) INST_MO:=$(addsuffix /LC_MESSAGES/labyrinth.mo,$(LANG_FOLDERS)) # Translate to binary message format %.mo: %.po msgfmt -o $@ $< all-mo: $(LANGS:%=%.mo) # The installation rule $(localedir)/%/LC_MESSAGES/labyrinth.mo : %.mo install -D -m 644 $< $@ install: all-mo $(INST_MO) labyrinth.pot: xgettext --language=Python --keyword=_ --output=$@ `find ../labyrinth_lib -name "*.py"` xgettext --output=$@ --join-existing ../data/labyrinth.glade update-%-po: @echo -n "Updating $*.po" @result="`msgmerge -o $*.new.po $*.po labyrinth.pot`"; \ if $$result; then \ if cmp $*.po $*.new.po >/dev/null 2>&1; then \ # No changes - discard the new file \ rm -f $*.new.po; \ else \ # File has changed - new file replaces the old \ if mv -f $*.new.po $*.po; then \ :; \ else \ echo "msgmerge for $*.po failed: cannot move $*.new.po to $*.po" 1>&2; \ rm -f $*.new.po; \ exit 1; \ fi; \ fi; \ else \ echo "msgmerge for $*.gmo failed!"; \ rm -f $*.new.po; \ fi; \ update-po: labyrinth.pot $(LANGS:%=update-%-po) clean: rm -rf *.mo rm -rf *.new.po labyrinth-0.6/po/POTFILES.in000066400000000000000000000003241204476542500155560ustar00rootroot00000000000000# List of source files containing translatable strings. [encoding: UTF-8] src/Browser.py src/MainWindow.py src/DrawingThought.py src/MMapArea.py src/ImageThought.py data/labyrinth.glade data/labyrinth.desktop.in labyrinth-0.6/po/POTFILES.skip000066400000000000000000000000001204476542500161050ustar00rootroot00000000000000labyrinth-0.6/po/ca.po000066400000000000000000000204431204476542500147300ustar00rootroot00000000000000# labrynth translation to Catalan. # Copyright (C) 2006 labrynth package # Gil Forcada , 2006 # msgid "" msgstr "" "Project-Id-Version: 0.3\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2012-09-23 18:55+0100\n" "PO-Revision-Date: 2006-11-07 15:20+0100\n" "Last-Translator: Gil Forcada \n" "Language-Team: Catalan \n" "Language: ca\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" #: ../labyrinth_lib/ImageThought.py:68 msgid "Choose image to insert" msgstr "Escolliu la imatge a inserir" #: ../labyrinth_lib/ImageThought.py:323 msgid "Error loading file" msgstr "S'ha produït un error en carregar el fitxer" #: ../labyrinth_lib/ImageThought.py:324 #, python-format msgid "%s could not be found. Associated thought will be empty." msgstr "No s'ha pogut trobar %s. El pensament associat estarà buit." #: ../labyrinth_lib/ImageThought.py:339 msgid "Change Image" msgstr "" #: ../labyrinth_lib/Browser.py:192 #, python-format msgid "Unable to display help: %s" msgstr "" #: ../labyrinth_lib/Browser.py:223 msgid "Translation by Don Scorgie" msgstr "" #: ../labyrinth_lib/Browser.py:245 #, fuzzy msgid "The map cannot be deleted right now. Is it open?" msgstr "No es pot suprimir el mapa ara mateix. Està obert?" #: ../labyrinth_lib/Browser.py:247 msgid "The map has no associated filename." msgstr "El mapa no té un nom de fitxer associat." #: ../labyrinth_lib/Browser.py:250 msgid "Cannot delete this map" msgstr "No s'ha pogut suprimir el mapa" #: ../labyrinth_lib/Browser.py:257 msgid "Do you really want to delete this Map?" msgstr "Realment voleu suprimir aquest mapa?" #: ../labyrinth_lib/Browser.py:282 #, fuzzy msgid "Open File" msgstr "Fitxer" #: ../labyrinth_lib/Browser.py:286 msgid "MAPZ Compressed Map (*.mapz)" msgstr "" #: ../labyrinth_lib/Browser.py:317 msgid "Map Name" msgstr "Nom del mapa" #: ../labyrinth_lib/Browser.py:324 msgid "Last Modified" msgstr "" #: ../labyrinth_lib/Links.py:265 msgid "Choose Color" msgstr "" #: ../labyrinth_lib/Links.py:278 msgid "Set Color" msgstr "" #: ../labyrinth_lib/MainWindow.py:166 ../labyrinth_lib/MainWindow.py:481 #, fuzzy msgid "Untitled Map" msgstr "Mapa sense nom %d" #: ../labyrinth_lib/MainWindow.py:213 msgid "File" msgstr "Fitxer" #: ../labyrinth_lib/MainWindow.py:214 msgid "Export as Image" msgstr "Exporta com a imatge" #: ../labyrinth_lib/MainWindow.py:215 msgid "Export your map as an image" msgstr "Exporteu el vostre mapa com a imatge" #: ../labyrinth_lib/MainWindow.py:216 #, fuzzy msgid "Export Map..." msgstr "Exporta el mapa" #: ../labyrinth_lib/MainWindow.py:217 #, fuzzy msgid "Export your map as XML" msgstr "Exporteu el vostre mapa com a imatge" #: ../labyrinth_lib/MainWindow.py:219 msgid "Close the current window" msgstr "Tanca la finestra actual" #: ../labyrinth_lib/MainWindow.py:220 msgid "_Edit" msgstr "_Edita" #: ../labyrinth_lib/MainWindow.py:221 msgid "_View" msgstr "" #: ../labyrinth_lib/MainWindow.py:222 msgid "_Toolbar" msgstr "" #: ../labyrinth_lib/MainWindow.py:231 #, fuzzy msgid "Link Thoughts" msgstr "Enllaça/Desenllaça els pensaments" #: ../labyrinth_lib/MainWindow.py:232 #, fuzzy msgid "Link the selected thoughts" msgstr "Enllaça/Desenllaça els pensaments seleccionats" #: ../labyrinth_lib/MainWindow.py:233 msgid "_Mode" msgstr "_Mode" #: ../labyrinth_lib/MainWindow.py:241 msgid "_Edit Mode" msgstr "Mode d'_edició" #: ../labyrinth_lib/MainWindow.py:242 msgid "Turn on edit mode" msgstr "Activa el mode d'edició" #: ../labyrinth_lib/MainWindow.py:243 msgid "_Add Image" msgstr "_Afegeix una imatge" #: ../labyrinth_lib/MainWindow.py:244 msgid "Add an image to selected thought" msgstr "Afegeix una imatge al pensament seleccionat" #: ../labyrinth_lib/MainWindow.py:245 msgid "_Drawing Mode" msgstr "_Mode de dibuix" #: ../labyrinth_lib/MainWindow.py:246 msgid "Make a pretty drawing" msgstr "Fes un dibuix bonic" #: ../labyrinth_lib/MainWindow.py:248 msgid "Use _Curves" msgstr "" #: ../labyrinth_lib/MainWindow.py:249 msgid "Use curves as links" msgstr "" #: ../labyrinth_lib/MainWindow.py:250 msgid "Use _Lines" msgstr "" #: ../labyrinth_lib/MainWindow.py:251 msgid "Use straight lines as links" msgstr "" #: ../labyrinth_lib/MainWindow.py:253 msgid "_Extended Information" msgstr "" #: ../labyrinth_lib/MainWindow.py:254 #, fuzzy msgid "Show extended information for thoughts" msgstr "Visualitza informació addicional per als pensaments" #: ../labyrinth_lib/MainWindow.py:255 msgid "_Main" msgstr "" #: ../labyrinth_lib/MainWindow.py:256 msgid "Show main toolbar" msgstr "" #: ../labyrinth_lib/MainWindow.py:257 msgid "_Format" msgstr "" #: ../labyrinth_lib/MainWindow.py:258 msgid "Show format toolbar" msgstr "" #: ../labyrinth_lib/MainWindow.py:536 msgid "Save File As" msgstr "" #: ../labyrinth_lib/MainWindow.py:630 #, fuzzy msgid "All Files" msgstr "Fitxer" #: ../labyrinth_lib/MainWindow.py:631 msgid "PNG Image (*.png)" msgstr "" #: ../labyrinth_lib/MainWindow.py:632 msgid "JPEG Image (*.jpg, *.jpeg)" msgstr "" #: ../labyrinth_lib/MainWindow.py:633 msgid "SVG Vector Image (*.svg)" msgstr "" #: ../labyrinth_lib/MainWindow.py:634 msgid "PDF Portable Document (*.pdf)" msgstr "" #: ../labyrinth_lib/MainWindow.py:670 msgid "Unknown file format" msgstr "Format de fitxer desconegut" #: ../labyrinth_lib/MainWindow.py:671 #, fuzzy, python-format msgid "" "The file type '%s' is unsupported. Please use the suffix '.png', '.jpg' or " "'.svg'." msgstr "" "No està implementat el tipus de fitxer «%s». Feu servir el sufix «.png» o «." "jpg»" #: ../labyrinth_lib/ResourceThought.py:128 #, fuzzy msgid "Edit Text" msgstr "Mode d'_edició" #: ../labyrinth_lib/ResourceThought.py:133 #, fuzzy msgid "Edit URI" msgstr "_Edita" #: ../labyrinth_lib/DrawingThought.py:65 #, python-format msgid "Drawing #%d" msgstr "Dibuix #%d" #: ../data/labyrinth.glade:7 msgid "Export Map as Image" msgstr "Exporta el mapa com a imatge" #: ../data/labyrinth.glade:87 msgid "Complete Map" msgstr "Mapa complet" #: ../data/labyrinth.glade:101 msgid "Visible Area" msgstr "Àrea visible" #: ../data/labyrinth.glade:157 msgid "Width" msgstr "Amplada" #: ../data/labyrinth.glade:172 msgid "Height" msgstr "Altura" #: ../data/labyrinth.glade:226 msgid "Export Map" msgstr "Exporta el mapa" #: ../data/labyrinth.glade:245 msgid "Labyrinth Maps" msgstr "Mapes Labyrinth" #: ../data/labyrinth.glade:259 msgid "_File" msgstr "_Fitxer" #: ../data/labyrinth.glade:299 msgid "Import..." msgstr "" #: ../data/labyrinth.glade:329 msgid "_Help" msgstr "A_juda" #: ../data/labyrinth.glade:765 msgid "URL" msgstr "" #: ../data/labyrinth.glade:806 msgid "Align Left" msgstr "" #: ../data/labyrinth.glade:825 msgid "Align Right" msgstr "" #: ../data/labyrinth.glade:844 msgid "Align Vertical Center" msgstr "" #: ../data/labyrinth.glade:863 msgid "Align Top" msgstr "" #: ../data/labyrinth.glade:882 msgid "Align Bottom" msgstr "" #: ../data/labyrinth.glade:901 msgid "Align Horizontal Center" msgstr "" #~ msgid "_Delete Selected Thoughts" #~ msgstr "_Suprimeix els pensaments seleccionats" #~ msgid "Delete the selected element(s)" #~ msgstr "Suprimeix els elements seleccionats" #~ msgid "_View Extended" #~ msgstr "_Visualització estesa" #~ msgid "Labyrinth Mind-mapping" #~ msgstr "Creació de mapes mentals Labyrinth" #~ msgid "Map your mind" #~ msgstr "Mapejeu la vostra memòria" #~ msgid "Mind-mapping" #~ msgstr "Mapa mental" #~ msgid "Learn about the application" #~ msgstr "Aprèn sobre l'aplicació" #~ msgid "Delete Map" #~ msgstr "Suprimeix el mapa" #~ msgid "New Map" #~ msgstr "Nou mapa" #~ msgid "Open Map" #~ msgstr "Obre un mapa" #~ msgid "Quit" #~ msgstr "Surt" #~ msgid "_New" #~ msgstr "_Nou" #~ msgid "Create a new mind-map" #~ msgstr "Crea un nou mapa mental" #~ msgid "_Close" #~ msgstr "_Tanca" #~ msgid "_Quit" #~ msgstr "_Surt" #~ msgid "Close all the windows and exit the application" #~ msgstr "Hi ha algunes coses trencades" #~ msgid "_About" #~ msgstr "_Quant a" #~ msgid "Somethings broken" #~ msgstr "Hi ha algunes coses trencades" #~ msgid "_Move Mode" #~ msgstr "Mode de _moviment" #~ msgid "Turn on move mode" #~ msgstr "Activa el mode de moviment" #~ msgid "%s could not be read. Please ensure its a valid image." #~ msgstr "" #~ "No s'ha pogut llegir %s. Assegureu-vos de que és una imatge vàlida." labyrinth-0.6/po/cs.po000066400000000000000000000210671204476542500147550ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # msgid "" msgstr "" "Project-Id-Version: Labyrinth svn\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2012-09-23 18:55+0100\n" "PO-Revision-Date: 2006-11-07 15:57+0100\n" "Last-Translator: Josef Vybíral \n" "Language-Team: \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Language: Czech\n" "X-Poedit-Country: CZECH REPUBLIC\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" #: ../labyrinth_lib/ImageThought.py:68 msgid "Choose image to insert" msgstr "Vyberte obrázek, který chcete vložit" #: ../labyrinth_lib/ImageThought.py:323 msgid "Error loading file" msgstr "Chyba při otevírání obrázku" #: ../labyrinth_lib/ImageThought.py:324 #, python-format msgid "%s could not be found. Associated thought will be empty." msgstr "Nebylo možné nalézt soubor %s. Myšlenka zůstane prázdná." #: ../labyrinth_lib/ImageThought.py:339 msgid "Change Image" msgstr "" #: ../labyrinth_lib/Browser.py:192 #, python-format msgid "Unable to display help: %s" msgstr "" #: ../labyrinth_lib/Browser.py:223 msgid "Translation by Don Scorgie" msgstr "" #: ../labyrinth_lib/Browser.py:245 #, fuzzy msgid "The map cannot be deleted right now. Is it open?" msgstr "Tuto mapu nelze v tomto okamžiku smazat. Není otevřená?" #: ../labyrinth_lib/Browser.py:247 msgid "The map has no associated filename." msgstr "Mapa nemá přiřazeno žádné jméno" #: ../labyrinth_lib/Browser.py:250 msgid "Cannot delete this map" msgstr "Tuto mapu nelze smazat" #: ../labyrinth_lib/Browser.py:257 msgid "Do you really want to delete this Map?" msgstr "Opravdu chcete smazat tuto mapu?" #: ../labyrinth_lib/Browser.py:282 #, fuzzy msgid "Open File" msgstr "Soubor" #: ../labyrinth_lib/Browser.py:286 msgid "MAPZ Compressed Map (*.mapz)" msgstr "" #: ../labyrinth_lib/Browser.py:317 msgid "Map Name" msgstr "Jméno mapy" #: ../labyrinth_lib/Browser.py:324 msgid "Last Modified" msgstr "" #: ../labyrinth_lib/Links.py:265 msgid "Choose Color" msgstr "" #: ../labyrinth_lib/Links.py:278 msgid "Set Color" msgstr "" #: ../labyrinth_lib/MainWindow.py:166 ../labyrinth_lib/MainWindow.py:481 #, fuzzy msgid "Untitled Map" msgstr "Nepojmenovaná Mapa %d" #: ../labyrinth_lib/MainWindow.py:213 msgid "File" msgstr "Soubor" #: ../labyrinth_lib/MainWindow.py:214 msgid "Export as Image" msgstr "Exportovat jako obrázek" #: ../labyrinth_lib/MainWindow.py:215 msgid "Export your map as an image" msgstr "Vyexportuje vaši mapu jako obrázek" #: ../labyrinth_lib/MainWindow.py:216 #, fuzzy msgid "Export Map..." msgstr "Exportovat Mapu" #: ../labyrinth_lib/MainWindow.py:217 #, fuzzy msgid "Export your map as XML" msgstr "Vyexportuje vaši mapu jako obrázek" #: ../labyrinth_lib/MainWindow.py:219 msgid "Close the current window" msgstr "Zavřít současné okno" #: ../labyrinth_lib/MainWindow.py:220 msgid "_Edit" msgstr "_Úpravy" #: ../labyrinth_lib/MainWindow.py:221 msgid "_View" msgstr "" #: ../labyrinth_lib/MainWindow.py:222 msgid "_Toolbar" msgstr "" #: ../labyrinth_lib/MainWindow.py:231 #, fuzzy msgid "Link Thoughts" msgstr "Odpojit/Propojit myšlenky" #: ../labyrinth_lib/MainWindow.py:232 #, fuzzy msgid "Link the selected thoughts" msgstr "Odpojí nebo připojí vybrané myšlenky" #: ../labyrinth_lib/MainWindow.py:233 msgid "_Mode" msgstr "Režim" #: ../labyrinth_lib/MainWindow.py:241 msgid "_Edit Mode" msgstr "R_ežim Úprav" #: ../labyrinth_lib/MainWindow.py:242 msgid "Turn on edit mode" msgstr "Zapne režim úprav" #: ../labyrinth_lib/MainWindow.py:243 msgid "_Add Image" msgstr "Přid_at Obrázek" #: ../labyrinth_lib/MainWindow.py:244 msgid "Add an image to selected thought" msgstr "Vloží obrázek do vybrané myšlenky" #: ../labyrinth_lib/MainWindow.py:245 msgid "_Drawing Mode" msgstr "Režim _Kreslení" #: ../labyrinth_lib/MainWindow.py:246 msgid "Make a pretty drawing" msgstr "Nakreslete něco pěkného" #: ../labyrinth_lib/MainWindow.py:248 msgid "Use _Curves" msgstr "" #: ../labyrinth_lib/MainWindow.py:249 msgid "Use curves as links" msgstr "" #: ../labyrinth_lib/MainWindow.py:250 msgid "Use _Lines" msgstr "" #: ../labyrinth_lib/MainWindow.py:251 msgid "Use straight lines as links" msgstr "" #: ../labyrinth_lib/MainWindow.py:253 msgid "_Extended Information" msgstr "" #: ../labyrinth_lib/MainWindow.py:254 #, fuzzy msgid "Show extended information for thoughts" msgstr "Zobrazí rozšířené informace o myšlenkách" #: ../labyrinth_lib/MainWindow.py:255 msgid "_Main" msgstr "" #: ../labyrinth_lib/MainWindow.py:256 msgid "Show main toolbar" msgstr "" #: ../labyrinth_lib/MainWindow.py:257 msgid "_Format" msgstr "" #: ../labyrinth_lib/MainWindow.py:258 msgid "Show format toolbar" msgstr "" #: ../labyrinth_lib/MainWindow.py:536 msgid "Save File As" msgstr "" #: ../labyrinth_lib/MainWindow.py:630 #, fuzzy msgid "All Files" msgstr "Soubor" #: ../labyrinth_lib/MainWindow.py:631 msgid "PNG Image (*.png)" msgstr "" #: ../labyrinth_lib/MainWindow.py:632 msgid "JPEG Image (*.jpg, *.jpeg)" msgstr "" #: ../labyrinth_lib/MainWindow.py:633 msgid "SVG Vector Image (*.svg)" msgstr "" #: ../labyrinth_lib/MainWindow.py:634 msgid "PDF Portable Document (*.pdf)" msgstr "" #: ../labyrinth_lib/MainWindow.py:670 msgid "Unknown file format" msgstr "Neznámý formát souboru" #: ../labyrinth_lib/MainWindow.py:671 #, fuzzy, python-format msgid "" "The file type '%s' is unsupported. Please use the suffix '.png', '.jpg' or " "'.svg'." msgstr "" "Typ souboru '%s' není podporován. Prosím použijte příponu '.png' nebo '.jpg'" #: ../labyrinth_lib/ResourceThought.py:128 #, fuzzy msgid "Edit Text" msgstr "R_ežim Úprav" #: ../labyrinth_lib/ResourceThought.py:133 #, fuzzy msgid "Edit URI" msgstr "_Úpravy" #: ../labyrinth_lib/DrawingThought.py:65 #, python-format msgid "Drawing #%d" msgstr "Kresba #%d" #: ../data/labyrinth.glade:7 msgid "Export Map as Image" msgstr "Vyexportovat mapu jako obrázek" #: ../data/labyrinth.glade:87 msgid "Complete Map" msgstr "Dokončit mapu" #: ../data/labyrinth.glade:101 msgid "Visible Area" msgstr "Viditelná oblast" #: ../data/labyrinth.glade:157 msgid "Width" msgstr "Šířka" #: ../data/labyrinth.glade:172 msgid "Height" msgstr "Výška" #: ../data/labyrinth.glade:226 msgid "Export Map" msgstr "Exportovat Mapu" #: ../data/labyrinth.glade:245 msgid "Labyrinth Maps" msgstr "Mapy Labyrinth" #: ../data/labyrinth.glade:259 msgid "_File" msgstr "_Soubor" #: ../data/labyrinth.glade:299 msgid "Import..." msgstr "" #: ../data/labyrinth.glade:329 msgid "_Help" msgstr "_Nápověda" #: ../data/labyrinth.glade:765 msgid "URL" msgstr "" #: ../data/labyrinth.glade:806 msgid "Align Left" msgstr "" #: ../data/labyrinth.glade:825 msgid "Align Right" msgstr "" #: ../data/labyrinth.glade:844 msgid "Align Vertical Center" msgstr "" #: ../data/labyrinth.glade:863 msgid "Align Top" msgstr "" #: ../data/labyrinth.glade:882 msgid "Align Bottom" msgstr "" #: ../data/labyrinth.glade:901 msgid "Align Horizontal Center" msgstr "" #~ msgid "_Delete Selected Thoughts" #~ msgstr "Vymazat vybrané myšlenky" #~ msgid "Delete the selected element(s)" #~ msgstr "Vymaže vybrané prvky" #~ msgid "_View Extended" #~ msgstr "Rozšířené zobrazení" #~ msgid "Labyrinth Mind-mapping" #~ msgstr "Labyrinth Myšlenkové mapy" #~ msgid "Map your mind" #~ msgstr "Zmapujte svou mysl" #~ msgid "Mind-mapping" #~ msgstr "Tvorba myšlenkových map" #~ msgid "Learn about the application" #~ msgstr "Více informací o této aplikaci" #~ msgid "Delete Map" #~ msgstr "Vymazat Mapu" #~ msgid "New Map" #~ msgstr "Nová Mapa" #~ msgid "Open Map" #~ msgstr "Otevřít Mapu" #~ msgid "Quit" #~ msgstr "Ukončit" #~ msgid "_New" #~ msgstr "_Nový" #~ msgid "Create a new mind-map" #~ msgstr "Vytvořit novou myšlenkovou mapu" #~ msgid "_Close" #~ msgstr "_Zavřít" #~ msgid "_Quit" #~ msgstr "_Ukončit" #~ msgid "Close all the windows and exit the application" #~ msgstr "Zavřít všechna okna aplikace a skončit" #~ msgid "_About" #~ msgstr "O _aplikaci" #~ msgid "Somethings broken" #~ msgstr "Něco se se rozbilo" #~ msgid "_Move Mode" #~ msgstr "Reži_m přesunu" #~ msgid "Turn on move mode" #~ msgstr "Zapne režim pro přesun objektů" #~ msgid "%s could not be read. Please ensure its a valid image." #~ msgstr "" #~ "Nebylo možné přečíst soubor %s. Ujistěte se prosím, že se skutečně jedná " #~ "o obrázek." labyrinth-0.6/po/de.po000066400000000000000000000173661204476542500147470ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: # , 2012. # Matthias Vogelgesang , 2012. # Raphael J. Schmid , 2008. msgid "" msgstr "" "Project-Id-Version: Labyrinth\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2012-09-23 18:55+0100\n" "PO-Revision-Date: 2012-10-22 06:33+0000\n" "Last-Translator: matthiasv \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: de\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: ../labyrinth_lib/ImageThought.py:68 msgid "Choose image to insert" msgstr "Bild zum Einfügen auswählen" #: ../labyrinth_lib/ImageThought.py:323 msgid "Error loading file" msgstr "Fehler beim Laden der Datei" #: ../labyrinth_lib/ImageThought.py:324 #, python-format msgid "%s could not be found. Associated thought will be empty." msgstr "Konnte %s nicht finden. Verknüpfter Gedanke wird leer sein." #: ../labyrinth_lib/ImageThought.py:339 msgid "Change Image" msgstr "Ändere Bild" #: ../labyrinth_lib/Browser.py:192 #, python-format msgid "Unable to display help: %s" msgstr "Kann Hilfe nicht anzeigen: %s" #: ../labyrinth_lib/Browser.py:223 msgid "Translation by Don Scorgie" msgstr "Übersetzung von Matthias Vogelgesang" #: ../labyrinth_lib/Browser.py:245 msgid "The map cannot be deleted right now. Is it open?" msgstr "Mindmap kann nicht gelöscht werden. Ist sie geöffnet?" #: ../labyrinth_lib/Browser.py:247 msgid "The map has no associated filename." msgstr "Der Mindmap ist kein Dateiname zugewiesen." #: ../labyrinth_lib/Browser.py:250 msgid "Cannot delete this map" msgstr "Mindmap kann nicht gelöscht werden" #: ../labyrinth_lib/Browser.py:257 msgid "Do you really want to delete this Map?" msgstr "Möchten Sie die Mindmap wirklich löschen?" #: ../labyrinth_lib/Browser.py:282 msgid "Open File" msgstr "Öffne Datei" #: ../labyrinth_lib/Browser.py:286 msgid "MAPZ Compressed Map (*.mapz)" msgstr "MAPZ komprimierte Mind Map (*.mapz)" #: ../labyrinth_lib/Browser.py:317 msgid "Map Name" msgstr "Mindmap-Name" #: ../labyrinth_lib/Browser.py:324 msgid "Last Modified" msgstr "Zuletzt modifiziert" #: ../labyrinth_lib/Links.py:265 msgid "Choose Color" msgstr "Farbe wählen" #: ../labyrinth_lib/Links.py:278 msgid "Set Color" msgstr "Farbe festlegen" #: ../labyrinth_lib/MainWindow.py:166 ../labyrinth_lib/MainWindow.py:481 msgid "Untitled Map" msgstr "Unbenannte Mindmap" #: ../labyrinth_lib/MainWindow.py:213 msgid "File" msgstr "Datei" #: ../labyrinth_lib/MainWindow.py:214 msgid "Export as Image" msgstr "Als Bild exportieren" #: ../labyrinth_lib/MainWindow.py:215 msgid "Export your map as an image" msgstr "Exportieren Sie ihre Mindmap als Bild" #: ../labyrinth_lib/MainWindow.py:216 msgid "Export Map..." msgstr "Exportiere Mindmap..." #: ../labyrinth_lib/MainWindow.py:217 msgid "Export your map as XML" msgstr "Exportieren Sie ihre Mindmap als XML" #: ../labyrinth_lib/MainWindow.py:219 msgid "Close the current window" msgstr "Aktuelles Fenster schließen" #: ../labyrinth_lib/MainWindow.py:220 msgid "_Edit" msgstr "B_earbeiten" #: ../labyrinth_lib/MainWindow.py:221 msgid "_View" msgstr "_Ansicht" #: ../labyrinth_lib/MainWindow.py:222 msgid "_Toolbar" msgstr "_Werkzeugleiste" #: ../labyrinth_lib/MainWindow.py:231 msgid "Link Thoughts" msgstr "Gedanken verbinden" #: ../labyrinth_lib/MainWindow.py:232 msgid "Link the selected thoughts" msgstr "Ausgewählte Gedanken verbinden" #: ../labyrinth_lib/MainWindow.py:233 msgid "_Mode" msgstr "_Modus" #: ../labyrinth_lib/MainWindow.py:241 msgid "_Edit Mode" msgstr "Bearbeitungs_modus" #: ../labyrinth_lib/MainWindow.py:242 msgid "Turn on edit mode" msgstr "Bearbeitungsmodus aktivieren" #: ../labyrinth_lib/MainWindow.py:243 msgid "_Add Image" msgstr "_Bild hinzufügen" #: ../labyrinth_lib/MainWindow.py:244 msgid "Add an image to selected thought" msgstr "Dem gewählten Gedanken ein Bild hinzufügen" #: ../labyrinth_lib/MainWindow.py:245 msgid "_Drawing Mode" msgstr "Zeichenmo_dus" #: ../labyrinth_lib/MainWindow.py:246 msgid "Make a pretty drawing" msgstr "Hübsche Zeichnung erstellen" #: ../labyrinth_lib/MainWindow.py:248 msgid "Use _Curves" msgstr "Benutze _Kurven" #: ../labyrinth_lib/MainWindow.py:249 msgid "Use curves as links" msgstr "Benutze Kurven als Verbindungen" #: ../labyrinth_lib/MainWindow.py:250 msgid "Use _Lines" msgstr "Benutze Geraden" #: ../labyrinth_lib/MainWindow.py:251 msgid "Use straight lines as links" msgstr "Benutze gerade Linien als Verbindungen" #: ../labyrinth_lib/MainWindow.py:253 msgid "_Extended Information" msgstr "_Erweiterte Information" #: ../labyrinth_lib/MainWindow.py:254 msgid "Show extended information for thoughts" msgstr "Zeige erweiterte Gedankeninformationen" #: ../labyrinth_lib/MainWindow.py:255 msgid "_Main" msgstr "_Haupt" #: ../labyrinth_lib/MainWindow.py:256 msgid "Show main toolbar" msgstr "Zeige Werkzeugleiste" #: ../labyrinth_lib/MainWindow.py:257 msgid "_Format" msgstr "_Formatierung" #: ../labyrinth_lib/MainWindow.py:258 msgid "Show format toolbar" msgstr "Zeige Werkzeugleiste zur Formatierung" #: ../labyrinth_lib/MainWindow.py:536 msgid "Save File As" msgstr "Speichern unter" #: ../labyrinth_lib/MainWindow.py:630 msgid "All Files" msgstr "Alle Dateien" #: ../labyrinth_lib/MainWindow.py:631 msgid "PNG Image (*.png)" msgstr "PNG Bild (*.png)" #: ../labyrinth_lib/MainWindow.py:632 msgid "JPEG Image (*.jpg, *.jpeg)" msgstr "JPEG Bild (*.jpg, *.jpeg)" #: ../labyrinth_lib/MainWindow.py:633 msgid "SVG Vector Image (*.svg)" msgstr "SVG Vektorbild (*.svg)" #: ../labyrinth_lib/MainWindow.py:634 msgid "PDF Portable Document (*.pdf)" msgstr "PDF Portable Document (*.pdf)" #: ../labyrinth_lib/MainWindow.py:670 msgid "Unknown file format" msgstr "Unbekanntes Dateiformat" #: ../labyrinth_lib/MainWindow.py:671 #, python-format msgid "" "The file type '%s' is unsupported. Please use the suffix '.png', '.jpg' or " "'.svg'." msgstr "Der Dateityp '%s' wird nicht unterstützt. Bitte verwenden Sie die Dateiendungen '.png', '.jpg' oder '.svg'." #: ../labyrinth_lib/ResourceThought.py:128 msgid "Edit Text" msgstr "Text bearbeiten" #: ../labyrinth_lib/ResourceThought.py:133 msgid "Edit URI" msgstr "URI bearbeiten" #: ../labyrinth_lib/DrawingThought.py:65 #, python-format msgid "Drawing #%d" msgstr "Zeichnung #%d" #: ../data/labyrinth.glade:7 msgid "Export Map as Image" msgstr "Mindmap als Bild exportieren" #: ../data/labyrinth.glade:87 msgid "Complete Map" msgstr "Vollständige Mindmap" #: ../data/labyrinth.glade:101 msgid "Visible Area" msgstr "Sichtbarer Bereich" #: ../data/labyrinth.glade:157 msgid "Width" msgstr "Breite" #: ../data/labyrinth.glade:172 msgid "Height" msgstr "Höhe" #: ../data/labyrinth.glade:226 msgid "Export Map" msgstr "Exportierte Mindmap" #: ../data/labyrinth.glade:245 msgid "Labyrinth Maps" msgstr "Labyrinth Mindmaps" #: ../data/labyrinth.glade:259 msgid "_File" msgstr "_Datei" #: ../data/labyrinth.glade:299 msgid "Import..." msgstr "Importieren …" #: ../data/labyrinth.glade:329 msgid "_Help" msgstr "_Hilfe" #: ../data/labyrinth.glade:765 msgid "URL" msgstr "URL" #: ../data/labyrinth.glade:806 msgid "Align Left" msgstr "Linksbündig ausrichten" #: ../data/labyrinth.glade:825 msgid "Align Right" msgstr "Rechtsbündig ausrichten" #: ../data/labyrinth.glade:844 msgid "Align Vertical Center" msgstr "Vertikal zentrieren" #: ../data/labyrinth.glade:863 msgid "Align Top" msgstr "Oben ausrichten" #: ../data/labyrinth.glade:882 msgid "Align Bottom" msgstr "Unten ausrichten" #: ../data/labyrinth.glade:901 msgid "Align Horizontal Center" msgstr "Horizontal zentrieren" labyrinth-0.6/po/es.po000066400000000000000000000172141204476542500147560ustar00rootroot00000000000000# Labyrinth Spanish Translation # Copyright (C) 2008 Peter Gordon # This file is distributed under the same license as the Labyrinth package. # Peter Gordon # msgid "" msgstr "" "Project-Id-Version: Labyrinth 0.4\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2012-09-23 18:55+0100\n" "PO-Revision-Date: 2008-04-02 22:26-0800\n" "Last-Translator: Peter Gordon \n" "Language-Team: \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" #: ../labyrinth_lib/ImageThought.py:68 msgid "Choose image to insert" msgstr "Elija imagen para insertar" #: ../labyrinth_lib/ImageThought.py:323 msgid "Error loading file" msgstr "Error en cargando el archivo" #: ../labyrinth_lib/ImageThought.py:324 #, python-format msgid "%s could not be found. Associated thought will be empty." msgstr "No se pudo encontrar %s. El pensamiento asociado será vacío." #: ../labyrinth_lib/ImageThought.py:339 msgid "Change Image" msgstr "" #: ../labyrinth_lib/Browser.py:192 #, python-format msgid "Unable to display help: %s" msgstr "" #: ../labyrinth_lib/Browser.py:223 msgid "Translation by Don Scorgie" msgstr "" #: ../labyrinth_lib/Browser.py:245 #, fuzzy msgid "The map cannot be deleted right now. Is it open?" msgstr "No se puede borrar este mapa. ¿Está abierta?" #: ../labyrinth_lib/Browser.py:247 msgid "The map has no associated filename." msgstr "El mapa no tiene nombre de archivo asociado." #: ../labyrinth_lib/Browser.py:250 msgid "Cannot delete this map" msgstr "No se puede borrar este mapa" #: ../labyrinth_lib/Browser.py:257 msgid "Do you really want to delete this Map?" msgstr "¿Está seguro de que quiere borrar este Mapa?" #: ../labyrinth_lib/Browser.py:282 msgid "Open File" msgstr "Abrir desde archivo" #: ../labyrinth_lib/Browser.py:286 msgid "MAPZ Compressed Map (*.mapz)" msgstr "Mapa con compresión (*.mapz)" #: ../labyrinth_lib/Browser.py:317 msgid "Map Name" msgstr "Nombre del Mapa" #: ../labyrinth_lib/Browser.py:324 msgid "Last Modified" msgstr "Última modificación" #: ../labyrinth_lib/Links.py:265 #, fuzzy msgid "Choose Color" msgstr "Elija el color del fondo" #: ../labyrinth_lib/Links.py:278 msgid "Set Color" msgstr "" #: ../labyrinth_lib/MainWindow.py:166 ../labyrinth_lib/MainWindow.py:481 #, fuzzy msgid "Untitled Map" msgstr "Mapa sin nombre %d" #: ../labyrinth_lib/MainWindow.py:213 msgid "File" msgstr "Archivo" #: ../labyrinth_lib/MainWindow.py:214 msgid "Export as Image" msgstr "Guardar como imagen" #: ../labyrinth_lib/MainWindow.py:215 msgid "Export your map as an image" msgstr "Guardar su mapa como un imagen" #: ../labyrinth_lib/MainWindow.py:216 msgid "Export Map..." msgstr "Guardar Mapa…" #: ../labyrinth_lib/MainWindow.py:217 msgid "Export your map as XML" msgstr "Guardar su mapa como XML" #: ../labyrinth_lib/MainWindow.py:219 msgid "Close the current window" msgstr "Cierra la ventana actual" #: ../labyrinth_lib/MainWindow.py:220 msgid "_Edit" msgstr "_Editar" #: ../labyrinth_lib/MainWindow.py:221 msgid "_View" msgstr "" #: ../labyrinth_lib/MainWindow.py:222 msgid "_Toolbar" msgstr "" #: ../labyrinth_lib/MainWindow.py:231 #, fuzzy msgid "Link Thoughts" msgstr "(Des)Conectar Piensamientos" #: ../labyrinth_lib/MainWindow.py:232 #, fuzzy msgid "Link the selected thoughts" msgstr "(Des)Conectar los pensamientos eligidos" #: ../labyrinth_lib/MainWindow.py:233 msgid "_Mode" msgstr "_Modo" #: ../labyrinth_lib/MainWindow.py:241 msgid "_Edit Mode" msgstr "Modo _Edición" #: ../labyrinth_lib/MainWindow.py:242 msgid "Turn on edit mode" msgstr "Activar modo edición" #: ../labyrinth_lib/MainWindow.py:243 msgid "_Add Image" msgstr "_Añadir un imagen" #: ../labyrinth_lib/MainWindow.py:244 msgid "Add an image to selected thought" msgstr "Añadir un imagen al pensamiento elegido" #: ../labyrinth_lib/MainWindow.py:245 msgid "_Drawing Mode" msgstr "Modo de _Dibujar" #: ../labyrinth_lib/MainWindow.py:246 msgid "Make a pretty drawing" msgstr "Hacer un dibujo bonito" #: ../labyrinth_lib/MainWindow.py:248 msgid "Use _Curves" msgstr "" #: ../labyrinth_lib/MainWindow.py:249 msgid "Use curves as links" msgstr "" #: ../labyrinth_lib/MainWindow.py:250 msgid "Use _Lines" msgstr "" #: ../labyrinth_lib/MainWindow.py:251 msgid "Use straight lines as links" msgstr "" #: ../labyrinth_lib/MainWindow.py:253 msgid "_Extended Information" msgstr "" #: ../labyrinth_lib/MainWindow.py:254 #, fuzzy msgid "Show extended information for thoughts" msgstr "Ver información extendido de los pensamientos" #: ../labyrinth_lib/MainWindow.py:255 msgid "_Main" msgstr "" #: ../labyrinth_lib/MainWindow.py:256 msgid "Show main toolbar" msgstr "" #: ../labyrinth_lib/MainWindow.py:257 msgid "_Format" msgstr "" #: ../labyrinth_lib/MainWindow.py:258 msgid "Show format toolbar" msgstr "" #: ../labyrinth_lib/MainWindow.py:536 msgid "Save File As" msgstr "Guardar Archivo Como" #: ../labyrinth_lib/MainWindow.py:630 msgid "All Files" msgstr "Todos los Archivos" #: ../labyrinth_lib/MainWindow.py:631 msgid "PNG Image (*.png)" msgstr "Imagen PNG (*.png)" #: ../labyrinth_lib/MainWindow.py:632 msgid "JPEG Image (*.jpg, *.jpeg)" msgstr "Imagen JPEG (*.jpg, *.jpeg)" #: ../labyrinth_lib/MainWindow.py:633 msgid "SVG Vector Image (*.svg)" msgstr "Imagen escalable SVG (*.svg)" #: ../labyrinth_lib/MainWindow.py:634 msgid "PDF Portable Document (*.pdf)" msgstr "Documento de Formato Portátil PDF (*.pdf)" #: ../labyrinth_lib/MainWindow.py:670 msgid "Unknown file format" msgstr "Formato de archivo desconocido" #: ../labyrinth_lib/MainWindow.py:671 #, python-format msgid "" "The file type '%s' is unsupported. Please use the suffix '.png', '.jpg' or " "'.svg'." msgstr "" "No se soporta el tipo de archivo '%s'. Favor de usar el sufijo de '.png', '." "jpg', o '.svg'." #: ../labyrinth_lib/ResourceThought.py:128 #, fuzzy msgid "Edit Text" msgstr "Modo _Edición" #: ../labyrinth_lib/ResourceThought.py:133 #, fuzzy msgid "Edit URI" msgstr "_Editar" #: ../labyrinth_lib/DrawingThought.py:65 #, python-format msgid "Drawing #%d" msgstr "Dibujando #%d" #: ../data/labyrinth.glade:7 msgid "Export Map as Image" msgstr "Guardar Mapa como Imagen" #: ../data/labyrinth.glade:87 msgid "Complete Map" msgstr "Mapa Cumplido" #: ../data/labyrinth.glade:101 msgid "Visible Area" msgstr "Área Visible" #: ../data/labyrinth.glade:157 msgid "Width" msgstr "Anchura" #: ../data/labyrinth.glade:172 msgid "Height" msgstr "Altura" #: ../data/labyrinth.glade:226 msgid "Export Map" msgstr "Guardar Mapa" #: ../data/labyrinth.glade:245 msgid "Labyrinth Maps" msgstr "Labyrinth Mapas" #: ../data/labyrinth.glade:259 msgid "_File" msgstr "_Archivo" #: ../data/labyrinth.glade:299 #, fuzzy msgid "Import..." msgstr "Guardar Mapa…" #: ../data/labyrinth.glade:329 msgid "_Help" msgstr "_Ayuda" #: ../data/labyrinth.glade:765 msgid "URL" msgstr "" #: ../data/labyrinth.glade:806 msgid "Align Left" msgstr "" #: ../data/labyrinth.glade:825 msgid "Align Right" msgstr "" #: ../data/labyrinth.glade:844 msgid "Align Vertical Center" msgstr "" #: ../data/labyrinth.glade:863 msgid "Align Top" msgstr "" #: ../data/labyrinth.glade:882 msgid "Align Bottom" msgstr "" #: ../data/labyrinth.glade:901 msgid "Align Horizontal Center" msgstr "" #~ msgid "Choose foreground color" #~ msgstr "Elija el color del primer plano" #~ msgid "_Delete Selected Elements" #~ msgstr "_Borrar los elementos elegidos" #~ msgid "Delete the selected element(s)" #~ msgstr "Borrar los elementos elegidos" #~ msgid "_View Extended" #~ msgstr "_Ver Extendido" #~ msgid "Labyrinth Mind-mapping" #~ msgstr "Labyrinth Mapa de Mente" #~ msgid "Map your mind" #~ msgstr "Hacer un mapa de su mente" #~ msgid "Mind-mapping" #~ msgstr "Mapa de Mente" labyrinth-0.6/po/eu.po000066400000000000000000000163711204476542500147630ustar00rootroot00000000000000# Translation into Basque by Zunbeltz Izaola # msgid "" msgstr "" "Project-Id-Version: Labyrinth 0.3\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2012-09-23 18:55+0100\n" "PO-Revision-Date: 2006-11-07 17:12+0100\n" "Last-Translator: Zunbeltz Izaola \n" "Language-Team: \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Language: Basque\n" "X-Poedit-SourceCharset: utf-8\n" #: ../labyrinth_lib/ImageThought.py:68 msgid "Choose image to insert" msgstr "Aukeratu sartzeko irudia" #: ../labyrinth_lib/ImageThought.py:323 msgid "Error loading file" msgstr "Errorea fitxategia kargatzean" #: ../labyrinth_lib/ImageThought.py:324 #, python-format msgid "%s could not be found. Associated thought will be empty." msgstr "Ezin izan da %s aurkitu. Elkartutako gogoetak utzik egongo dira." #: ../labyrinth_lib/ImageThought.py:339 msgid "Change Image" msgstr "" #: ../labyrinth_lib/Browser.py:192 #, python-format msgid "Unable to display help: %s" msgstr "" #: ../labyrinth_lib/Browser.py:223 msgid "Translation by Don Scorgie" msgstr "" #: ../labyrinth_lib/Browser.py:245 #, fuzzy msgid "The map cannot be deleted right now. Is it open?" msgstr "Mapa ezin da ezabatu orain. Zabalik al dago?" #: ../labyrinth_lib/Browser.py:247 msgid "The map has no associated filename." msgstr "Mapak ez dauka elkartutako ftxaegi izenik." #: ../labyrinth_lib/Browser.py:250 msgid "Cannot delete this map" msgstr "Ezin da ezabatu Mapa hau." #: ../labyrinth_lib/Browser.py:257 msgid "Do you really want to delete this Map?" msgstr "Benetan nahi al duzu Mapa hau ezabatzea?" #: ../labyrinth_lib/Browser.py:282 #, fuzzy msgid "Open File" msgstr "Fitxategia" #: ../labyrinth_lib/Browser.py:286 msgid "MAPZ Compressed Map (*.mapz)" msgstr "" #: ../labyrinth_lib/Browser.py:317 msgid "Map Name" msgstr "Maparen izena" #: ../labyrinth_lib/Browser.py:324 msgid "Last Modified" msgstr "" #: ../labyrinth_lib/Links.py:265 msgid "Choose Color" msgstr "" #: ../labyrinth_lib/Links.py:278 msgid "Set Color" msgstr "" #: ../labyrinth_lib/MainWindow.py:166 ../labyrinth_lib/MainWindow.py:481 #, fuzzy msgid "Untitled Map" msgstr "Izenik gabeko Mapa %d" #: ../labyrinth_lib/MainWindow.py:213 msgid "File" msgstr "Fitxategia" #: ../labyrinth_lib/MainWindow.py:214 msgid "Export as Image" msgstr "Irudi gisa esportatu" #: ../labyrinth_lib/MainWindow.py:215 msgid "Export your map as an image" msgstr "Zure Mapa irudi gisa ezportatu" #: ../labyrinth_lib/MainWindow.py:216 #, fuzzy msgid "Export Map..." msgstr "Esportatu Mapa" #: ../labyrinth_lib/MainWindow.py:217 #, fuzzy msgid "Export your map as XML" msgstr "Zure Mapa irudi gisa ezportatu" #: ../labyrinth_lib/MainWindow.py:219 msgid "Close the current window" msgstr "Itxi momentuko lehioa" #: ../labyrinth_lib/MainWindow.py:220 msgid "_Edit" msgstr "_Editatu" #: ../labyrinth_lib/MainWindow.py:221 msgid "_View" msgstr "" #: ../labyrinth_lib/MainWindow.py:222 msgid "_Toolbar" msgstr "" #: ../labyrinth_lib/MainWindow.py:231 #, fuzzy msgid "Link Thoughts" msgstr "Ideiak lotu/eten" #: ../labyrinth_lib/MainWindow.py:232 #, fuzzy msgid "Link the selected thoughts" msgstr "Lotu/Eten aukeratutako gogoetak" #: ../labyrinth_lib/MainWindow.py:233 msgid "_Mode" msgstr "_Modu" #: ../labyrinth_lib/MainWindow.py:241 msgid "_Edit Mode" msgstr "_Editatze modua" #: ../labyrinth_lib/MainWindow.py:242 msgid "Turn on edit mode" msgstr "Piztu editatze modua" #: ../labyrinth_lib/MainWindow.py:243 msgid "_Add Image" msgstr "_Gehitu irudia" #: ../labyrinth_lib/MainWindow.py:244 msgid "Add an image to selected thought" msgstr "Gehitu irudia aukeratutako gogetari" #: ../labyrinth_lib/MainWindow.py:245 msgid "_Drawing Mode" msgstr "_Marrazki modua" #: ../labyrinth_lib/MainWindow.py:246 msgid "Make a pretty drawing" msgstr "Egin irudi polit bat" #: ../labyrinth_lib/MainWindow.py:248 msgid "Use _Curves" msgstr "" #: ../labyrinth_lib/MainWindow.py:249 msgid "Use curves as links" msgstr "" #: ../labyrinth_lib/MainWindow.py:250 msgid "Use _Lines" msgstr "" #: ../labyrinth_lib/MainWindow.py:251 msgid "Use straight lines as links" msgstr "" #: ../labyrinth_lib/MainWindow.py:253 msgid "_Extended Information" msgstr "" #: ../labyrinth_lib/MainWindow.py:254 #, fuzzy msgid "Show extended information for thoughts" msgstr "Ikusi gogoeten informazio hedatua" #: ../labyrinth_lib/MainWindow.py:255 msgid "_Main" msgstr "" #: ../labyrinth_lib/MainWindow.py:256 msgid "Show main toolbar" msgstr "" #: ../labyrinth_lib/MainWindow.py:257 msgid "_Format" msgstr "" #: ../labyrinth_lib/MainWindow.py:258 msgid "Show format toolbar" msgstr "" #: ../labyrinth_lib/MainWindow.py:536 msgid "Save File As" msgstr "" #: ../labyrinth_lib/MainWindow.py:630 #, fuzzy msgid "All Files" msgstr "Fitxategia" #: ../labyrinth_lib/MainWindow.py:631 msgid "PNG Image (*.png)" msgstr "" #: ../labyrinth_lib/MainWindow.py:632 msgid "JPEG Image (*.jpg, *.jpeg)" msgstr "" #: ../labyrinth_lib/MainWindow.py:633 msgid "SVG Vector Image (*.svg)" msgstr "" #: ../labyrinth_lib/MainWindow.py:634 msgid "PDF Portable Document (*.pdf)" msgstr "" #: ../labyrinth_lib/MainWindow.py:670 msgid "Unknown file format" msgstr "Fitxategi-formatu ezezaguna" #: ../labyrinth_lib/MainWindow.py:671 #, fuzzy, python-format msgid "" "The file type '%s' is unsupported. Please use the suffix '.png', '.jpg' or " "'.svg'." msgstr "" "%s fitxategi formatua ezin da onartu. Mesedez erabili '.gng' edo '.jpg' " "fitxategi-luzapena" #: ../labyrinth_lib/ResourceThought.py:128 #, fuzzy msgid "Edit Text" msgstr "_Editatze modua" #: ../labyrinth_lib/ResourceThought.py:133 #, fuzzy msgid "Edit URI" msgstr "_Editatu" #: ../labyrinth_lib/DrawingThought.py:65 #, python-format msgid "Drawing #%d" msgstr "%d irudia" #: ../data/labyrinth.glade:7 msgid "Export Map as Image" msgstr "Esportatu Mapa irudi gisa" #: ../data/labyrinth.glade:87 msgid "Complete Map" msgstr "Mapa osoa" #: ../data/labyrinth.glade:101 msgid "Visible Area" msgstr "Ageriko area" #: ../data/labyrinth.glade:157 msgid "Width" msgstr "Zabalera" #: ../data/labyrinth.glade:172 msgid "Height" msgstr "Altuera" #: ../data/labyrinth.glade:226 msgid "Export Map" msgstr "Esportatu Mapa" #: ../data/labyrinth.glade:245 msgid "Labyrinth Maps" msgstr "Labyrinth-mapak" #: ../data/labyrinth.glade:259 msgid "_File" msgstr "_Fitxategia" #: ../data/labyrinth.glade:299 msgid "Import..." msgstr "" #: ../data/labyrinth.glade:329 msgid "_Help" msgstr "_Laguntza" #: ../data/labyrinth.glade:765 msgid "URL" msgstr "" #: ../data/labyrinth.glade:806 msgid "Align Left" msgstr "" #: ../data/labyrinth.glade:825 msgid "Align Right" msgstr "" #: ../data/labyrinth.glade:844 msgid "Align Vertical Center" msgstr "" #: ../data/labyrinth.glade:863 msgid "Align Top" msgstr "" #: ../data/labyrinth.glade:882 msgid "Align Bottom" msgstr "" #: ../data/labyrinth.glade:901 msgid "Align Horizontal Center" msgstr "" #~ msgid "_Delete Selected Thoughts" #~ msgstr "_Ezabatu aukeratutako gogoetak" #~ msgid "Delete the selected element(s)" #~ msgstr "Ezabatu aukeratutako elementua(k)" #~ msgid "_View Extended" #~ msgstr "_Ikusi hedatutakoa" #~ msgid "Labyrinth Mind-mapping" #~ msgstr "Labyrinth Gogoeta-mapak" #~ msgid "Map your mind" #~ msgstr "Zure gogoeten mapa egin" #~ msgid "Mind-mapping" #~ msgstr "Gogoeta-mapak" labyrinth-0.6/po/fa.po000066400000000000000000000174511204476542500147400ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # msgid "" msgstr "" "Project-Id-Version: Labyrinth\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2012-09-23 18:55+0100\n" "PO-Revision-Date: 2008-03-23 16:30+0300\n" "Last-Translator: Pedram Azimaie \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Language: Persian\n" "X-Poedit-Country: Iran\n" #: ../labyrinth_lib/ImageThought.py:68 msgid "Choose image to insert" msgstr "عکس را برای ورود انتخاب کنید" #: ../labyrinth_lib/ImageThought.py:323 msgid "Error loading file" msgstr "خطا در هنگام بار گزاری " #: ../labyrinth_lib/ImageThought.py:324 #, python-format msgid "%s could not be found. Associated thought will be empty." msgstr "%s پیدا نشد.تکفر مورد نظر خالی خواهد ماند" #: ../labyrinth_lib/ImageThought.py:339 msgid "Change Image" msgstr "" #: ../labyrinth_lib/Browser.py:192 #, python-format msgid "Unable to display help: %s" msgstr "" #: ../labyrinth_lib/Browser.py:223 msgid "Translation by Don Scorgie" msgstr "" #: ../labyrinth_lib/Browser.py:245 #, fuzzy msgid "The map cannot be deleted right now. Is it open?" msgstr "امکان حذف نقشه فراهم نیست,آیا نقشه باز است؟" #: ../labyrinth_lib/Browser.py:247 msgid "The map has no associated filename." msgstr "نقشه هیچ نامی ندارد" #: ../labyrinth_lib/Browser.py:250 msgid "Cannot delete this map" msgstr "امکان حذف نقشه وجود ندارد" #: ../labyrinth_lib/Browser.py:257 msgid "Do you really want to delete this Map?" msgstr "واقعا میخواهید نقشه را حذف کنید؟" #: ../labyrinth_lib/Browser.py:282 #, fuzzy msgid "Open File" msgstr "پرونده" #: ../labyrinth_lib/Browser.py:286 msgid "MAPZ Compressed Map (*.mapz)" msgstr "" #: ../labyrinth_lib/Browser.py:317 msgid "Map Name" msgstr "نام نقشه" #: ../labyrinth_lib/Browser.py:324 msgid "Last Modified" msgstr "" #: ../labyrinth_lib/Links.py:265 msgid "Choose Color" msgstr "" #: ../labyrinth_lib/Links.py:278 msgid "Set Color" msgstr "" #: ../labyrinth_lib/MainWindow.py:166 ../labyrinth_lib/MainWindow.py:481 #, fuzzy msgid "Untitled Map" msgstr "نقشه بدون نام #%d" #: ../labyrinth_lib/MainWindow.py:213 msgid "File" msgstr "پرونده" #: ../labyrinth_lib/MainWindow.py:214 msgid "Export as Image" msgstr "صدور به صورت عکس" #: ../labyrinth_lib/MainWindow.py:215 msgid "Export your map as an image" msgstr "صدور نقشه شما به صورت عکس" #: ../labyrinth_lib/MainWindow.py:216 #, fuzzy msgid "Export Map..." msgstr "صدور نقشه" #: ../labyrinth_lib/MainWindow.py:217 #, fuzzy msgid "Export your map as XML" msgstr "صدور نقشه شما به صورت عکس" #: ../labyrinth_lib/MainWindow.py:219 msgid "Close the current window" msgstr "بستن پنجره فعلی" #: ../labyrinth_lib/MainWindow.py:220 msgid "_Edit" msgstr "_ویرایش" #: ../labyrinth_lib/MainWindow.py:221 msgid "_View" msgstr "" #: ../labyrinth_lib/MainWindow.py:222 msgid "_Toolbar" msgstr "" #: ../labyrinth_lib/MainWindow.py:231 #, fuzzy msgid "Link Thoughts" msgstr "(خذف)پیوند تفکرات" #: ../labyrinth_lib/MainWindow.py:232 #, fuzzy msgid "Link the selected thoughts" msgstr "(خذف)پیوند تفکرات انتخاب شده" #: ../labyrinth_lib/MainWindow.py:233 msgid "_Mode" msgstr "_نوع" #: ../labyrinth_lib/MainWindow.py:241 msgid "_Edit Mode" msgstr "_حالت ویرایش" #: ../labyrinth_lib/MainWindow.py:242 msgid "Turn on edit mode" msgstr "روشن کردن حالت ویرایش" #: ../labyrinth_lib/MainWindow.py:243 msgid "_Add Image" msgstr "_افزودن عکس" #: ../labyrinth_lib/MainWindow.py:244 msgid "Add an image to selected thought" msgstr "افزودن عکس به تفکر انتخاب شده" #: ../labyrinth_lib/MainWindow.py:245 msgid "_Drawing Mode" msgstr "حالت ـنقاشی" #: ../labyrinth_lib/MainWindow.py:246 msgid "Make a pretty drawing" msgstr "ساخت نقاشی قشنگ" #: ../labyrinth_lib/MainWindow.py:248 msgid "Use _Curves" msgstr "" #: ../labyrinth_lib/MainWindow.py:249 msgid "Use curves as links" msgstr "" #: ../labyrinth_lib/MainWindow.py:250 msgid "Use _Lines" msgstr "" #: ../labyrinth_lib/MainWindow.py:251 msgid "Use straight lines as links" msgstr "" #: ../labyrinth_lib/MainWindow.py:253 msgid "_Extended Information" msgstr "" #: ../labyrinth_lib/MainWindow.py:254 #, fuzzy msgid "Show extended information for thoughts" msgstr "نمایش اطلاعات گسترده برای تفکرات" #: ../labyrinth_lib/MainWindow.py:255 msgid "_Main" msgstr "" #: ../labyrinth_lib/MainWindow.py:256 msgid "Show main toolbar" msgstr "" #: ../labyrinth_lib/MainWindow.py:257 msgid "_Format" msgstr "" #: ../labyrinth_lib/MainWindow.py:258 msgid "Show format toolbar" msgstr "" #: ../labyrinth_lib/MainWindow.py:536 msgid "Save File As" msgstr "" #: ../labyrinth_lib/MainWindow.py:630 #, fuzzy msgid "All Files" msgstr "پرونده" #: ../labyrinth_lib/MainWindow.py:631 msgid "PNG Image (*.png)" msgstr "" #: ../labyrinth_lib/MainWindow.py:632 msgid "JPEG Image (*.jpg, *.jpeg)" msgstr "" #: ../labyrinth_lib/MainWindow.py:633 msgid "SVG Vector Image (*.svg)" msgstr "" #: ../labyrinth_lib/MainWindow.py:634 msgid "PDF Portable Document (*.pdf)" msgstr "" #: ../labyrinth_lib/MainWindow.py:670 msgid "Unknown file format" msgstr "پرونده نامشخص" #: ../labyrinth_lib/MainWindow.py:671 #, fuzzy, python-format msgid "" "The file type '%s' is unsupported. Please use the suffix '.png', '.jpg' or " "'.svg'." msgstr "" "نوع فایل '%s' پشتیبانی نمی شود. لطفا از پسوند های '.png' یا '.jpg' استفاده " "کنید" #: ../labyrinth_lib/ResourceThought.py:128 #, fuzzy msgid "Edit Text" msgstr "_حالت ویرایش" #: ../labyrinth_lib/ResourceThought.py:133 #, fuzzy msgid "Edit URI" msgstr "_ویرایش" #: ../labyrinth_lib/DrawingThought.py:65 #, python-format msgid "Drawing #%d" msgstr "کشیدن #%d" #: ../data/labyrinth.glade:7 msgid "Export Map as Image" msgstr "صدور نقشه به صورت عکس" #: ../data/labyrinth.glade:87 msgid "Complete Map" msgstr "اتمام نقشه" #: ../data/labyrinth.glade:101 msgid "Visible Area" msgstr "منطقه قابل دید" #: ../data/labyrinth.glade:157 msgid "Width" msgstr "طول" #: ../data/labyrinth.glade:172 msgid "Height" msgstr "ارتفاع" #: ../data/labyrinth.glade:226 msgid "Export Map" msgstr "صدور نقشه" #: ../data/labyrinth.glade:245 msgid "Labyrinth Maps" msgstr "Labyrinth Maps" #: ../data/labyrinth.glade:259 msgid "_File" msgstr "_پرونده" #: ../data/labyrinth.glade:299 msgid "Import..." msgstr "" #: ../data/labyrinth.glade:329 msgid "_Help" msgstr "_کمک" #: ../data/labyrinth.glade:765 msgid "URL" msgstr "" #: ../data/labyrinth.glade:806 msgid "Align Left" msgstr "" #: ../data/labyrinth.glade:825 msgid "Align Right" msgstr "" #: ../data/labyrinth.glade:844 msgid "Align Vertical Center" msgstr "" #: ../data/labyrinth.glade:863 msgid "Align Top" msgstr "" #: ../data/labyrinth.glade:882 msgid "Align Bottom" msgstr "" #: ../data/labyrinth.glade:901 msgid "Align Horizontal Center" msgstr "" #~ msgid "_Delete Selected Thoughts" #~ msgstr "حذف تفکراـت انتخاب شده" #~ msgid "Delete the selected element(s)" #~ msgstr "حذف عامل/عوامل انتخاب شده" #~ msgid "_View Extended" #~ msgstr "نمای_ش حالت گسترده" #~ msgid "Labyrinth Mind-mapping" #~ msgstr "Labyrinth Mind-mapping" #~ msgid "Map your mind" #~ msgstr "نقشه تفکرات خود را بکشید" #~ msgid "Mind-mapping" #~ msgstr "Mind-mapping" labyrinth-0.6/po/fr.po000066400000000000000000000167331204476542500147630ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: # Mathieu Leduc-Hamel, 2006. # , 2012. msgid "" msgstr "" "Project-Id-Version: Labyrinth\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2012-09-23 18:55+0100\n" "PO-Revision-Date: 2012-09-25 19:57+0000\n" "Last-Translator: pat332 \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: fr\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" #: ../labyrinth_lib/ImageThought.py:68 msgid "Choose image to insert" msgstr "Sélectionner une image à insérer" #: ../labyrinth_lib/ImageThought.py:323 msgid "Error loading file" msgstr "Erreur de chargement du fichier" #: ../labyrinth_lib/ImageThought.py:324 #, python-format msgid "%s could not be found. Associated thought will be empty." msgstr "%s est introuvable. L'idée correspondante sera vide." #: ../labyrinth_lib/ImageThought.py:339 msgid "Change Image" msgstr "Changer d'image" #: ../labyrinth_lib/Browser.py:192 #, python-format msgid "Unable to display help: %s" msgstr "Impossible d'afficher l'aide: %s" #: ../labyrinth_lib/Browser.py:223 msgid "Translation by Don Scorgie" msgstr "Traduction par Don Scorgie" #: ../labyrinth_lib/Browser.py:245 msgid "The map cannot be deleted right now. Is it open?" msgstr "La carte ne peut pas être supprimée actuellement. Est-elle ouverte?" #: ../labyrinth_lib/Browser.py:247 msgid "The map has no associated filename." msgstr "Cette carte n'a pas de nom de fichier associé." #: ../labyrinth_lib/Browser.py:250 msgid "Cannot delete this map" msgstr "Impossible de supprimer cette carte" #: ../labyrinth_lib/Browser.py:257 msgid "Do you really want to delete this Map?" msgstr "Voulez-vous vraiment supprimer cette carte ?" #: ../labyrinth_lib/Browser.py:282 msgid "Open File" msgstr "Ouvrir le fichier" #: ../labyrinth_lib/Browser.py:286 msgid "MAPZ Compressed Map (*.mapz)" msgstr "Carte compressée MAPZ (*.mapz)" #: ../labyrinth_lib/Browser.py:317 msgid "Map Name" msgstr "Nom de la carte" #: ../labyrinth_lib/Browser.py:324 msgid "Last Modified" msgstr "Derniers modifiés" #: ../labyrinth_lib/Links.py:265 msgid "Choose Color" msgstr "Choisir la couleur" #: ../labyrinth_lib/Links.py:278 msgid "Set Color" msgstr "Configurer la couleur" #: ../labyrinth_lib/MainWindow.py:166 ../labyrinth_lib/MainWindow.py:481 msgid "Untitled Map" msgstr "Carte sans titre" #: ../labyrinth_lib/MainWindow.py:213 msgid "File" msgstr "Fichier" #: ../labyrinth_lib/MainWindow.py:214 msgid "Export as Image" msgstr "Exporter en tant qu'image" #: ../labyrinth_lib/MainWindow.py:215 msgid "Export your map as an image" msgstr "Exporte votre carte en tant qu'image de format différent" #: ../labyrinth_lib/MainWindow.py:216 msgid "Export Map..." msgstr "Exporter la carte..." #: ../labyrinth_lib/MainWindow.py:217 msgid "Export your map as XML" msgstr "Exportez votre carte au format XML" #: ../labyrinth_lib/MainWindow.py:219 msgid "Close the current window" msgstr "Ferme la fenêtre courante" #: ../labyrinth_lib/MainWindow.py:220 msgid "_Edit" msgstr "_Édition" #: ../labyrinth_lib/MainWindow.py:221 msgid "_View" msgstr "_Vue" #: ../labyrinth_lib/MainWindow.py:222 msgid "_Toolbar" msgstr "" #: ../labyrinth_lib/MainWindow.py:231 msgid "Link Thoughts" msgstr "" #: ../labyrinth_lib/MainWindow.py:232 msgid "Link the selected thoughts" msgstr "" #: ../labyrinth_lib/MainWindow.py:233 msgid "_Mode" msgstr "_Mode" #: ../labyrinth_lib/MainWindow.py:241 msgid "_Edit Mode" msgstr "Mode _édition" #: ../labyrinth_lib/MainWindow.py:242 msgid "Turn on edit mode" msgstr "Activer le mode d'édition" #: ../labyrinth_lib/MainWindow.py:243 msgid "_Add Image" msgstr "_Ajouter une image" #: ../labyrinth_lib/MainWindow.py:244 msgid "Add an image to selected thought" msgstr "Ajouter une image à l'idée sélectionnée" #: ../labyrinth_lib/MainWindow.py:245 msgid "_Drawing Mode" msgstr "Mode _dessin" #: ../labyrinth_lib/MainWindow.py:246 msgid "Make a pretty drawing" msgstr "Faire un beau dessin" #: ../labyrinth_lib/MainWindow.py:248 msgid "Use _Curves" msgstr "" #: ../labyrinth_lib/MainWindow.py:249 msgid "Use curves as links" msgstr "" #: ../labyrinth_lib/MainWindow.py:250 msgid "Use _Lines" msgstr "" #: ../labyrinth_lib/MainWindow.py:251 msgid "Use straight lines as links" msgstr "" #: ../labyrinth_lib/MainWindow.py:253 msgid "_Extended Information" msgstr "" #: ../labyrinth_lib/MainWindow.py:254 msgid "Show extended information for thoughts" msgstr "" #: ../labyrinth_lib/MainWindow.py:255 msgid "_Main" msgstr "" #: ../labyrinth_lib/MainWindow.py:256 msgid "Show main toolbar" msgstr "Montrer la barre d'outils principale" #: ../labyrinth_lib/MainWindow.py:257 msgid "_Format" msgstr "" #: ../labyrinth_lib/MainWindow.py:258 msgid "Show format toolbar" msgstr "Montrer le format de la barre d'outils" #: ../labyrinth_lib/MainWindow.py:536 msgid "Save File As" msgstr "Enregistrez sous" #: ../labyrinth_lib/MainWindow.py:630 msgid "All Files" msgstr "Tous les fichiers" #: ../labyrinth_lib/MainWindow.py:631 msgid "PNG Image (*.png)" msgstr "Image PNG (*.png)" #: ../labyrinth_lib/MainWindow.py:632 msgid "JPEG Image (*.jpg, *.jpeg)" msgstr "Image JPEG (*.jpg, *.jpeg)" #: ../labyrinth_lib/MainWindow.py:633 msgid "SVG Vector Image (*.svg)" msgstr "Image vectorisée SVG (*.svg)" #: ../labyrinth_lib/MainWindow.py:634 msgid "PDF Portable Document (*.pdf)" msgstr "Document pdf (*.pdf)" #: ../labyrinth_lib/MainWindow.py:670 msgid "Unknown file format" msgstr "Type de fichier inconnu" #: ../labyrinth_lib/MainWindow.py:671 #, python-format msgid "" "The file type '%s' is unsupported. Please use the suffix '.png', '.jpg' or " "'.svg'." msgstr "Le fichier au format '%s' n'est pas reconnu. Utilisez s'il vous plaît le suffixe '.png', '.jpg' ou '.svg'." #: ../labyrinth_lib/ResourceThought.py:128 msgid "Edit Text" msgstr "Editer le texte" #: ../labyrinth_lib/ResourceThought.py:133 msgid "Edit URI" msgstr "Editer l'URI" #: ../labyrinth_lib/DrawingThought.py:65 #, python-format msgid "Drawing #%d" msgstr "Dessin #%d" #: ../data/labyrinth.glade:7 msgid "Export Map as Image" msgstr "Exporter la carte en tant qu'image" #: ../data/labyrinth.glade:87 msgid "Complete Map" msgstr "Carte entière" #: ../data/labyrinth.glade:101 msgid "Visible Area" msgstr "Aire visible" #: ../data/labyrinth.glade:157 msgid "Width" msgstr "Largeur" #: ../data/labyrinth.glade:172 msgid "Height" msgstr "Hauteur" #: ../data/labyrinth.glade:226 msgid "Export Map" msgstr "Exporter la carte" #: ../data/labyrinth.glade:245 msgid "Labyrinth Maps" msgstr "Carte de Labyrinth" #: ../data/labyrinth.glade:259 msgid "_File" msgstr "_Fichier" #: ../data/labyrinth.glade:299 msgid "Import..." msgstr "Importer..." #: ../data/labyrinth.glade:329 msgid "_Help" msgstr "_Aide" #: ../data/labyrinth.glade:765 msgid "URL" msgstr "URL" #: ../data/labyrinth.glade:806 msgid "Align Left" msgstr "Alignement à gauche" #: ../data/labyrinth.glade:825 msgid "Align Right" msgstr "Alignement à droite" #: ../data/labyrinth.glade:844 msgid "Align Vertical Center" msgstr "Alignement vertical centré" #: ../data/labyrinth.glade:863 msgid "Align Top" msgstr "Alignement en haut" #: ../data/labyrinth.glade:882 msgid "Align Bottom" msgstr "Alignement en bas" #: ../data/labyrinth.glade:901 msgid "Align Horizontal Center" msgstr "Alignement horizontal centré" labyrinth-0.6/po/it.po000066400000000000000000000167541204476542500147730ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: # , 2012. msgid "" msgstr "" "Project-Id-Version: Labyrinth\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2012-09-23 18:55+0100\n" "PO-Revision-Date: 2012-10-09 13:18+0000\n" "Last-Translator: Tony Goodyear \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: it\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" #: ../labyrinth_lib/ImageThought.py:68 msgid "Choose image to insert" msgstr "Scegli un'immagine da inserire" #: ../labyrinth_lib/ImageThought.py:323 msgid "Error loading file" msgstr "Errore durante il caricamento del file" #: ../labyrinth_lib/ImageThought.py:324 #, python-format msgid "%s could not be found. Associated thought will be empty." msgstr "%s non è stato trovato. I nodi associati saranno vuoti." #: ../labyrinth_lib/ImageThought.py:339 msgid "Change Image" msgstr "Cambia Immagine" #: ../labyrinth_lib/Browser.py:192 #, python-format msgid "Unable to display help: %s" msgstr "Impossibile visualizzare la guida: %s" #: ../labyrinth_lib/Browser.py:223 msgid "Translation by Don Scorgie" msgstr "Tradotto da Don Scorgie" #: ../labyrinth_lib/Browser.py:245 msgid "The map cannot be deleted right now. Is it open?" msgstr "La mappa non può essere cancellata. E' aperta ?" #: ../labyrinth_lib/Browser.py:247 msgid "The map has no associated filename." msgstr "Nessun nome è stato associato al file della mappa" #: ../labyrinth_lib/Browser.py:250 msgid "Cannot delete this map" msgstr "Non posso cancellare questa mappa" #: ../labyrinth_lib/Browser.py:257 msgid "Do you really want to delete this Map?" msgstr "Vuoi veramente cancellare questa Mappa?" #: ../labyrinth_lib/Browser.py:282 msgid "Open File" msgstr "Apri File" #: ../labyrinth_lib/Browser.py:286 msgid "MAPZ Compressed Map (*.mapz)" msgstr "MAPZ Mappa Compressa (*.mapz)" #: ../labyrinth_lib/Browser.py:317 msgid "Map Name" msgstr "Nome della Mappa" #: ../labyrinth_lib/Browser.py:324 msgid "Last Modified" msgstr "Ultima Modifica" #: ../labyrinth_lib/Links.py:265 msgid "Choose Color" msgstr "Scegli Colore" #: ../labyrinth_lib/Links.py:278 msgid "Set Color" msgstr "Imposta Colore" #: ../labyrinth_lib/MainWindow.py:166 ../labyrinth_lib/MainWindow.py:481 msgid "Untitled Map" msgstr "Mappa Senza Titolo" #: ../labyrinth_lib/MainWindow.py:213 msgid "File" msgstr "File" #: ../labyrinth_lib/MainWindow.py:214 msgid "Export as Image" msgstr "Esporta come immagine" #: ../labyrinth_lib/MainWindow.py:215 msgid "Export your map as an image" msgstr "Esporta la tua mappa come un'immagine" #: ../labyrinth_lib/MainWindow.py:216 msgid "Export Map..." msgstr "Esporta Mappa..." #: ../labyrinth_lib/MainWindow.py:217 msgid "Export your map as XML" msgstr "Esporta mappa come XML" #: ../labyrinth_lib/MainWindow.py:219 msgid "Close the current window" msgstr "Chiudi la finestra" #: ../labyrinth_lib/MainWindow.py:220 msgid "_Edit" msgstr "_Modifica" #: ../labyrinth_lib/MainWindow.py:221 msgid "_View" msgstr "_Visualizza" #: ../labyrinth_lib/MainWindow.py:222 msgid "_Toolbar" msgstr "_Barra degli strumenti" #: ../labyrinth_lib/MainWindow.py:231 msgid "Link Thoughts" msgstr "" #: ../labyrinth_lib/MainWindow.py:232 msgid "Link the selected thoughts" msgstr "" #: ../labyrinth_lib/MainWindow.py:233 msgid "_Mode" msgstr "M_odo" #: ../labyrinth_lib/MainWindow.py:241 msgid "_Edit Mode" msgstr "Modalità _Modifica" #: ../labyrinth_lib/MainWindow.py:242 msgid "Turn on edit mode" msgstr "Abilità la modifica" #: ../labyrinth_lib/MainWindow.py:243 msgid "_Add Image" msgstr "_Aggiunti immagine" #: ../labyrinth_lib/MainWindow.py:244 msgid "Add an image to selected thought" msgstr "Aggiungi un'immagine al nodo selezionato" #: ../labyrinth_lib/MainWindow.py:245 msgid "_Drawing Mode" msgstr "Modalità _Disegno" #: ../labyrinth_lib/MainWindow.py:246 msgid "Make a pretty drawing" msgstr "Realizza un disegno carino" #: ../labyrinth_lib/MainWindow.py:248 msgid "Use _Curves" msgstr "Usa _Curves" #: ../labyrinth_lib/MainWindow.py:249 msgid "Use curves as links" msgstr "Usa curve come collegamenti" #: ../labyrinth_lib/MainWindow.py:250 msgid "Use _Lines" msgstr "Usa _Lines" #: ../labyrinth_lib/MainWindow.py:251 msgid "Use straight lines as links" msgstr "Usa linee rette come collegamenti" #: ../labyrinth_lib/MainWindow.py:253 msgid "_Extended Information" msgstr "Informazioni _Estese" #: ../labyrinth_lib/MainWindow.py:254 msgid "Show extended information for thoughts" msgstr "" #: ../labyrinth_lib/MainWindow.py:255 msgid "_Main" msgstr "_Principale" #: ../labyrinth_lib/MainWindow.py:256 msgid "Show main toolbar" msgstr "Visualizza barra degli strumenti principale" #: ../labyrinth_lib/MainWindow.py:257 msgid "_Format" msgstr "_Formato" #: ../labyrinth_lib/MainWindow.py:258 msgid "Show format toolbar" msgstr "Visualizza barra degli strumenti formato" #: ../labyrinth_lib/MainWindow.py:536 msgid "Save File As" msgstr "Salva File Come" #: ../labyrinth_lib/MainWindow.py:630 msgid "All Files" msgstr "Tutti i files" #: ../labyrinth_lib/MainWindow.py:631 msgid "PNG Image (*.png)" msgstr "Immagine PNG ( *.png)" #: ../labyrinth_lib/MainWindow.py:632 msgid "JPEG Image (*.jpg, *.jpeg)" msgstr "Immagine JPEG (*.jpg, *.jpeg)" #: ../labyrinth_lib/MainWindow.py:633 msgid "SVG Vector Image (*.svg)" msgstr "SVG Immagine Vettoriale (*.svg)" #: ../labyrinth_lib/MainWindow.py:634 msgid "PDF Portable Document (*.pdf)" msgstr "PDF Documento Portabile (*.pdf)" #: ../labyrinth_lib/MainWindow.py:670 msgid "Unknown file format" msgstr "Formato file non riconosciuto" #: ../labyrinth_lib/MainWindow.py:671 #, python-format msgid "" "The file type '%s' is unsupported. Please use the suffix '.png', '.jpg' or " "'.svg'." msgstr "Il tipo file '%s' non è supportato. Utilizzare l'estensione '.png', '.jpg' or '.svg'." #: ../labyrinth_lib/ResourceThought.py:128 msgid "Edit Text" msgstr "Modifica Testo" #: ../labyrinth_lib/ResourceThought.py:133 msgid "Edit URI" msgstr "Modifica URI" #: ../labyrinth_lib/DrawingThought.py:65 #, python-format msgid "Drawing #%d" msgstr "Disegno #%d" #: ../data/labyrinth.glade:7 msgid "Export Map as Image" msgstr "Esporta la Mappa come un'immagine" #: ../data/labyrinth.glade:87 msgid "Complete Map" msgstr "Mappa completa" #: ../data/labyrinth.glade:101 msgid "Visible Area" msgstr "Area visibile" #: ../data/labyrinth.glade:157 msgid "Width" msgstr "Larghezza" #: ../data/labyrinth.glade:172 msgid "Height" msgstr "Altezza" #: ../data/labyrinth.glade:226 msgid "Export Map" msgstr "Esporta la Mappa" #: ../data/labyrinth.glade:245 msgid "Labyrinth Maps" msgstr "Labyrinth Maps" #: ../data/labyrinth.glade:259 msgid "_File" msgstr "_File" #: ../data/labyrinth.glade:299 msgid "Import..." msgstr "Importa..." #: ../data/labyrinth.glade:329 msgid "_Help" msgstr "A_iuto" #: ../data/labyrinth.glade:765 msgid "URL" msgstr "URL" #: ../data/labyrinth.glade:806 msgid "Align Left" msgstr "Allinea a Sinistra" #: ../data/labyrinth.glade:825 msgid "Align Right" msgstr "Allinea a Destra" #: ../data/labyrinth.glade:844 msgid "Align Vertical Center" msgstr "Allinea Verticale Centrato" #: ../data/labyrinth.glade:863 msgid "Align Top" msgstr "Allinea in Alto" #: ../data/labyrinth.glade:882 msgid "Align Bottom" msgstr "Allinea in Basso" #: ../data/labyrinth.glade:901 msgid "Align Horizontal Center" msgstr "Allinea Orizzontale Centrato" labyrinth-0.6/po/labyrinth.pot000066400000000000000000000136561204476542500165350ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2012-09-23 18:55+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" #: ../labyrinth_lib/ImageThought.py:68 msgid "Choose image to insert" msgstr "" #: ../labyrinth_lib/ImageThought.py:323 msgid "Error loading file" msgstr "" #: ../labyrinth_lib/ImageThought.py:324 #, python-format msgid "%s could not be found. Associated thought will be empty." msgstr "" #: ../labyrinth_lib/ImageThought.py:339 msgid "Change Image" msgstr "" #: ../labyrinth_lib/Browser.py:192 #, python-format msgid "Unable to display help: %s" msgstr "" #: ../labyrinth_lib/Browser.py:223 msgid "Translation by Don Scorgie" msgstr "" #: ../labyrinth_lib/Browser.py:245 msgid "The map cannot be deleted right now. Is it open?" msgstr "" #: ../labyrinth_lib/Browser.py:247 msgid "The map has no associated filename." msgstr "" #: ../labyrinth_lib/Browser.py:250 msgid "Cannot delete this map" msgstr "" #: ../labyrinth_lib/Browser.py:257 msgid "Do you really want to delete this Map?" msgstr "" #: ../labyrinth_lib/Browser.py:282 msgid "Open File" msgstr "" #: ../labyrinth_lib/Browser.py:286 msgid "MAPZ Compressed Map (*.mapz)" msgstr "" #: ../labyrinth_lib/Browser.py:317 msgid "Map Name" msgstr "" #: ../labyrinth_lib/Browser.py:324 msgid "Last Modified" msgstr "" #: ../labyrinth_lib/Links.py:265 msgid "Choose Color" msgstr "" #: ../labyrinth_lib/Links.py:278 msgid "Set Color" msgstr "" #: ../labyrinth_lib/MainWindow.py:166 ../labyrinth_lib/MainWindow.py:481 msgid "Untitled Map" msgstr "" #: ../labyrinth_lib/MainWindow.py:213 msgid "File" msgstr "" #: ../labyrinth_lib/MainWindow.py:214 msgid "Export as Image" msgstr "" #: ../labyrinth_lib/MainWindow.py:215 msgid "Export your map as an image" msgstr "" #: ../labyrinth_lib/MainWindow.py:216 msgid "Export Map..." msgstr "" #: ../labyrinth_lib/MainWindow.py:217 msgid "Export your map as XML" msgstr "" #: ../labyrinth_lib/MainWindow.py:219 msgid "Close the current window" msgstr "" #: ../labyrinth_lib/MainWindow.py:220 msgid "_Edit" msgstr "" #: ../labyrinth_lib/MainWindow.py:221 msgid "_View" msgstr "" #: ../labyrinth_lib/MainWindow.py:222 msgid "_Toolbar" msgstr "" #: ../labyrinth_lib/MainWindow.py:231 msgid "Link Thoughts" msgstr "" #: ../labyrinth_lib/MainWindow.py:232 msgid "Link the selected thoughts" msgstr "" #: ../labyrinth_lib/MainWindow.py:233 msgid "_Mode" msgstr "" #: ../labyrinth_lib/MainWindow.py:241 msgid "_Edit Mode" msgstr "" #: ../labyrinth_lib/MainWindow.py:242 msgid "Turn on edit mode" msgstr "" #: ../labyrinth_lib/MainWindow.py:243 msgid "_Add Image" msgstr "" #: ../labyrinth_lib/MainWindow.py:244 msgid "Add an image to selected thought" msgstr "" #: ../labyrinth_lib/MainWindow.py:245 msgid "_Drawing Mode" msgstr "" #: ../labyrinth_lib/MainWindow.py:246 msgid "Make a pretty drawing" msgstr "" #: ../labyrinth_lib/MainWindow.py:248 msgid "Use _Curves" msgstr "" #: ../labyrinth_lib/MainWindow.py:249 msgid "Use curves as links" msgstr "" #: ../labyrinth_lib/MainWindow.py:250 msgid "Use _Lines" msgstr "" #: ../labyrinth_lib/MainWindow.py:251 msgid "Use straight lines as links" msgstr "" #: ../labyrinth_lib/MainWindow.py:253 msgid "_Extended Information" msgstr "" #: ../labyrinth_lib/MainWindow.py:254 msgid "Show extended information for thoughts" msgstr "" #: ../labyrinth_lib/MainWindow.py:255 msgid "_Main" msgstr "" #: ../labyrinth_lib/MainWindow.py:256 msgid "Show main toolbar" msgstr "" #: ../labyrinth_lib/MainWindow.py:257 msgid "_Format" msgstr "" #: ../labyrinth_lib/MainWindow.py:258 msgid "Show format toolbar" msgstr "" #: ../labyrinth_lib/MainWindow.py:536 msgid "Save File As" msgstr "" #: ../labyrinth_lib/MainWindow.py:630 msgid "All Files" msgstr "" #: ../labyrinth_lib/MainWindow.py:631 msgid "PNG Image (*.png)" msgstr "" #: ../labyrinth_lib/MainWindow.py:632 msgid "JPEG Image (*.jpg, *.jpeg)" msgstr "" #: ../labyrinth_lib/MainWindow.py:633 msgid "SVG Vector Image (*.svg)" msgstr "" #: ../labyrinth_lib/MainWindow.py:634 msgid "PDF Portable Document (*.pdf)" msgstr "" #: ../labyrinth_lib/MainWindow.py:670 msgid "Unknown file format" msgstr "" #: ../labyrinth_lib/MainWindow.py:671 #, python-format msgid "" "The file type '%s' is unsupported. Please use the suffix '.png', '.jpg' or " "'.svg'." msgstr "" #: ../labyrinth_lib/ResourceThought.py:128 msgid "Edit Text" msgstr "" #: ../labyrinth_lib/ResourceThought.py:133 msgid "Edit URI" msgstr "" #: ../labyrinth_lib/DrawingThought.py:65 #, python-format msgid "Drawing #%d" msgstr "" #: ../data/labyrinth.glade:7 msgid "Export Map as Image" msgstr "" #: ../data/labyrinth.glade:87 msgid "Complete Map" msgstr "" #: ../data/labyrinth.glade:101 msgid "Visible Area" msgstr "" #: ../data/labyrinth.glade:157 msgid "Width" msgstr "" #: ../data/labyrinth.glade:172 msgid "Height" msgstr "" #: ../data/labyrinth.glade:226 msgid "Export Map" msgstr "" #: ../data/labyrinth.glade:245 msgid "Labyrinth Maps" msgstr "" #: ../data/labyrinth.glade:259 msgid "_File" msgstr "" #: ../data/labyrinth.glade:299 msgid "Import..." msgstr "" #: ../data/labyrinth.glade:329 msgid "_Help" msgstr "" #: ../data/labyrinth.glade:765 msgid "URL" msgstr "" #: ../data/labyrinth.glade:806 msgid "Align Left" msgstr "" #: ../data/labyrinth.glade:825 msgid "Align Right" msgstr "" #: ../data/labyrinth.glade:844 msgid "Align Vertical Center" msgstr "" #: ../data/labyrinth.glade:863 msgid "Align Top" msgstr "" #: ../data/labyrinth.glade:882 msgid "Align Bottom" msgstr "" #: ../data/labyrinth.glade:901 msgid "Align Horizontal Center" msgstr "" labyrinth-0.6/po/nl.po000066400000000000000000000206161204476542500147600ustar00rootroot00000000000000# translation of nl.po to Dutch # Rigo Ketelings , Max Beauchez \n" "Language-Team: Dutch \n" "Language: nl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" #: ../labyrinth_lib/ImageThought.py:68 msgid "Choose image to insert" msgstr "Kies in te voegen afbeelding" #: ../labyrinth_lib/ImageThought.py:323 msgid "Error loading file" msgstr "Fout tijdens laden bestand" #: ../labyrinth_lib/ImageThought.py:324 #, python-format msgid "%s could not be found. Associated thought will be empty." msgstr "%s kon niet gevonden worden. Geassocieerde gedachte zal leeg zijn." #: ../labyrinth_lib/ImageThought.py:339 msgid "Change Image" msgstr "" #: ../labyrinth_lib/Browser.py:192 #, python-format msgid "Unable to display help: %s" msgstr "" #: ../labyrinth_lib/Browser.py:223 msgid "Translation by Don Scorgie" msgstr "" #: ../labyrinth_lib/Browser.py:245 #, fuzzy msgid "The map cannot be deleted right now. Is it open?" msgstr "De map kan op dit moment niet verwijderd worden. Is de map geopend?" #: ../labyrinth_lib/Browser.py:247 msgid "The map has no associated filename." msgstr "De map heeft geen geassocieerde bestandsnaam" #: ../labyrinth_lib/Browser.py:250 msgid "Cannot delete this map" msgstr "Kan deze map niet verwijderen" #: ../labyrinth_lib/Browser.py:257 msgid "Do you really want to delete this Map?" msgstr "Weet je zeker dat je deze map wilt verwijderen?" #: ../labyrinth_lib/Browser.py:282 #, fuzzy msgid "Open File" msgstr "_Bestand" #: ../labyrinth_lib/Browser.py:286 msgid "MAPZ Compressed Map (*.mapz)" msgstr "" #: ../labyrinth_lib/Browser.py:317 msgid "Map Name" msgstr "Naam map" #: ../labyrinth_lib/Browser.py:324 msgid "Last Modified" msgstr "" #: ../labyrinth_lib/Links.py:265 msgid "Choose Color" msgstr "" #: ../labyrinth_lib/Links.py:278 msgid "Set Color" msgstr "" #: ../labyrinth_lib/MainWindow.py:166 ../labyrinth_lib/MainWindow.py:481 #, fuzzy msgid "Untitled Map" msgstr "Naamloze map %d" #: ../labyrinth_lib/MainWindow.py:213 #, fuzzy msgid "File" msgstr "_Bestand" #: ../labyrinth_lib/MainWindow.py:214 msgid "Export as Image" msgstr "Exporteer als afbeelding" #: ../labyrinth_lib/MainWindow.py:215 msgid "Export your map as an image" msgstr "Exporteer uw map als afbeelding" #: ../labyrinth_lib/MainWindow.py:216 #, fuzzy msgid "Export Map..." msgstr "Map exporteren" #: ../labyrinth_lib/MainWindow.py:217 #, fuzzy msgid "Export your map as XML" msgstr "Exporteer uw map als afbeelding" #: ../labyrinth_lib/MainWindow.py:219 msgid "Close the current window" msgstr "Sluit het huidige scherm" #: ../labyrinth_lib/MainWindow.py:220 #, fuzzy msgid "_Edit" msgstr "_Bewerk-mode" #: ../labyrinth_lib/MainWindow.py:221 msgid "_View" msgstr "" #: ../labyrinth_lib/MainWindow.py:222 msgid "_Toolbar" msgstr "" #: ../labyrinth_lib/MainWindow.py:231 #, fuzzy msgid "Link Thoughts" msgstr "Verbind/verbreek de gedachte(n)" #: ../labyrinth_lib/MainWindow.py:232 #, fuzzy msgid "Link the selected thoughts" msgstr "Afbeelding toevoegen aan geselecteerde gedachte" #: ../labyrinth_lib/MainWindow.py:233 msgid "_Mode" msgstr "_Mode" #: ../labyrinth_lib/MainWindow.py:241 msgid "_Edit Mode" msgstr "_Bewerk-mode" #: ../labyrinth_lib/MainWindow.py:242 msgid "Turn on edit mode" msgstr "Bewerk-mode aanzetten" #: ../labyrinth_lib/MainWindow.py:243 msgid "_Add Image" msgstr "_Afbeelding toevoegen" #: ../labyrinth_lib/MainWindow.py:244 msgid "Add an image to selected thought" msgstr "Afbeelding toevoegen aan geselecteerde gedachte" #: ../labyrinth_lib/MainWindow.py:245 msgid "_Drawing Mode" msgstr "_Teken-mode" #: ../labyrinth_lib/MainWindow.py:246 msgid "Make a pretty drawing" msgstr "Maak een mooie tekening" #: ../labyrinth_lib/MainWindow.py:248 msgid "Use _Curves" msgstr "" #: ../labyrinth_lib/MainWindow.py:249 msgid "Use curves as links" msgstr "" #: ../labyrinth_lib/MainWindow.py:250 msgid "Use _Lines" msgstr "" #: ../labyrinth_lib/MainWindow.py:251 msgid "Use straight lines as links" msgstr "" #: ../labyrinth_lib/MainWindow.py:253 msgid "_Extended Information" msgstr "" #: ../labyrinth_lib/MainWindow.py:254 #, fuzzy msgid "Show extended information for thoughts" msgstr "Uitgebreiden gedachteninformatie laten zien" #: ../labyrinth_lib/MainWindow.py:255 msgid "_Main" msgstr "" #: ../labyrinth_lib/MainWindow.py:256 msgid "Show main toolbar" msgstr "" #: ../labyrinth_lib/MainWindow.py:257 msgid "_Format" msgstr "" #: ../labyrinth_lib/MainWindow.py:258 msgid "Show format toolbar" msgstr "" #: ../labyrinth_lib/MainWindow.py:536 msgid "Save File As" msgstr "" #: ../labyrinth_lib/MainWindow.py:630 #, fuzzy msgid "All Files" msgstr "_Bestand" #: ../labyrinth_lib/MainWindow.py:631 msgid "PNG Image (*.png)" msgstr "" #: ../labyrinth_lib/MainWindow.py:632 msgid "JPEG Image (*.jpg, *.jpeg)" msgstr "" #: ../labyrinth_lib/MainWindow.py:633 msgid "SVG Vector Image (*.svg)" msgstr "" #: ../labyrinth_lib/MainWindow.py:634 msgid "PDF Portable Document (*.pdf)" msgstr "" #: ../labyrinth_lib/MainWindow.py:670 msgid "Unknown file format" msgstr "Onbekend bestandsformaat" #: ../labyrinth_lib/MainWindow.py:671 #, fuzzy, python-format msgid "" "The file type '%s' is unsupported. Please use the suffix '.png', '.jpg' or " "'.svg'." msgstr "" "Het bestandstype '%s' wordt niet ondersteund. Gebruik de extensie '.png' of " "'.jpg'." #: ../labyrinth_lib/ResourceThought.py:128 #, fuzzy msgid "Edit Text" msgstr "_Bewerk-mode" #: ../labyrinth_lib/ResourceThought.py:133 #, fuzzy msgid "Edit URI" msgstr "_Bewerk-mode" #: ../labyrinth_lib/DrawingThought.py:65 #, python-format msgid "Drawing #%d" msgstr "Tekenen #%d" #: ../data/labyrinth.glade:7 msgid "Export Map as Image" msgstr "Map als afbeeldingen exporteren" #: ../data/labyrinth.glade:87 #, fuzzy msgid "Complete Map" msgstr "Verwijder map" #: ../data/labyrinth.glade:101 msgid "Visible Area" msgstr "Zichtbaar gebied" #: ../data/labyrinth.glade:157 msgid "Width" msgstr "Breedte" #: ../data/labyrinth.glade:172 msgid "Height" msgstr "Hoogte" #: ../data/labyrinth.glade:226 msgid "Export Map" msgstr "Map exporteren" #: ../data/labyrinth.glade:245 msgid "Labyrinth Maps" msgstr "Labyrinth maps" #: ../data/labyrinth.glade:259 #, fuzzy msgid "_File" msgstr "_Bestand" #: ../data/labyrinth.glade:299 msgid "Import..." msgstr "" #: ../data/labyrinth.glade:329 msgid "_Help" msgstr "_Help" #: ../data/labyrinth.glade:765 msgid "URL" msgstr "" #: ../data/labyrinth.glade:806 msgid "Align Left" msgstr "" #: ../data/labyrinth.glade:825 msgid "Align Right" msgstr "" #: ../data/labyrinth.glade:844 msgid "Align Vertical Center" msgstr "" #: ../data/labyrinth.glade:863 msgid "Align Top" msgstr "" #: ../data/labyrinth.glade:882 msgid "Align Bottom" msgstr "" #: ../data/labyrinth.glade:901 msgid "Align Horizontal Center" msgstr "" #~ msgid "_Delete Selected Thoughts" #~ msgstr "_Verwijder geselecteerde gedachten" #~ msgid "Delete the selected element(s)" #~ msgstr "Verwijder geselecteerd(e) element(en)" #~ msgid "_View Extended" #~ msgstr "Uitgebreide blik" #~ msgid "Labyrinth Mind-mapping" #~ msgstr "Labyrinth Mind-mapping" #~ msgid "Map your mind" #~ msgstr "Map je gedachten" #~ msgid "Mind-mapping" #~ msgstr "Mind-mapping" #~ msgid "Learn about the application" #~ msgstr "Hulp bij de applicatie" #~ msgid "Delete Map" #~ msgstr "Verwijder map" #~ msgid "New Map" #~ msgstr "Nieuwe map" #~ msgid "Open Map" #~ msgstr "Open map" #~ msgid "Quit" #~ msgstr "Afsluiten" #~ msgid "_New" #~ msgstr "_Nieuw" #~ msgid "Create a new mind-map" #~ msgstr "Creëer een nieuwe mind-map" #~ msgid "_Close" #~ msgstr "_Sluit" #~ msgid "_Quit" #~ msgstr "_Afsluiten" #~ msgid "Close all the windows and exit the application" #~ msgstr "Sluit alle schermen en verlaat de applicatie" #~ msgid "_About" #~ msgstr "_Over" #~ msgid "Somethings broken" #~ msgstr "Er is iets kapot." #~ msgid "_Move Mode" #~ msgstr "_Verplaats-mode" #~ msgid "Turn on move mode" #~ msgstr "Zet verplaats-mode aan" #~ msgid "%s could not be read. Please ensure its a valid image." #~ msgstr "" #~ "%s kon niet gelezen worden. Verifieer of het daadwerkelijk een afbeelding " #~ "is." labyrinth-0.6/po/pl.po000066400000000000000000000176101204476542500147620ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # msgid "" msgstr "" "Project-Id-Version: Labyrinth\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2012-09-23 18:55+0100\n" "PO-Revision-Date: 2006-10-11 21:07+0100\n" "Last-Translator: Tomasz Dominikowski \n" "Language-Team: Tomasz Dominikowski \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Poedit-Language: Polish\n" "X-Poedit-Country: Poland\n" #: ../labyrinth_lib/ImageThought.py:68 msgid "Choose image to insert" msgstr "Wybierz obraz do wstawienia" #: ../labyrinth_lib/ImageThought.py:323 msgid "Error loading file" msgstr "Błąd podczas wczytywania pliku" #: ../labyrinth_lib/ImageThought.py:324 #, python-format msgid "%s could not be found. Associated thought will be empty." msgstr "%s nie mógł zostać odnaleziony. Związana myśl będzie pusta." #: ../labyrinth_lib/ImageThought.py:339 msgid "Change Image" msgstr "" #: ../labyrinth_lib/Browser.py:192 #, python-format msgid "Unable to display help: %s" msgstr "" #: ../labyrinth_lib/Browser.py:223 msgid "Translation by Don Scorgie" msgstr "" #: ../labyrinth_lib/Browser.py:245 #, fuzzy msgid "The map cannot be deleted right now. Is it open?" msgstr "Mapa nie może teraz zostać usunięta. Czy jest otwarta?" #: ../labyrinth_lib/Browser.py:247 msgid "The map has no associated filename." msgstr "" #: ../labyrinth_lib/Browser.py:250 msgid "Cannot delete this map" msgstr "Nie można usunąć tej mapy" #: ../labyrinth_lib/Browser.py:257 msgid "Do you really want to delete this Map?" msgstr "Czy chcesz usunąć tę mapę?" #: ../labyrinth_lib/Browser.py:282 msgid "Open File" msgstr "" #: ../labyrinth_lib/Browser.py:286 msgid "MAPZ Compressed Map (*.mapz)" msgstr "" #: ../labyrinth_lib/Browser.py:317 msgid "Map Name" msgstr "" #: ../labyrinth_lib/Browser.py:324 msgid "Last Modified" msgstr "" #: ../labyrinth_lib/Links.py:265 msgid "Choose Color" msgstr "" #: ../labyrinth_lib/Links.py:278 msgid "Set Color" msgstr "" #: ../labyrinth_lib/MainWindow.py:166 ../labyrinth_lib/MainWindow.py:481 #, fuzzy msgid "Untitled Map" msgstr "Nienazwana mapa %d" #: ../labyrinth_lib/MainWindow.py:213 msgid "File" msgstr "" #: ../labyrinth_lib/MainWindow.py:214 msgid "Export as Image" msgstr "" #: ../labyrinth_lib/MainWindow.py:215 msgid "Export your map as an image" msgstr "" #: ../labyrinth_lib/MainWindow.py:216 msgid "Export Map..." msgstr "" #: ../labyrinth_lib/MainWindow.py:217 msgid "Export your map as XML" msgstr "" #: ../labyrinth_lib/MainWindow.py:219 msgid "Close the current window" msgstr "Zamknij bieżące okno" #: ../labyrinth_lib/MainWindow.py:220 #, fuzzy msgid "_Edit" msgstr "Tryb _modyfikowania" #: ../labyrinth_lib/MainWindow.py:221 msgid "_View" msgstr "" #: ../labyrinth_lib/MainWindow.py:222 msgid "_Toolbar" msgstr "" #: ../labyrinth_lib/MainWindow.py:231 msgid "Link Thoughts" msgstr "" #: ../labyrinth_lib/MainWindow.py:232 #, fuzzy msgid "Link the selected thoughts" msgstr "Dodaj obraz do wybranej myśli" #: ../labyrinth_lib/MainWindow.py:233 #, fuzzy msgid "_Mode" msgstr "Tryb _modyfikowania" #: ../labyrinth_lib/MainWindow.py:241 msgid "_Edit Mode" msgstr "Tryb _modyfikowania" #: ../labyrinth_lib/MainWindow.py:242 msgid "Turn on edit mode" msgstr "Włącz tryb modyfikowania" #: ../labyrinth_lib/MainWindow.py:243 msgid "_Add Image" msgstr "_Dodaj obraz" #: ../labyrinth_lib/MainWindow.py:244 msgid "Add an image to selected thought" msgstr "Dodaj obraz do wybranej myśli" #: ../labyrinth_lib/MainWindow.py:245 msgid "_Drawing Mode" msgstr "Tryb _rysowania" #: ../labyrinth_lib/MainWindow.py:246 msgid "Make a pretty drawing" msgstr "Utwórz piękny rysunek" #: ../labyrinth_lib/MainWindow.py:248 msgid "Use _Curves" msgstr "" #: ../labyrinth_lib/MainWindow.py:249 msgid "Use curves as links" msgstr "" #: ../labyrinth_lib/MainWindow.py:250 msgid "Use _Lines" msgstr "" #: ../labyrinth_lib/MainWindow.py:251 msgid "Use straight lines as links" msgstr "" #: ../labyrinth_lib/MainWindow.py:253 msgid "_Extended Information" msgstr "" #: ../labyrinth_lib/MainWindow.py:254 msgid "Show extended information for thoughts" msgstr "" #: ../labyrinth_lib/MainWindow.py:255 msgid "_Main" msgstr "" #: ../labyrinth_lib/MainWindow.py:256 msgid "Show main toolbar" msgstr "" #: ../labyrinth_lib/MainWindow.py:257 msgid "_Format" msgstr "" #: ../labyrinth_lib/MainWindow.py:258 msgid "Show format toolbar" msgstr "" #: ../labyrinth_lib/MainWindow.py:536 msgid "Save File As" msgstr "" #: ../labyrinth_lib/MainWindow.py:630 msgid "All Files" msgstr "" #: ../labyrinth_lib/MainWindow.py:631 msgid "PNG Image (*.png)" msgstr "" #: ../labyrinth_lib/MainWindow.py:632 msgid "JPEG Image (*.jpg, *.jpeg)" msgstr "" #: ../labyrinth_lib/MainWindow.py:633 msgid "SVG Vector Image (*.svg)" msgstr "" #: ../labyrinth_lib/MainWindow.py:634 msgid "PDF Portable Document (*.pdf)" msgstr "" #: ../labyrinth_lib/MainWindow.py:670 msgid "Unknown file format" msgstr "" #: ../labyrinth_lib/MainWindow.py:671 #, python-format msgid "" "The file type '%s' is unsupported. Please use the suffix '.png', '.jpg' or " "'.svg'." msgstr "" #: ../labyrinth_lib/ResourceThought.py:128 #, fuzzy msgid "Edit Text" msgstr "Tryb _modyfikowania" #: ../labyrinth_lib/ResourceThought.py:133 #, fuzzy msgid "Edit URI" msgstr "Tryb _modyfikowania" #: ../labyrinth_lib/DrawingThought.py:65 #, python-format msgid "Drawing #%d" msgstr "Rysunek #%d" #: ../data/labyrinth.glade:7 msgid "Export Map as Image" msgstr "" #: ../data/labyrinth.glade:87 #, fuzzy msgid "Complete Map" msgstr "Usuń mapę" #: ../data/labyrinth.glade:101 msgid "Visible Area" msgstr "" #: ../data/labyrinth.glade:157 msgid "Width" msgstr "" #: ../data/labyrinth.glade:172 msgid "Height" msgstr "" #: ../data/labyrinth.glade:226 msgid "Export Map" msgstr "" #: ../data/labyrinth.glade:245 msgid "Labyrinth Maps" msgstr "Mapy Labyrinth" #: ../data/labyrinth.glade:259 msgid "_File" msgstr "" #: ../data/labyrinth.glade:299 msgid "Import..." msgstr "" #: ../data/labyrinth.glade:329 msgid "_Help" msgstr "" #: ../data/labyrinth.glade:765 msgid "URL" msgstr "" #: ../data/labyrinth.glade:806 msgid "Align Left" msgstr "" #: ../data/labyrinth.glade:825 msgid "Align Right" msgstr "" #: ../data/labyrinth.glade:844 msgid "Align Vertical Center" msgstr "" #: ../data/labyrinth.glade:863 msgid "Align Top" msgstr "" #: ../data/labyrinth.glade:882 msgid "Align Bottom" msgstr "" #: ../data/labyrinth.glade:901 msgid "Align Horizontal Center" msgstr "" #~ msgid "_Delete Selected Thoughts" #~ msgstr "_Usuń wybrane myśli" #~ msgid "Delete the selected element(s)" #~ msgstr "Usuń zaznaczony(-e) element(-y)" #~ msgid "Labyrinth Mind-mapping" #~ msgstr "Mapowanie myśli Labyrinth" #~ msgid "Map your mind" #~ msgstr "Mapowanie myśli" #~ msgid "Mind-mapping" #~ msgstr "Mapowanie myśli" #~ msgid "Learn about the application" #~ msgstr "Dowiedz się o tej aplikacji" #~ msgid "Delete Map" #~ msgstr "Usuń mapę" #~ msgid "New Map" #~ msgstr "Nowa mapa" #~ msgid "Open Map" #~ msgstr "Otwórz mapę" #~ msgid "Quit" #~ msgstr "Zakończ" #~ msgid "_New" #~ msgstr "_Nowa" #~ msgid "Create a new mind-map" #~ msgstr "Utwórz nową mapę myśli" #~ msgid "_Close" #~ msgstr "Z_amknij" #~ msgid "_Quit" #~ msgstr "_Zakończ" #~ msgid "Close all the windows and exit the application" #~ msgstr "Zamknij wszystkie okna i zakończ aplikację" #~ msgid "_About" #~ msgstr "_O programie" #~ msgid "Somethings broken" #~ msgstr "Coś jest zepsute" #~ msgid "_Move Mode" #~ msgstr "Tryb _przemieszczania" #~ msgid "Turn on move mode" #~ msgstr "Włącz tryb przemieszczania" #~ msgid "%s could not be read. Please ensure its a valid image." #~ msgstr "" #~ "%s nie mógł zostać odczytany. Proszę sprawdzić, czy jest to poprawny " #~ "obraz." labyrinth-0.6/po/pt_BR.po000066400000000000000000000171201204476542500153510ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Translators: # Leonardo Gregianin , 2006. # , 2012. msgid "" msgstr "" "Project-Id-Version: Labyrinth\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2012-09-23 18:55+0100\n" "PO-Revision-Date: 2012-09-28 16:28+0000\n" "Last-Translator: salmora8 \n" "Language-Team: LANGUAGE \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Language: pt_BR\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" #: ../labyrinth_lib/ImageThought.py:68 msgid "Choose image to insert" msgstr "Escolha a imagem para inserir" #: ../labyrinth_lib/ImageThought.py:323 msgid "Error loading file" msgstr "Erro ao carregar arquivo" #: ../labyrinth_lib/ImageThought.py:324 #, python-format msgid "%s could not be found. Associated thought will be empty." msgstr "%s não pode ser encontrado. O nó associado estará vazio." #: ../labyrinth_lib/ImageThought.py:339 msgid "Change Image" msgstr "Alterar Imagem" #: ../labyrinth_lib/Browser.py:192 #, python-format msgid "Unable to display help: %s" msgstr "Não foi possível exibir ajuda: %s" #: ../labyrinth_lib/Browser.py:223 msgid "Translation by Don Scorgie" msgstr "Tradução por Alexandro Casanova" #: ../labyrinth_lib/Browser.py:245 msgid "The map cannot be deleted right now. Is it open?" msgstr "O mapa não pode ser excluído no momento. Ele está aberto?" #: ../labyrinth_lib/Browser.py:247 msgid "The map has no associated filename." msgstr "O mapa não tem nenhum nome de arquivo associado." #: ../labyrinth_lib/Browser.py:250 msgid "Cannot delete this map" msgstr "Não foi possível apagar este mapa" #: ../labyrinth_lib/Browser.py:257 msgid "Do you really want to delete this Map?" msgstr "Vocé quer realmente apagar este mapa?" #: ../labyrinth_lib/Browser.py:282 msgid "Open File" msgstr "Abrir Arquivo" #: ../labyrinth_lib/Browser.py:286 msgid "MAPZ Compressed Map (*.mapz)" msgstr "MAPZ Compressed Map (*.mapz)" #: ../labyrinth_lib/Browser.py:317 msgid "Map Name" msgstr "Nome do Mapa" #: ../labyrinth_lib/Browser.py:324 msgid "Last Modified" msgstr "Última Modificação" #: ../labyrinth_lib/Links.py:265 msgid "Choose Color" msgstr "Escolha a Cor" #: ../labyrinth_lib/Links.py:278 msgid "Set Color" msgstr "Definir Cor" #: ../labyrinth_lib/MainWindow.py:166 ../labyrinth_lib/MainWindow.py:481 msgid "Untitled Map" msgstr "Mapa sem Título" #: ../labyrinth_lib/MainWindow.py:213 msgid "File" msgstr "Arquivo" #: ../labyrinth_lib/MainWindow.py:214 msgid "Export as Image" msgstr "Exportar como Imagem" #: ../labyrinth_lib/MainWindow.py:215 msgid "Export your map as an image" msgstr "Exportar seu mapa como uma imagem" #: ../labyrinth_lib/MainWindow.py:216 msgid "Export Map..." msgstr "Exportar Mapa..." #: ../labyrinth_lib/MainWindow.py:217 msgid "Export your map as XML" msgstr "Exportar seu mapa como XML" #: ../labyrinth_lib/MainWindow.py:219 msgid "Close the current window" msgstr "Fechar a janela atual" #: ../labyrinth_lib/MainWindow.py:220 msgid "_Edit" msgstr "_Editar" #: ../labyrinth_lib/MainWindow.py:221 msgid "_View" msgstr "_Ver" #: ../labyrinth_lib/MainWindow.py:222 msgid "_Toolbar" msgstr "_Barra de Ferramentas" #: ../labyrinth_lib/MainWindow.py:231 msgid "Link Thoughts" msgstr "Link de Nós" #: ../labyrinth_lib/MainWindow.py:232 msgid "Link the selected thoughts" msgstr "Vincular os nós selecionados" #: ../labyrinth_lib/MainWindow.py:233 msgid "_Mode" msgstr "_Modo" #: ../labyrinth_lib/MainWindow.py:241 msgid "_Edit Mode" msgstr "_Modo Editar" #: ../labyrinth_lib/MainWindow.py:242 msgid "Turn on edit mode" msgstr "Voltar ao modo de edição" #: ../labyrinth_lib/MainWindow.py:243 msgid "_Add Image" msgstr "_Adicionar Imagem" #: ../labyrinth_lib/MainWindow.py:244 msgid "Add an image to selected thought" msgstr "Adicione uma imagem para o nó selecionado" #: ../labyrinth_lib/MainWindow.py:245 msgid "_Drawing Mode" msgstr "_Modo Desenho" #: ../labyrinth_lib/MainWindow.py:246 msgid "Make a pretty drawing" msgstr "Fazer um desenho" #: ../labyrinth_lib/MainWindow.py:248 msgid "Use _Curves" msgstr "Usar _Curvas" #: ../labyrinth_lib/MainWindow.py:249 msgid "Use curves as links" msgstr "Usar curvas como links" #: ../labyrinth_lib/MainWindow.py:250 msgid "Use _Lines" msgstr "Usar _Linhas" #: ../labyrinth_lib/MainWindow.py:251 msgid "Use straight lines as links" msgstr "Usar linhas retas como links" #: ../labyrinth_lib/MainWindow.py:253 msgid "_Extended Information" msgstr "_Informação Adicional" #: ../labyrinth_lib/MainWindow.py:254 msgid "Show extended information for thoughts" msgstr "Mostrar informação adicional dos nós" #: ../labyrinth_lib/MainWindow.py:255 msgid "_Main" msgstr "_Principal" #: ../labyrinth_lib/MainWindow.py:256 msgid "Show main toolbar" msgstr "Mostrar barra de ferramentas principal" #: ../labyrinth_lib/MainWindow.py:257 msgid "_Format" msgstr "_Formatação" #: ../labyrinth_lib/MainWindow.py:258 msgid "Show format toolbar" msgstr "_Mostrar barra de formatação" #: ../labyrinth_lib/MainWindow.py:536 msgid "Save File As" msgstr "Salvar Arquivo Como" #: ../labyrinth_lib/MainWindow.py:630 msgid "All Files" msgstr "Todos os Arquivos" #: ../labyrinth_lib/MainWindow.py:631 msgid "PNG Image (*.png)" msgstr "Imagem PNG (*.png)" #: ../labyrinth_lib/MainWindow.py:632 msgid "JPEG Image (*.jpg, *.jpeg)" msgstr "Imagem JPEG (*.jpg, *.jpeg)" #: ../labyrinth_lib/MainWindow.py:633 msgid "SVG Vector Image (*.svg)" msgstr "Imagem Vetorial SVG (*.svg)" #: ../labyrinth_lib/MainWindow.py:634 msgid "PDF Portable Document (*.pdf)" msgstr "Documento Portátil PDF (*.pdf)" #: ../labyrinth_lib/MainWindow.py:670 msgid "Unknown file format" msgstr "Formato de imagem desconhecida" #: ../labyrinth_lib/MainWindow.py:671 #, python-format msgid "" "The file type '%s' is unsupported. Please use the suffix '.png', '.jpg' or " "'.svg'." msgstr "O tipo de arquivo '%s' não é suportado. Favor usar o sufixo '.png', '.jpg' ou '.svg'." #: ../labyrinth_lib/ResourceThought.py:128 msgid "Edit Text" msgstr "Editar Texto" #: ../labyrinth_lib/ResourceThought.py:133 msgid "Edit URI" msgstr "Editar URI" #: ../labyrinth_lib/DrawingThought.py:65 #, python-format msgid "Drawing #%d" msgstr "Desenhando #%d" #: ../data/labyrinth.glade:7 msgid "Export Map as Image" msgstr "Exportar Mapa como Imagem" #: ../data/labyrinth.glade:87 msgid "Complete Map" msgstr "Mapa Completo" #: ../data/labyrinth.glade:101 msgid "Visible Area" msgstr "Área Visível" #: ../data/labyrinth.glade:157 msgid "Width" msgstr "Largura" #: ../data/labyrinth.glade:172 msgid "Height" msgstr "Altura" #: ../data/labyrinth.glade:226 msgid "Export Map" msgstr "Exportar Mapa" #: ../data/labyrinth.glade:245 msgid "Labyrinth Maps" msgstr "Mapas do Labyrinth" #: ../data/labyrinth.glade:259 msgid "_File" msgstr "_Arquivo" #: ../data/labyrinth.glade:299 msgid "Import..." msgstr "Importar..." #: ../data/labyrinth.glade:329 msgid "_Help" msgstr "_Ajuda" #: ../data/labyrinth.glade:765 msgid "URL" msgstr "URL" #: ../data/labyrinth.glade:806 msgid "Align Left" msgstr "Alinhar à Esquerda" #: ../data/labyrinth.glade:825 msgid "Align Right" msgstr "Alinhar à Direita" #: ../data/labyrinth.glade:844 msgid "Align Vertical Center" msgstr "Alinhar no Centro Vertical" #: ../data/labyrinth.glade:863 msgid "Align Top" msgstr "Alinhar no Topo" #: ../data/labyrinth.glade:882 msgid "Align Bottom" msgstr "Alinhar para Baixo" #: ../data/labyrinth.glade:901 msgid "Align Horizontal Center" msgstr "Alinhar no Centro Horizontal" labyrinth-0.6/po/pt_PT.po000066400000000000000000000205311204476542500153710ustar00rootroot00000000000000# labrynth translation to European Portugese. # Copyright (C) 2006 # Luis Gomes , 2006. # msgid "" msgstr "" "Project-Id-Version: pt-pt\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2012-09-23 18:55+0100\n" "PO-Revision-Date: 2006-11-07 15:24+0000\n" "Last-Translator: Luis Gomes \n" "Language-Team: European Portuguese \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" #: ../labyrinth_lib/ImageThought.py:68 msgid "Choose image to insert" msgstr "Escolha a imagem a inserir" #: ../labyrinth_lib/ImageThought.py:323 msgid "Error loading file" msgstr "Erro a carregar ficheiro" #: ../labyrinth_lib/ImageThought.py:324 #, fuzzy, python-format msgid "%s could not be found. Associated thought will be empty." msgstr "%d não foi encontrado. O pensamento associado vai estar vazio." #: ../labyrinth_lib/ImageThought.py:339 msgid "Change Image" msgstr "" #: ../labyrinth_lib/Browser.py:192 #, python-format msgid "Unable to display help: %s" msgstr "" #: ../labyrinth_lib/Browser.py:223 msgid "Translation by Don Scorgie" msgstr "" #: ../labyrinth_lib/Browser.py:245 #, fuzzy msgid "The map cannot be deleted right now. Is it open?" msgstr "O mapa não pode ser apagado. Está aberto?" #: ../labyrinth_lib/Browser.py:247 msgid "The map has no associated filename." msgstr "O mapa não tem nenhum ficheiro associado." #: ../labyrinth_lib/Browser.py:250 msgid "Cannot delete this map" msgstr "Não é possível apagar este mapa" #: ../labyrinth_lib/Browser.py:257 msgid "Do you really want to delete this Map?" msgstr "Quer mesmo apagar este mapa?" #: ../labyrinth_lib/Browser.py:282 #, fuzzy msgid "Open File" msgstr "Ficheiro" #: ../labyrinth_lib/Browser.py:286 msgid "MAPZ Compressed Map (*.mapz)" msgstr "" #: ../labyrinth_lib/Browser.py:317 msgid "Map Name" msgstr "Nome do Mapa" #: ../labyrinth_lib/Browser.py:324 msgid "Last Modified" msgstr "" #: ../labyrinth_lib/Links.py:265 msgid "Choose Color" msgstr "" #: ../labyrinth_lib/Links.py:278 msgid "Set Color" msgstr "" #: ../labyrinth_lib/MainWindow.py:166 ../labyrinth_lib/MainWindow.py:481 #, fuzzy msgid "Untitled Map" msgstr "Mapa Sem Nome %d" #: ../labyrinth_lib/MainWindow.py:213 msgid "File" msgstr "Ficheiro" #: ../labyrinth_lib/MainWindow.py:214 msgid "Export as Image" msgstr "Exportar como Imagem" #: ../labyrinth_lib/MainWindow.py:215 msgid "Export your map as an image" msgstr "Exportar o seu mapa como uma imagem" #: ../labyrinth_lib/MainWindow.py:216 #, fuzzy msgid "Export Map..." msgstr "Exportar Mapa" #: ../labyrinth_lib/MainWindow.py:217 #, fuzzy msgid "Export your map as XML" msgstr "Exportar o seu mapa como uma imagem" #: ../labyrinth_lib/MainWindow.py:219 msgid "Close the current window" msgstr "Fechar esta janela" #: ../labyrinth_lib/MainWindow.py:220 msgid "_Edit" msgstr "_Editar" #: ../labyrinth_lib/MainWindow.py:221 msgid "_View" msgstr "" #: ../labyrinth_lib/MainWindow.py:222 msgid "_Toolbar" msgstr "" #: ../labyrinth_lib/MainWindow.py:231 #, fuzzy msgid "Link Thoughts" msgstr "(Des)Conectar Pensamentos" #: ../labyrinth_lib/MainWindow.py:232 #, fuzzy msgid "Link the selected thoughts" msgstr "(Des)Conectar os pensamentos seleccionados" #: ../labyrinth_lib/MainWindow.py:233 msgid "_Mode" msgstr "_Modo" #: ../labyrinth_lib/MainWindow.py:241 msgid "_Edit Mode" msgstr "Modo de _Edição" #: ../labyrinth_lib/MainWindow.py:242 msgid "Turn on edit mode" msgstr "Ligar o modo de edição" #: ../labyrinth_lib/MainWindow.py:243 msgid "_Add Image" msgstr "_Adicionar Imagem" #: ../labyrinth_lib/MainWindow.py:244 msgid "Add an image to selected thought" msgstr "Adicione uma imagem ao pensamento seleccionado" #: ../labyrinth_lib/MainWindow.py:245 msgid "_Drawing Mode" msgstr "Modo de _Desenho" #: ../labyrinth_lib/MainWindow.py:246 msgid "Make a pretty drawing" msgstr "Fazer um desenho bonito" #: ../labyrinth_lib/MainWindow.py:248 msgid "Use _Curves" msgstr "" #: ../labyrinth_lib/MainWindow.py:249 msgid "Use curves as links" msgstr "" #: ../labyrinth_lib/MainWindow.py:250 msgid "Use _Lines" msgstr "" #: ../labyrinth_lib/MainWindow.py:251 msgid "Use straight lines as links" msgstr "" #: ../labyrinth_lib/MainWindow.py:253 msgid "_Extended Information" msgstr "" #: ../labyrinth_lib/MainWindow.py:254 #, fuzzy msgid "Show extended information for thoughts" msgstr "Ver informação alargada dos pensamentos" #: ../labyrinth_lib/MainWindow.py:255 msgid "_Main" msgstr "" #: ../labyrinth_lib/MainWindow.py:256 msgid "Show main toolbar" msgstr "" #: ../labyrinth_lib/MainWindow.py:257 msgid "_Format" msgstr "" #: ../labyrinth_lib/MainWindow.py:258 msgid "Show format toolbar" msgstr "" #: ../labyrinth_lib/MainWindow.py:536 msgid "Save File As" msgstr "" #: ../labyrinth_lib/MainWindow.py:630 #, fuzzy msgid "All Files" msgstr "Ficheiro" #: ../labyrinth_lib/MainWindow.py:631 msgid "PNG Image (*.png)" msgstr "" #: ../labyrinth_lib/MainWindow.py:632 msgid "JPEG Image (*.jpg, *.jpeg)" msgstr "" #: ../labyrinth_lib/MainWindow.py:633 msgid "SVG Vector Image (*.svg)" msgstr "" #: ../labyrinth_lib/MainWindow.py:634 msgid "PDF Portable Document (*.pdf)" msgstr "" #: ../labyrinth_lib/MainWindow.py:670 msgid "Unknown file format" msgstr "Formato de ficheiro desconhecido" #: ../labyrinth_lib/MainWindow.py:671 #, fuzzy, python-format msgid "" "The file type '%s' is unsupported. Please use the suffix '.png', '.jpg' or " "'.svg'." msgstr "" "O tipo de ficheiro '%s' não é suportado. Por favor use o sufixo '.png' ou '." "jpg'" #: ../labyrinth_lib/ResourceThought.py:128 #, fuzzy msgid "Edit Text" msgstr "Modo de _Edição" #: ../labyrinth_lib/ResourceThought.py:133 #, fuzzy msgid "Edit URI" msgstr "_Editar" #: ../labyrinth_lib/DrawingThought.py:65 #, python-format msgid "Drawing #%d" msgstr "Desenho #%d" #: ../data/labyrinth.glade:7 msgid "Export Map as Image" msgstr "Exportar Mapa como Imagem" #: ../data/labyrinth.glade:87 msgid "Complete Map" msgstr "Mapa Completo" #: ../data/labyrinth.glade:101 msgid "Visible Area" msgstr "Área Visível" #: ../data/labyrinth.glade:157 msgid "Width" msgstr "Largura" #: ../data/labyrinth.glade:172 msgid "Height" msgstr "Altura" #: ../data/labyrinth.glade:226 msgid "Export Map" msgstr "Exportar Mapa" #: ../data/labyrinth.glade:245 msgid "Labyrinth Maps" msgstr "Mapas do Labyrinth" #: ../data/labyrinth.glade:259 msgid "_File" msgstr "_Ficheiro" #: ../data/labyrinth.glade:299 msgid "Import..." msgstr "" #: ../data/labyrinth.glade:329 msgid "_Help" msgstr "_Ajuda" #: ../data/labyrinth.glade:765 msgid "URL" msgstr "" #: ../data/labyrinth.glade:806 msgid "Align Left" msgstr "" #: ../data/labyrinth.glade:825 msgid "Align Right" msgstr "" #: ../data/labyrinth.glade:844 msgid "Align Vertical Center" msgstr "" #: ../data/labyrinth.glade:863 msgid "Align Top" msgstr "" #: ../data/labyrinth.glade:882 msgid "Align Bottom" msgstr "" #: ../data/labyrinth.glade:901 msgid "Align Horizontal Center" msgstr "" #~ msgid "_Delete Selected Thoughts" #~ msgstr "_Apagar pensamentos seleccionados" #~ msgid "Delete the selected element(s)" #~ msgstr "Apagar o(s) elemento(s) seleccionado(s)" #~ msgid "_View Extended" #~ msgstr "_Vista Alargada" #~ msgid "Labyrinth Mind-mapping" #~ msgstr "Labyrinth Mind-mapping" #~ msgid "Map your mind" #~ msgstr "Mapeie a sua mente" #~ msgid "Mind-mapping" #~ msgstr "Mind-mapping" #~ msgid "Learn about the application" #~ msgstr "Saiba mais sobre o programa" #~ msgid "Delete Map" #~ msgstr "Apagar Mapa" #~ msgid "New Map" #~ msgstr "Novo Mapa" #~ msgid "Open Map" #~ msgstr "Abrir Mapa" #~ msgid "Quit" #~ msgstr "Sair" #~ msgid "_New" #~ msgstr "_Novo" #~ msgid "Create a new mind-map" #~ msgstr "Criar um mapa mental novo" #~ msgid "_Close" #~ msgstr "_Fechar" #~ msgid "_Quit" #~ msgstr "_Sair" #~ msgid "Close all the windows and exit the application" #~ msgstr "Fechar todas as janelas e sair do programa" #~ msgid "_About" #~ msgstr "_Sobre" #~ msgid "Somethings broken" #~ msgstr "Algo se partiu" #~ msgid "_Move Mode" #~ msgstr "_Modo de Movimentação" #~ msgid "Turn on move mode" #~ msgstr "Ligar o modo de movimentação" #~ msgid "%s could not be read. Please ensure its a valid image." #~ msgstr "" #~ "%s não pode ser lida. Por favor certifique-se de que é uma imagem válida." labyrinth-0.6/po/ru.po000066400000000000000000000207751204476542500150030ustar00rootroot00000000000000# translation of ru.po to Russian # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # # Alexandre Prokoudine , 2006. msgid "" msgstr "" "Project-Id-Version: ru\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2012-09-23 18:55+0100\n" "PO-Revision-Date: 2006-11-27 06:31+0300\n" "Last-Translator: Alexandre Prokoudine \n" "Language-Team: Russian \n" "Language: ru\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "X-Generator: KBabel 1.11.4\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n" "%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" #: ../labyrinth_lib/ImageThought.py:68 msgid "Choose image to insert" msgstr "Выберите изображения для вставки" #: ../labyrinth_lib/ImageThought.py:323 msgid "Error loading file" msgstr "Ошибка при загрузке файла" #: ../labyrinth_lib/ImageThought.py:324 #, python-format msgid "%s could not be found. Associated thought will be empty." msgstr "Не удалось найти %s. Ассоциированная мысль будет пустой." #: ../labyrinth_lib/ImageThought.py:339 msgid "Change Image" msgstr "" #: ../labyrinth_lib/Browser.py:192 #, python-format msgid "Unable to display help: %s" msgstr "" #: ../labyrinth_lib/Browser.py:223 msgid "Translation by Don Scorgie" msgstr "" #: ../labyrinth_lib/Browser.py:245 #, fuzzy msgid "The map cannot be deleted right now. Is it open?" msgstr "Эту карту сейчас невозможно удалить. Она открыта?" #: ../labyrinth_lib/Browser.py:247 msgid "The map has no associated filename." msgstr "С этой картой не ассоциировано ни одно имя файла." #: ../labyrinth_lib/Browser.py:250 msgid "Cannot delete this map" msgstr "Невозможно удалить эту карту" #: ../labyrinth_lib/Browser.py:257 msgid "Do you really want to delete this Map?" msgstr "Вы действительно хотите удалить эту карту?" #: ../labyrinth_lib/Browser.py:282 #, fuzzy msgid "Open File" msgstr "Файл" #: ../labyrinth_lib/Browser.py:286 msgid "MAPZ Compressed Map (*.mapz)" msgstr "" #: ../labyrinth_lib/Browser.py:317 msgid "Map Name" msgstr "Название карты" #: ../labyrinth_lib/Browser.py:324 msgid "Last Modified" msgstr "" #: ../labyrinth_lib/Links.py:265 msgid "Choose Color" msgstr "" #: ../labyrinth_lib/Links.py:278 msgid "Set Color" msgstr "" #: ../labyrinth_lib/MainWindow.py:166 ../labyrinth_lib/MainWindow.py:481 #, fuzzy msgid "Untitled Map" msgstr "Безымянная карта %d" #: ../labyrinth_lib/MainWindow.py:213 msgid "File" msgstr "Файл" #: ../labyrinth_lib/MainWindow.py:214 msgid "Export as Image" msgstr "Экспортировать как изображение" #: ../labyrinth_lib/MainWindow.py:215 msgid "Export your map as an image" msgstr "Экспортировать карту как изображение" #: ../labyrinth_lib/MainWindow.py:216 #, fuzzy msgid "Export Map..." msgstr "Экспорт карты" #: ../labyrinth_lib/MainWindow.py:217 #, fuzzy msgid "Export your map as XML" msgstr "Экспортировать карту как изображение" #: ../labyrinth_lib/MainWindow.py:219 msgid "Close the current window" msgstr "Закрыть активное окно" #: ../labyrinth_lib/MainWindow.py:220 msgid "_Edit" msgstr "_Правка" #: ../labyrinth_lib/MainWindow.py:221 msgid "_View" msgstr "" #: ../labyrinth_lib/MainWindow.py:222 msgid "_Toolbar" msgstr "" #: ../labyrinth_lib/MainWindow.py:231 #, fuzzy msgid "Link Thoughts" msgstr "Связать или отсоединить мысли" #: ../labyrinth_lib/MainWindow.py:232 #, fuzzy msgid "Link the selected thoughts" msgstr "Связать или отсоединить выбранные мысли" #: ../labyrinth_lib/MainWindow.py:233 msgid "_Mode" msgstr "_Режим" #: ../labyrinth_lib/MainWindow.py:241 msgid "_Edit Mode" msgstr "_Правка" #: ../labyrinth_lib/MainWindow.py:242 msgid "Turn on edit mode" msgstr "Переключиться на режим правки" #: ../labyrinth_lib/MainWindow.py:243 msgid "_Add Image" msgstr "Добавить _изображение" #: ../labyrinth_lib/MainWindow.py:244 msgid "Add an image to selected thought" msgstr "Добавить изображение к выбранной мысли" #: ../labyrinth_lib/MainWindow.py:245 msgid "_Drawing Mode" msgstr "Рисование" #: ../labyrinth_lib/MainWindow.py:246 msgid "Make a pretty drawing" msgstr "Добавить мысли" #: ../labyrinth_lib/MainWindow.py:248 msgid "Use _Curves" msgstr "" #: ../labyrinth_lib/MainWindow.py:249 msgid "Use curves as links" msgstr "" #: ../labyrinth_lib/MainWindow.py:250 msgid "Use _Lines" msgstr "" #: ../labyrinth_lib/MainWindow.py:251 msgid "Use straight lines as links" msgstr "" #: ../labyrinth_lib/MainWindow.py:253 msgid "_Extended Information" msgstr "" #: ../labyrinth_lib/MainWindow.py:254 #, fuzzy msgid "Show extended information for thoughts" msgstr "Просмотреть подробности о мыслях" #: ../labyrinth_lib/MainWindow.py:255 msgid "_Main" msgstr "" #: ../labyrinth_lib/MainWindow.py:256 msgid "Show main toolbar" msgstr "" #: ../labyrinth_lib/MainWindow.py:257 msgid "_Format" msgstr "" #: ../labyrinth_lib/MainWindow.py:258 msgid "Show format toolbar" msgstr "" #: ../labyrinth_lib/MainWindow.py:536 msgid "Save File As" msgstr "" #: ../labyrinth_lib/MainWindow.py:630 #, fuzzy msgid "All Files" msgstr "Файл" #: ../labyrinth_lib/MainWindow.py:631 msgid "PNG Image (*.png)" msgstr "" #: ../labyrinth_lib/MainWindow.py:632 msgid "JPEG Image (*.jpg, *.jpeg)" msgstr "" #: ../labyrinth_lib/MainWindow.py:633 msgid "SVG Vector Image (*.svg)" msgstr "" #: ../labyrinth_lib/MainWindow.py:634 msgid "PDF Portable Document (*.pdf)" msgstr "" #: ../labyrinth_lib/MainWindow.py:670 msgid "Unknown file format" msgstr "Неизвестный формат файлов" #: ../labyrinth_lib/MainWindow.py:671 #, fuzzy, python-format msgid "" "The file type '%s' is unsupported. Please use the suffix '.png', '.jpg' or " "'.svg'." msgstr "" "Формат файлов '%s' не поддерживается. Используйте суффикс '.png' или '.jpg'" #: ../labyrinth_lib/ResourceThought.py:128 #, fuzzy msgid "Edit Text" msgstr "_Правка" #: ../labyrinth_lib/ResourceThought.py:133 #, fuzzy msgid "Edit URI" msgstr "_Правка" #: ../labyrinth_lib/DrawingThought.py:65 #, python-format msgid "Drawing #%d" msgstr "Рисунок #%d" #: ../data/labyrinth.glade:7 msgid "Export Map as Image" msgstr "Экспорт карты как изображения" #: ../data/labyrinth.glade:87 msgid "Complete Map" msgstr "Карта полностью" #: ../data/labyrinth.glade:101 msgid "Visible Area" msgstr "Видимая область" #: ../data/labyrinth.glade:157 msgid "Width" msgstr "Ширина" #: ../data/labyrinth.glade:172 msgid "Height" msgstr "Высота" #: ../data/labyrinth.glade:226 msgid "Export Map" msgstr "Экспорт карты" #: ../data/labyrinth.glade:245 msgid "Labyrinth Maps" msgstr "Ассоциативные карты в Labyrinth" #: ../data/labyrinth.glade:259 msgid "_File" msgstr "_Файл" #: ../data/labyrinth.glade:299 msgid "Import..." msgstr "" #: ../data/labyrinth.glade:329 msgid "_Help" msgstr "_Справка" #: ../data/labyrinth.glade:765 msgid "URL" msgstr "" #: ../data/labyrinth.glade:806 msgid "Align Left" msgstr "" #: ../data/labyrinth.glade:825 msgid "Align Right" msgstr "" #: ../data/labyrinth.glade:844 msgid "Align Vertical Center" msgstr "" #: ../data/labyrinth.glade:863 msgid "Align Top" msgstr "" #: ../data/labyrinth.glade:882 msgid "Align Bottom" msgstr "" #: ../data/labyrinth.glade:901 msgid "Align Horizontal Center" msgstr "" #~ msgid "_Delete Selected Thoughts" #~ msgstr "_Удалить выбранные мысли" #~ msgid "Delete the selected element(s)" #~ msgstr "Удалить выбранные элементы" #~ msgid "_View Extended" #~ msgstr "_Просмотр подробностей" #~ msgid "Labyrinth Mind-mapping" #~ msgstr "Ассоциативные карты в Labyrinth" #~ msgid "Map your mind" #~ msgstr "Упорядочьте свои знания" #~ msgid "Mind-mapping" #~ msgstr "Создание ассоциативных карт" labyrinth-0.6/po/sv.po000066400000000000000000000166611204476542500150040ustar00rootroot00000000000000# SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. # msgid "" msgstr "" "Project-Id-Version: Labyrinth 0.3\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2012-09-23 18:55+0100\n" "PO-Revision-Date: 2006-11-07 18:26+0100\n" "Last-Translator: Robin Sonefors \n" "Language-Team: \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1\n" "X-Poedit-Country: SWEDEN\n" #: ../labyrinth_lib/ImageThought.py:68 msgid "Choose image to insert" msgstr "Välj bild att infoga" #: ../labyrinth_lib/ImageThought.py:323 msgid "Error loading file" msgstr "Fel vid läsning av fil" #: ../labyrinth_lib/ImageThought.py:324 #, python-format msgid "%s could not be found. Associated thought will be empty." msgstr "%s kunde inte hittas. Dess tanke kommer att vara tom." #: ../labyrinth_lib/ImageThought.py:339 msgid "Change Image" msgstr "" #: ../labyrinth_lib/Browser.py:192 #, python-format msgid "Unable to display help: %s" msgstr "" #: ../labyrinth_lib/Browser.py:223 msgid "Translation by Don Scorgie" msgstr "" #: ../labyrinth_lib/Browser.py:245 #, fuzzy msgid "The map cannot be deleted right now. Is it open?" msgstr "Den här tankekartan går inte att ta bort nu. Är den öppen?" #: ../labyrinth_lib/Browser.py:247 msgid "The map has no associated filename." msgstr "Den här tankekartan har inget filnamn." #: ../labyrinth_lib/Browser.py:250 msgid "Cannot delete this map" msgstr "Kan inte ta bort den här tankekartan" #: ../labyrinth_lib/Browser.py:257 msgid "Do you really want to delete this Map?" msgstr "Vill du verkligen ta bort den här tankekartan?" #: ../labyrinth_lib/Browser.py:282 #, fuzzy msgid "Open File" msgstr "Arkiv" #: ../labyrinth_lib/Browser.py:286 msgid "MAPZ Compressed Map (*.mapz)" msgstr "" #: ../labyrinth_lib/Browser.py:317 msgid "Map Name" msgstr "Namn på tankekarta" #: ../labyrinth_lib/Browser.py:324 msgid "Last Modified" msgstr "" #: ../labyrinth_lib/Links.py:265 msgid "Choose Color" msgstr "" #: ../labyrinth_lib/Links.py:278 msgid "Set Color" msgstr "" #: ../labyrinth_lib/MainWindow.py:166 ../labyrinth_lib/MainWindow.py:481 #, fuzzy msgid "Untitled Map" msgstr "Namnlös tankekarta %d" #: ../labyrinth_lib/MainWindow.py:213 msgid "File" msgstr "Arkiv" #: ../labyrinth_lib/MainWindow.py:214 msgid "Export as Image" msgstr "Exportera som bild" #: ../labyrinth_lib/MainWindow.py:215 msgid "Export your map as an image" msgstr "Exportera din tankekarta som en bild" #: ../labyrinth_lib/MainWindow.py:216 #, fuzzy msgid "Export Map..." msgstr "Exportera tankekarta" #: ../labyrinth_lib/MainWindow.py:217 #, fuzzy msgid "Export your map as XML" msgstr "Exportera din tankekarta som en bild" #: ../labyrinth_lib/MainWindow.py:219 msgid "Close the current window" msgstr "Stäng det här fönstret" #: ../labyrinth_lib/MainWindow.py:220 msgid "_Edit" msgstr "_Redigera" #: ../labyrinth_lib/MainWindow.py:221 msgid "_View" msgstr "" #: ../labyrinth_lib/MainWindow.py:222 msgid "_Toolbar" msgstr "" #: ../labyrinth_lib/MainWindow.py:231 #, fuzzy msgid "Link Thoughts" msgstr "(Av)Länka tankar" #: ../labyrinth_lib/MainWindow.py:232 #, fuzzy msgid "Link the selected thoughts" msgstr "(Av)Länka de valda tankarna" #: ../labyrinth_lib/MainWindow.py:233 msgid "_Mode" msgstr "_Läge" #: ../labyrinth_lib/MainWindow.py:241 msgid "_Edit Mode" msgstr "_Redigeringsläge" #: ../labyrinth_lib/MainWindow.py:242 msgid "Turn on edit mode" msgstr "Aktivera redigeringsläge" #: ../labyrinth_lib/MainWindow.py:243 msgid "_Add Image" msgstr "_Lägg till bild" #: ../labyrinth_lib/MainWindow.py:244 msgid "Add an image to selected thought" msgstr "Lägg till en bild till den valda tanken" #: ../labyrinth_lib/MainWindow.py:245 msgid "_Drawing Mode" msgstr "_Ritläge" #: ../labyrinth_lib/MainWindow.py:246 msgid "Make a pretty drawing" msgstr "Rita en fin bild" #: ../labyrinth_lib/MainWindow.py:248 msgid "Use _Curves" msgstr "" #: ../labyrinth_lib/MainWindow.py:249 msgid "Use curves as links" msgstr "" #: ../labyrinth_lib/MainWindow.py:250 msgid "Use _Lines" msgstr "" #: ../labyrinth_lib/MainWindow.py:251 msgid "Use straight lines as links" msgstr "" #: ../labyrinth_lib/MainWindow.py:253 msgid "_Extended Information" msgstr "" #: ../labyrinth_lib/MainWindow.py:254 #, fuzzy msgid "Show extended information for thoughts" msgstr "Visa mer information om tankar" #: ../labyrinth_lib/MainWindow.py:255 msgid "_Main" msgstr "" #: ../labyrinth_lib/MainWindow.py:256 msgid "Show main toolbar" msgstr "" #: ../labyrinth_lib/MainWindow.py:257 msgid "_Format" msgstr "" #: ../labyrinth_lib/MainWindow.py:258 msgid "Show format toolbar" msgstr "" #: ../labyrinth_lib/MainWindow.py:536 msgid "Save File As" msgstr "" #: ../labyrinth_lib/MainWindow.py:630 #, fuzzy msgid "All Files" msgstr "Arkiv" #: ../labyrinth_lib/MainWindow.py:631 msgid "PNG Image (*.png)" msgstr "" #: ../labyrinth_lib/MainWindow.py:632 msgid "JPEG Image (*.jpg, *.jpeg)" msgstr "" #: ../labyrinth_lib/MainWindow.py:633 msgid "SVG Vector Image (*.svg)" msgstr "" #: ../labyrinth_lib/MainWindow.py:634 msgid "PDF Portable Document (*.pdf)" msgstr "" #: ../labyrinth_lib/MainWindow.py:670 msgid "Unknown file format" msgstr "Okänt filformat" #: ../labyrinth_lib/MainWindow.py:671 #, fuzzy, python-format msgid "" "The file type '%s' is unsupported. Please use the suffix '.png', '.jpg' or " "'.svg'." msgstr "" "Filtypen \"%s\" stödjs inte. Använd filändelsen \".png\" eller \".jpg\"" #: ../labyrinth_lib/ResourceThought.py:128 #, fuzzy msgid "Edit Text" msgstr "_Redigeringsläge" #: ../labyrinth_lib/ResourceThought.py:133 #, fuzzy msgid "Edit URI" msgstr "_Redigera" #: ../labyrinth_lib/DrawingThought.py:65 #, python-format msgid "Drawing #%d" msgstr "Ritning #%d" #: ../data/labyrinth.glade:7 msgid "Export Map as Image" msgstr "Exportera tankekarta som bild" #: ../data/labyrinth.glade:87 msgid "Complete Map" msgstr "Hela tankekartan" #: ../data/labyrinth.glade:101 msgid "Visible Area" msgstr "Synligt område" #: ../data/labyrinth.glade:157 msgid "Width" msgstr "Bredd" #: ../data/labyrinth.glade:172 msgid "Height" msgstr "Höjd" #: ../data/labyrinth.glade:226 msgid "Export Map" msgstr "Exportera tankekarta" #: ../data/labyrinth.glade:245 msgid "Labyrinth Maps" msgstr "Labyrinths tankekartor" #: ../data/labyrinth.glade:259 msgid "_File" msgstr "_Arkiv" #: ../data/labyrinth.glade:299 msgid "Import..." msgstr "" #: ../data/labyrinth.glade:329 msgid "_Help" msgstr "_Hjälp" #: ../data/labyrinth.glade:765 msgid "URL" msgstr "" #: ../data/labyrinth.glade:806 msgid "Align Left" msgstr "" #: ../data/labyrinth.glade:825 msgid "Align Right" msgstr "" #: ../data/labyrinth.glade:844 msgid "Align Vertical Center" msgstr "" #: ../data/labyrinth.glade:863 msgid "Align Top" msgstr "" #: ../data/labyrinth.glade:882 msgid "Align Bottom" msgstr "" #: ../data/labyrinth.glade:901 msgid "Align Horizontal Center" msgstr "" #~ msgid "_Delete Selected Thoughts" #~ msgstr "_Ta bort valda tankar" #~ msgid "Delete the selected element(s)" #~ msgstr "Ta bort det valda elementet/de valda elementen" #~ msgid "_View Extended" #~ msgstr "_Visa mer information" #~ msgid "Labyrinth Mind-mapping" #~ msgstr "Tankekarteprogrammet Labyrinth" #~ msgid "Map your mind" #~ msgstr "Kartlägg dina tankar" #~ msgid "Mind-mapping" #~ msgstr "Tankekartor" labyrinth-0.6/po/zh_CN.po000066400000000000000000000164641204476542500153560ustar00rootroot00000000000000# # jiero , 2011. # msgid "" msgstr "" "Project-Id-Version: 0.5\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2012-09-23 18:55+0100\n" "PO-Revision-Date: 2011-05-30 10:00+1000\n" "Last-Translator: jiero \n" "Language-Team: Simplified Chinese \n" "Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8-bit\n" "Plural-Forms: nplurals=1; plural=0\n" #: ../labyrinth_lib/ImageThought.py:68 msgid "Choose image to insert" msgstr "选择图片插入" #: ../labyrinth_lib/ImageThought.py:323 msgid "Error loading file" msgstr "读取文件错误" #: ../labyrinth_lib/ImageThought.py:324 #, python-format msgid "%s could not be found. Associated thought will be empty." msgstr "%s 无法找到。相关线索将被清空。" #: ../labyrinth_lib/ImageThought.py:339 msgid "Change Image" msgstr "改变图像" #: ../labyrinth_lib/Browser.py:192 #, python-format msgid "Unable to display help: %s" msgstr "无法显示帮助 %s" #: ../labyrinth_lib/Browser.py:223 msgid "Translation by Don Scorgie" msgstr "简体翻译 来自 jiero" #: ../labyrinth_lib/Browser.py:245 msgid "The map cannot be deleted right now. Is it open?" msgstr "无法删除。或许正在编辑?" #: ../labyrinth_lib/Browser.py:247 msgid "The map has no associated filename." msgstr "没有对应的文件名。" #: ../labyrinth_lib/Browser.py:250 msgid "Cannot delete this map" msgstr "无法删除" #: ../labyrinth_lib/Browser.py:257 msgid "Do you really want to delete this Map?" msgstr "确定删除此图?" #: ../labyrinth_lib/Browser.py:282 msgid "Open File" msgstr "打开文件" #: ../labyrinth_lib/Browser.py:286 msgid "MAPZ Compressed Map (*.mapz)" msgstr "MAPZ 压缩(*.mapz)" #: ../labyrinth_lib/Browser.py:317 msgid "Map Name" msgstr "名称" #: ../labyrinth_lib/Browser.py:324 msgid "Last Modified" msgstr "最后修改" #: ../labyrinth_lib/Links.py:265 msgid "Choose Color" msgstr "" #: ../labyrinth_lib/Links.py:278 msgid "Set Color" msgstr "" #: ../labyrinth_lib/MainWindow.py:166 ../labyrinth_lib/MainWindow.py:481 msgid "Untitled Map" msgstr "未命名" #: ../labyrinth_lib/MainWindow.py:213 msgid "File" msgstr "文件" #: ../labyrinth_lib/MainWindow.py:214 msgid "Export as Image" msgstr "导出图片" #: ../labyrinth_lib/MainWindow.py:215 msgid "Export your map as an image" msgstr "作为图片导出" #: ../labyrinth_lib/MainWindow.py:216 msgid "Export Map..." msgstr "导出" #: ../labyrinth_lib/MainWindow.py:217 msgid "Export your map as XML" msgstr "导出为XML" #: ../labyrinth_lib/MainWindow.py:219 msgid "Close the current window" msgstr "关闭当前窗口" #: ../labyrinth_lib/MainWindow.py:220 msgid "_Edit" msgstr "编辑(_E)" #: ../labyrinth_lib/MainWindow.py:221 msgid "_View" msgstr "查看(_V)" #: ../labyrinth_lib/MainWindow.py:222 msgid "_Toolbar" msgstr "工具栏(_T)" #: ../labyrinth_lib/MainWindow.py:231 msgid "Link Thoughts" msgstr "链接线索" #: ../labyrinth_lib/MainWindow.py:232 msgid "Link the selected thoughts" msgstr "链接选中的线索" #: ../labyrinth_lib/MainWindow.py:233 msgid "_Mode" msgstr "模式(_M)" #: ../labyrinth_lib/MainWindow.py:241 msgid "_Edit Mode" msgstr "编辑模式(_E)" #: ../labyrinth_lib/MainWindow.py:242 msgid "Turn on edit mode" msgstr "切至编辑模式" #: ../labyrinth_lib/MainWindow.py:243 msgid "_Add Image" msgstr "添加图片(_A)" #: ../labyrinth_lib/MainWindow.py:244 msgid "Add an image to selected thought" msgstr "添加图片到选中的线索" #: ../labyrinth_lib/MainWindow.py:245 msgid "_Drawing Mode" msgstr "描绘模式(_D)" #: ../labyrinth_lib/MainWindow.py:246 msgid "Make a pretty drawing" msgstr "绘制" #: ../labyrinth_lib/MainWindow.py:248 msgid "Use _Curves" msgstr "使用曲线(_C)" #: ../labyrinth_lib/MainWindow.py:249 msgid "Use curves as links" msgstr "使用曲线链接" #: ../labyrinth_lib/MainWindow.py:250 msgid "Use _Lines" msgstr "使用直线(_L)" #: ../labyrinth_lib/MainWindow.py:251 msgid "Use straight lines as links" msgstr "使用直线链接" #: ../labyrinth_lib/MainWindow.py:253 msgid "_Extended Information" msgstr "扩展信息(_E)" #: ../labyrinth_lib/MainWindow.py:254 msgid "Show extended information for thoughts" msgstr "显示线索相关的补充信息" #: ../labyrinth_lib/MainWindow.py:255 msgid "_Main" msgstr "主栏(_M)" #: ../labyrinth_lib/MainWindow.py:256 msgid "Show main toolbar" msgstr "显示主工具栏" #: ../labyrinth_lib/MainWindow.py:257 msgid "_Format" msgstr "格式(_F)" #: ../labyrinth_lib/MainWindow.py:258 msgid "Show format toolbar" msgstr "显示格式工具栏" #: ../labyrinth_lib/MainWindow.py:536 msgid "Save File As" msgstr "文件保存为" #: ../labyrinth_lib/MainWindow.py:630 msgid "All Files" msgstr "所有文件" #: ../labyrinth_lib/MainWindow.py:631 msgid "PNG Image (*.png)" msgstr "PNG (*.png)" #: ../labyrinth_lib/MainWindow.py:632 msgid "JPEG Image (*.jpg, *.jpeg)" msgstr "JPEG (*.jpg, *.jpeg)" #: ../labyrinth_lib/MainWindow.py:633 msgid "SVG Vector Image (*.svg)" msgstr "SVG (*.svg)" #: ../labyrinth_lib/MainWindow.py:634 msgid "PDF Portable Document (*.pdf)" msgstr "PDF (*.pdf)" #: ../labyrinth_lib/MainWindow.py:670 msgid "Unknown file format" msgstr "未知文件格式" #: ../labyrinth_lib/MainWindow.py:671 #, python-format msgid "" "The file type '%s' is unsupported. Please use the suffix '.png', '.jpg' or " "'.svg'." msgstr "文件类型'%s'无法使用。请添加'.png'或'.jpg'或'.svg'。" #: ../labyrinth_lib/ResourceThought.py:128 #, fuzzy msgid "Edit Text" msgstr "编辑模式(_E)" #: ../labyrinth_lib/ResourceThought.py:133 #, fuzzy msgid "Edit URI" msgstr "编辑(_E)" #: ../labyrinth_lib/DrawingThought.py:65 #, python-format msgid "Drawing #%d" msgstr "绘图 #%d" #: ../data/labyrinth.glade:7 msgid "Export Map as Image" msgstr "作为图片导出" #: ../data/labyrinth.glade:87 msgid "Complete Map" msgstr "完整视图" #: ../data/labyrinth.glade:101 msgid "Visible Area" msgstr "可视区域" #: ../data/labyrinth.glade:157 msgid "Width" msgstr "宽度" #: ../data/labyrinth.glade:172 msgid "Height" msgstr "高度" #: ../data/labyrinth.glade:226 msgid "Export Map" msgstr "导出" #: ../data/labyrinth.glade:245 msgid "Labyrinth Maps" msgstr "Labyrinth 图" #: ../data/labyrinth.glade:259 msgid "_File" msgstr "文件(_F)" #: ../data/labyrinth.glade:299 msgid "Import..." msgstr "导入..." #: ../data/labyrinth.glade:329 msgid "_Help" msgstr "帮助(_H)" #: ../data/labyrinth.glade:765 msgid "URL" msgstr "URL" #: ../data/labyrinth.glade:806 msgid "Align Left" msgstr "对齐左边" #: ../data/labyrinth.glade:825 msgid "Align Right" msgstr "对齐右边" #: ../data/labyrinth.glade:844 msgid "Align Vertical Center" msgstr "对齐垂直中心" #: ../data/labyrinth.glade:863 msgid "Align Top" msgstr "对齐顶部" #: ../data/labyrinth.glade:882 msgid "Align Bottom" msgstr "对齐底部" #: ../data/labyrinth.glade:901 msgid "Align Horizontal Center" msgstr "中心对齐" #~ msgid "_Outline" #~ msgstr "轮廓(_O)" #~ msgid "Show outline of thought hierarchy" #~ msgstr "显示线索框架的优先级" #~ msgid "Thoughts" #~ msgstr "想法" #~ msgid "gtk-help" #~ msgstr "gtk-help" #~ msgid "Labyrinth Mind-mapping" #~ msgstr "Labyrinth 思维导图" #~ msgid "Map your mind" #~ msgstr "绘画思维的节点" #~ msgid "Mind-mapping" #~ msgstr "思维导图" labyrinth-0.6/setup.py000066400000000000000000000013061204476542500150760ustar00rootroot00000000000000from distutils.core import setup from labyrinth_lib import __version__ setup(name='Labyrinth', version=__version__, description='', author='Labyrinth is a lightweight mind-mapping tool', author_email='Don@scorgie.org', url='http://people.gnome.org/~dscorgie/labyrinth.html', packages=['labyrinth_lib'], scripts=['labyrinth'], data_files=[('share/labyrinth', ['data/labyrinth.glade', 'data/labyrinth-ui.xml'])], requires=['PyGTK'], classifiers = [ 'Environment :: X11 Applications :: GTK', 'Intended Audience :: End Users/Desktop', 'License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)', ] )